aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap13
-rw-r--r--Documentation/ABI/testing/sysfs-class-pwm9
-rw-r--r--Documentation/DMA-API.txt33
-rw-r--r--Documentation/DMA-attributes.txt2
-rw-r--r--Documentation/DocBook/Makefile31
-rw-r--r--Documentation/DocBook/media/.gitignore1
-rw-r--r--Documentation/DocBook/media/Makefile427
-rw-r--r--Documentation/DocBook/media/bayer.png.b64171
-rw-r--r--Documentation/DocBook/media/constraints.png.b6459
-rw-r--r--Documentation/DocBook/media/crop.gif.b64105
-rw-r--r--Documentation/DocBook/media/dvb/.gitignore1
-rw-r--r--Documentation/DocBook/media/dvb/audio.xml1314
-rw-r--r--Documentation/DocBook/media/dvb/ca.xml582
-rw-r--r--Documentation/DocBook/media/dvb/demux.xml1162
-rw-r--r--Documentation/DocBook/media/dvb/dvbapi.xml156
-rw-r--r--Documentation/DocBook/media/dvb/dvbproperty.xml1680
-rw-r--r--Documentation/DocBook/media/dvb/dvbstb.pdfbin1881 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/dvb/examples.xml367
-rw-r--r--Documentation/DocBook/media/dvb/fe-diseqc-recv-slave-reply.xml78
-rw-r--r--Documentation/DocBook/media/dvb/fe-diseqc-reset-overload.xml51
-rw-r--r--Documentation/DocBook/media/dvb/fe-diseqc-send-burst.xml89
-rw-r--r--Documentation/DocBook/media/dvb/fe-diseqc-send-master-cmd.xml72
-rw-r--r--Documentation/DocBook/media/dvb/fe-enable-high-lnb-voltage.xml61
-rw-r--r--Documentation/DocBook/media/dvb/fe-get-info.xml266
-rw-r--r--Documentation/DocBook/media/dvb/fe-get-property.xml81
-rw-r--r--Documentation/DocBook/media/dvb/fe-read-status.xml107
-rw-r--r--Documentation/DocBook/media/dvb/fe-set-frontend-tune-mode.xml64
-rw-r--r--Documentation/DocBook/media/dvb/fe-set-tone.xml91
-rw-r--r--Documentation/DocBook/media/dvb/fe-set-voltage.xml69
-rw-r--r--Documentation/DocBook/media/dvb/frontend.xml269
-rw-r--r--Documentation/DocBook/media/dvb/frontend_legacy_api.xml654
-rw-r--r--Documentation/DocBook/media/dvb/intro.xml211
-rw-r--r--Documentation/DocBook/media/dvb/net.xml238
-rw-r--r--Documentation/DocBook/media/dvb/video.xml1968
-rw-r--r--Documentation/DocBook/media/dvbstb.png.b64398
-rw-r--r--Documentation/DocBook/media/fieldseq_bt.gif.b64447
-rw-r--r--Documentation/DocBook/media/fieldseq_tb.gif.b64445
-rw-r--r--Documentation/DocBook/media/nv12mt.gif.b6437
-rw-r--r--Documentation/DocBook/media/nv12mt_example.gif.b64121
-rw-r--r--Documentation/DocBook/media/pipeline.png.b64213
-rw-r--r--Documentation/DocBook/media/selection.png.b64206
-rw-r--r--Documentation/DocBook/media/typical_media_device.svg28
-rw-r--r--Documentation/DocBook/media/v4l/.gitignore1
-rw-r--r--Documentation/DocBook/media/v4l/biblio.xml381
-rw-r--r--Documentation/DocBook/media/v4l/capture.c.xml659
-rw-r--r--Documentation/DocBook/media/v4l/cec-api.xml75
-rw-r--r--Documentation/DocBook/media/v4l/cec-func-close.xml64
-rw-r--r--Documentation/DocBook/media/v4l/cec-func-ioctl.xml78
-rw-r--r--Documentation/DocBook/media/v4l/cec-func-open.xml104
-rw-r--r--Documentation/DocBook/media/v4l/cec-func-poll.xml94
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml151
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml329
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml86
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml202
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml255
-rw-r--r--Documentation/DocBook/media/v4l/cec-ioc-receive.xml274
-rw-r--r--Documentation/DocBook/media/v4l/common.xml1102
-rw-r--r--Documentation/DocBook/media/v4l/compat.xml2723
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml5505
-rw-r--r--Documentation/DocBook/media/v4l/crop.pdfbin5846 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/dev-capture.xml110
-rw-r--r--Documentation/DocBook/media/v4l/dev-codec.xml27
-rw-r--r--Documentation/DocBook/media/v4l/dev-effect.xml17
-rw-r--r--Documentation/DocBook/media/v4l/dev-event.xml43
-rw-r--r--Documentation/DocBook/media/v4l/dev-osd.xml149
-rw-r--r--Documentation/DocBook/media/v4l/dev-output.xml106
-rw-r--r--Documentation/DocBook/media/v4l/dev-overlay.xml368
-rw-r--r--Documentation/DocBook/media/v4l/dev-radio.xml49
-rw-r--r--Documentation/DocBook/media/v4l/dev-raw-vbi.xml345
-rw-r--r--Documentation/DocBook/media/v4l/dev-rds.xml196
-rw-r--r--Documentation/DocBook/media/v4l/dev-sdr.xml126
-rw-r--r--Documentation/DocBook/media/v4l/dev-sliced-vbi.xml706
-rw-r--r--Documentation/DocBook/media/v4l/dev-subdev.xml478
-rw-r--r--Documentation/DocBook/media/v4l/dev-teletext.xml29
-rw-r--r--Documentation/DocBook/media/v4l/driver.xml200
-rw-r--r--Documentation/DocBook/media/v4l/fdl-appendix.xml671
-rw-r--r--Documentation/DocBook/media/v4l/fieldseq_bt.pdfbin9185 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/fieldseq_tb.pdfbin9173 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/func-close.xml62
-rw-r--r--Documentation/DocBook/media/v4l/func-ioctl.xml71
-rw-r--r--Documentation/DocBook/media/v4l/func-mmap.xml183
-rw-r--r--Documentation/DocBook/media/v4l/func-munmap.xml76
-rw-r--r--Documentation/DocBook/media/v4l/func-open.xml113
-rw-r--r--Documentation/DocBook/media/v4l/func-poll.xml142
-rw-r--r--Documentation/DocBook/media/v4l/func-read.xml181
-rw-r--r--Documentation/DocBook/media/v4l/func-select.xml130
-rw-r--r--Documentation/DocBook/media/v4l/func-write.xml128
-rw-r--r--Documentation/DocBook/media/v4l/gen-errors.xml77
-rw-r--r--Documentation/DocBook/media/v4l/io.xml1545
-rw-r--r--Documentation/DocBook/media/v4l/keytable.c.xml172
-rw-r--r--Documentation/DocBook/media/v4l/libv4l.xml160
-rw-r--r--Documentation/DocBook/media/v4l/lirc_device_interface.xml255
-rw-r--r--Documentation/DocBook/media/v4l/media-controller.xml105
-rw-r--r--Documentation/DocBook/media/v4l/media-func-close.xml59
-rw-r--r--Documentation/DocBook/media/v4l/media-func-ioctl.xml73
-rw-r--r--Documentation/DocBook/media/v4l/media-func-open.xml94
-rw-r--r--Documentation/DocBook/media/v4l/media-ioc-device-info.xml132
-rw-r--r--Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml180
-rw-r--r--Documentation/DocBook/media/v4l/media-ioc-enum-links.xml160
-rw-r--r--Documentation/DocBook/media/v4l/media-ioc-g-topology.xml391
-rw-r--r--Documentation/DocBook/media/v4l/media-ioc-setup-link.xml84
-rw-r--r--Documentation/DocBook/media/v4l/media-types.xml379
-rw-r--r--Documentation/DocBook/media/v4l/pipeline.pdfbin20276 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-grey.xml62
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-m420.xml139
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv12.xml143
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv12m.xml153
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml66
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv16.xml166
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv16m.xml170
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv24.xml121
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml937
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml236
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml83
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml67
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml44
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml47
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml44
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml46
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml40
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml67
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml67
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10.xml90
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml34
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml28
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml99
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb12.xml90
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb8.xml67
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-uv8.xml62
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-uyvy.xml120
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-vyuy.xml120
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y10.xml79
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y10b.xml43
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y12.xml79
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y12i.xml49
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y16-be.xml81
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y16.xml81
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y41p.xml149
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-y8i.xml80
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv410.xml133
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml147
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv420.xml149
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml162
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml166
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml153
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml177
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yuyv.xml120
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-yvyu.xml120
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-z16.xml81
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt.xml2003
-rw-r--r--Documentation/DocBook/media/v4l/planar-apis.xml62
-rw-r--r--Documentation/DocBook/media/v4l/remote_controllers.xml320
-rw-r--r--Documentation/DocBook/media/v4l/selection-api.xml317
-rw-r--r--Documentation/DocBook/media/v4l/selections-common.xml180
-rw-r--r--Documentation/DocBook/media/v4l/subdev-formats.xml4040
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia614
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg63
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-full.dia1588
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-full.svg163
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia1152
-rw-r--r--Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg116
-rw-r--r--Documentation/DocBook/media/v4l/v4l2.xml728
-rw-r--r--Documentation/DocBook/media/v4l/v4l2grab.c.xml164
-rw-r--r--Documentation/DocBook/media/v4l/vbi_525.pdfbin3395 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/vbi_625.pdfbin3683 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/vbi_hsync.pdfbin7405 -> 0 bytes
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-create-bufs.xml158
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-cropcap.xml166
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml207
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml227
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml259
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dqevent.xml471
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml210
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml197
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml128
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml159
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-frameintervals.xml260
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml265
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml175
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enumaudio.xml76
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enumaudioout.xml79
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enuminput.xml316
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enumoutput.xml201
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-enumstd.xml389
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-expbuf.xml205
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-audio.xml172
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-audioout.xml138
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-crop.xml129
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml133
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml343
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-edid.xml173
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml189
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml456
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml459
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-fmt.xml204
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-frequency.xml148
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-input.xml83
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml175
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-modulator.xml252
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-output.xml85
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-parm.xml314
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-priority.xml135
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-selection.xml233
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-sliced-vbi-cap.xml255
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-std.xml98
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-tuner.xml594
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-log-status.xml41
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-overlay.xml74
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml88
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-qbuf.xml202
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml115
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-querybuf.xml106
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-querycap.xml350
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-queryctrl.xml661
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-querystd.xml85
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-reqbufs.xml137
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml188
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-streamon.xml136
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml151
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml153
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml118
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml158
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml177
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml135
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml159
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml130
-rw-r--r--Documentation/DocBook/media/vbi_525.gif.b6484
-rw-r--r--Documentation/DocBook/media/vbi_625.gif.b6490
-rw-r--r--Documentation/DocBook/media/vbi_hsync.gif.b6443
-rw-r--r--Documentation/DocBook/media_api.tmpl121
-rw-r--r--Documentation/Makefile.sphinx5
-rw-r--r--Documentation/binfmt_misc.txt7
-rw-r--r--Documentation/block/biodoc.txt4
-rw-r--r--Documentation/block/queue-sysfs.txt18
-rw-r--r--Documentation/cgroup-v1/cgroups.txt4
-rw-r--r--Documentation/cgroup-v1/cpusets.txt2
-rw-r--r--Documentation/cgroup-v1/memcg_test.txt4
-rw-r--r--Documentation/device-mapper/dm-flakey.txt2
-rw-r--r--Documentation/devicetree/bindings/input/rotary-encoder.txt4
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt36
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt33
-rw-r--r--Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt21
-rw-r--r--Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt23
-rw-r--r--Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt12
-rw-r--r--Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt1
-rw-r--r--Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt18
-rw-r--r--Documentation/devicetree/bindings/regulator/pwm-regulator.txt19
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/ramoops.txt (renamed from Documentation/devicetree/bindings/misc/ramoops.txt)8
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt1
-rw-r--r--Documentation/filesystems/Locking2
-rw-r--r--Documentation/filesystems/porting7
-rw-r--r--Documentation/filesystems/tmpfs.txt2
-rw-r--r--Documentation/filesystems/vfs.txt2
-rw-r--r--Documentation/gpu/kms-properties.csv1
-rw-r--r--Documentation/kernel-parameters.txt13
-rw-r--r--Documentation/kernel-per-CPU-kthreads.txt2
-rw-r--r--Documentation/module-signing.txt6
-rw-r--r--Documentation/ramoops.txt38
-rw-r--r--Documentation/scheduler/sched-deadline.txt2
-rw-r--r--Documentation/scheduler/sched-design-CFS.txt2
-rw-r--r--Documentation/scheduler/sched-rt-group.txt2
-rw-r--r--Documentation/virtual/kvm/api.txt53
-rw-r--r--Documentation/vm/numa4
-rw-r--r--Documentation/vm/numa_memory_policy.txt2
-rw-r--r--Documentation/vm/page_migration2
-rw-r--r--Documentation/vm/unevictable-lru.txt2
-rw-r--r--Documentation/x86/x86_64/fake-numa-for-cpusets4
-rw-r--r--MAINTAINERS65
-rw-r--r--Makefile13
-rw-r--r--arch/Kconfig9
-rw-r--r--arch/alpha/include/asm/dma-mapping.h2
-rw-r--r--arch/alpha/include/asm/rtc.h1
-rw-r--r--arch/alpha/kernel/core_marvel.c1
-rw-r--r--arch/alpha/kernel/pci-noop.c2
-rw-r--r--arch/alpha/kernel/pci_iommu.c12
-rw-r--r--arch/alpha/kernel/rtc.c6
-rw-r--r--arch/arc/mm/dma.c12
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boot/dts/arm-realview-pbx-a9.dts9
-rw-r--r--arch/arm/boot/dts/integratorap.dts2
-rw-r--r--arch/arm/boot/dts/integratorcp.dts2
-rw-r--r--arch/arm/boot/dts/keystone.dtsi8
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts4
-rw-r--r--arch/arm/common/dmabounce.c4
-rw-r--r--arch/arm/configs/aspeed_g4_defconfig2
-rw-r--r--arch/arm/configs/aspeed_g5_defconfig2
-rw-r--r--arch/arm/include/asm/dma-mapping.h13
-rw-r--r--arch/arm/include/asm/uaccess.h11
-rw-r--r--arch/arm/include/asm/xen/page-coherent.h16
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c8
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
-rw-r--r--arch/arm/kvm/Kconfig2
-rw-r--r--arch/arm/kvm/Makefile1
-rw-r--r--arch/arm/kvm/arm.c6
-rw-r--r--arch/arm/kvm/irq.h19
-rw-r--r--arch/arm/mach-clps711x/Kconfig2
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c2
-rw-r--r--arch/arm/mach-mvebu/Makefile3
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c2
-rw-r--r--arch/arm/mach-oxnas/Kconfig2
-rw-r--r--arch/arm/mach-pxa/cm-x270.c2
-rw-r--r--arch/arm/mach-pxa/cm-x300.c2
-rw-r--r--arch/arm/mach-pxa/corgi.c1
-rw-r--r--arch/arm/mach-pxa/em-x270.c2
-rw-r--r--arch/arm/mach-pxa/spitz.c1
-rw-r--r--arch/arm/mach-realview/Makefile3
-rw-r--r--arch/arm/mach-s5pv210/Makefile2
-rw-r--r--arch/arm/mach-shmobile/platsmp.c3
-rw-r--r--arch/arm/mm/dma-mapping.c129
-rw-r--r--arch/arm/xen/mm.c8
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/Kconfig.platforms4
-rw-r--r--arch/arm64/Makefile2
-rw-r--r--arch/arm64/boot/dts/exynos/exynos7-espresso.dts3
-rw-r--r--arch/arm64/configs/defconfig53
-rw-r--r--arch/arm64/include/asm/elf.h1
-rw-r--r--arch/arm64/include/asm/kprobes.h2
-rw-r--r--arch/arm64/include/asm/pgtable.h17
-rw-r--r--arch/arm64/include/asm/uaccess.h15
-rw-r--r--arch/arm64/include/uapi/asm/auxvec.h2
-rw-r--r--arch/arm64/kernel/entry.S7
-rw-r--r--arch/arm64/kernel/head.S21
-rw-r--r--arch/arm64/kernel/hibernate.c82
-rw-r--r--arch/arm64/kernel/probes/kprobes.c31
-rw-r--r--arch/arm64/kernel/smp.c8
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S13
-rw-r--r--arch/arm64/kvm/Kconfig2
-rw-r--r--arch/arm64/kvm/Makefile1
-rw-r--r--arch/arm64/kvm/inject_fault.c12
-rw-r--r--arch/arm64/kvm/irq.h19
-rw-r--r--arch/arm64/mm/dma-mapping.c66
-rw-r--r--arch/arm64/mm/fault.c14
-rw-r--r--arch/arm64/mm/mmu.c8
-rw-r--r--arch/avr32/mm/dma-coherent.c12
-rw-r--r--arch/blackfin/kernel/dma-mapping.c8
-rw-r--r--arch/c6x/include/asm/dma-mapping.h4
-rw-r--r--arch/c6x/kernel/dma.c9
-rw-r--r--arch/c6x/mm/dma-coherent.c4
-rw-r--r--arch/cris/arch-v32/drivers/pci/dma.c9
-rw-r--r--arch/frv/include/asm/mc146818rtc.h16
-rw-r--r--arch/frv/mb93090-mb00/pci-dma-nommu.c8
-rw-r--r--arch/frv/mb93090-mb00/pci-dma.c9
-rw-r--r--arch/h8300/include/asm/io.h2
-rw-r--r--arch/h8300/include/asm/mc146818rtc.h9
-rw-r--r--arch/h8300/kernel/dma.c8
-rw-r--r--arch/hexagon/include/asm/dma-mapping.h1
-rw-r--r--arch/hexagon/kernel/dma.c8
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/hp/common/sba_iommu.c22
-rw-r--r--arch/ia64/include/asm/machvec.h1
-rw-r--r--arch/ia64/include/asm/mc146818rtc.h10
-rw-r--r--arch/ia64/include/asm/uaccess.h18
-rw-r--r--arch/ia64/kernel/pci-swiotlb.c4
-rw-r--r--arch/ia64/sn/pci/pci_dma.c22
-rw-r--r--arch/m68k/amiga/config.c1
-rw-r--r--arch/m68k/apollo/config.c1
-rw-r--r--arch/m68k/bvme6000/config.c1
-rw-r--r--arch/m68k/hp300/config.c2
-rw-r--r--arch/m68k/include/asm/flat.h13
-rw-r--r--arch/m68k/include/asm/processor.h15
-rw-r--r--arch/m68k/include/asm/rtc.h79
-rw-r--r--arch/m68k/kernel/dma.c12
-rw-r--r--arch/m68k/kernel/signal.c1
-rw-r--r--arch/m68k/kernel/time.c48
-rw-r--r--arch/m68k/mac/config.c3
-rw-r--r--arch/m68k/mac/misc.c1
-rw-r--r--arch/m68k/mvme147/config.c1
-rw-r--r--arch/m68k/mvme16x/config.c1
-rw-r--r--arch/m68k/q40/config.c2
-rw-r--r--arch/m68k/sun3/config.c1
-rw-r--r--arch/m68k/sun3/intersil.c2
-rw-r--r--arch/m68k/sun3x/time.c2
-rw-r--r--arch/metag/include/asm/cmpxchg_lnkget.h2
-rw-r--r--arch/metag/include/asm/metag_mem.h2
-rw-r--r--arch/metag/include/asm/metag_regs.h2
-rw-r--r--arch/metag/kernel/cachepart.c2
-rw-r--r--arch/metag/kernel/dma.c16
-rw-r--r--arch/metag/lib/divsi3.S4
-rw-r--r--arch/metag/mm/fault.c2
-rw-r--r--arch/metag/mm/init.c1
-rw-r--r--arch/microblaze/include/asm/dma-mapping.h1
-rw-r--r--arch/microblaze/kernel/dma.c12
-rw-r--r--arch/mips/Kconfig47
-rw-r--r--arch/mips/ath79/setup.c4
-rw-r--r--arch/mips/bmips/setup.c4
-rw-r--r--arch/mips/boot/compressed/decompress.c17
-rw-r--r--arch/mips/boot/compressed/head.S16
-rw-r--r--arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts20
-rw-r--r--arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts12
-rw-r--r--arch/mips/boot/tools/relocs_64.c19
-rw-r--r--arch/mips/cavium-octeon/dma-octeon.c8
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-bootmem.c2
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c22
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c14
-rw-r--r--arch/mips/cavium-octeon/octeon-platform.c125
-rw-r--r--arch/mips/cavium-octeon/setup.c20
-rw-r--r--arch/mips/cavium-octeon/smp.c1
-rw-r--r--arch/mips/cobalt/setup.c4
-rw-r--r--arch/mips/configs/ath25_defconfig119
-rw-r--r--arch/mips/configs/cavium_octeon_defconfig2
-rw-r--r--arch/mips/include/asm/bootinfo.h4
-rw-r--r--arch/mips/include/asm/dsemul.h92
-rw-r--r--arch/mips/include/asm/elf.h4
-rw-r--r--arch/mips/include/asm/fpu_emulator.h17
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/irq.h2
-rw-r--r--arch/mips/include/asm/mach-cavium-octeon/mangle-port.h42
-rw-r--r--arch/mips/include/asm/mips-cm.h2
-rw-r--r--arch/mips/include/asm/mmu.h9
-rw-r--r--arch/mips/include/asm/mmu_context.h6
-rw-r--r--arch/mips/include/asm/msa.h2
-rw-r--r--arch/mips/include/asm/page.h44
-rw-r--r--arch/mips/include/asm/pgtable.h16
-rw-r--r--arch/mips/include/asm/processor.h18
-rw-r--r--arch/mips/include/asm/r4kcache.h4
-rw-r--r--arch/mips/include/asm/seccomp.h4
-rw-r--r--arch/mips/include/asm/signal.h6
-rw-r--r--arch/mips/include/asm/smp.h4
-rw-r--r--arch/mips/include/asm/syscall.h2
-rw-r--r--arch/mips/include/asm/uaccess.h2
-rw-r--r--arch/mips/include/uapi/asm/auxvec.h2
-rw-r--r--arch/mips/jz4740/setup.c2
-rw-r--r--arch/mips/kernel/Makefile2
-rw-r--r--arch/mips/kernel/cevt-r4k.c7
-rw-r--r--arch/mips/kernel/cpu-bugs64.c6
-rw-r--r--arch/mips/kernel/csrc-r4k.c4
-rw-r--r--arch/mips/kernel/elf.c23
-rw-r--r--arch/mips/kernel/head.S21
-rw-r--r--arch/mips/kernel/mips-cm.c2
-rw-r--r--arch/mips/kernel/mips-r2-to-r6-emul.c42
-rw-r--r--arch/mips/kernel/pm-cps.c4
-rw-r--r--arch/mips/kernel/process.c14
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/segment.c13
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/kernel/signal.c18
-rw-r--r--arch/mips/kernel/signal32.c288
-rw-r--r--arch/mips/kernel/signal_o32.c285
-rw-r--r--arch/mips/kernel/smp-bmips.c1
-rw-r--r--arch/mips/kernel/smp-cps.c46
-rw-r--r--arch/mips/kernel/smp.c34
-rw-r--r--arch/mips/kernel/traps.c4
-rw-r--r--arch/mips/kernel/unaligned.c10
-rw-r--r--arch/mips/kernel/vdso.c10
-rw-r--r--arch/mips/kvm/emulate.c35
-rw-r--r--arch/mips/kvm/mmu.c68
-rw-r--r--arch/mips/lantiq/irq.c31
-rw-r--r--arch/mips/lantiq/prom.c4
-rw-r--r--arch/mips/loongson64/common/dma-swiotlb.c10
-rw-r--r--arch/mips/loongson64/loongson-3/hpet.c14
-rw-r--r--arch/mips/loongson64/loongson-3/smp.c1
-rw-r--r--arch/mips/math-emu/cp1emu.c14
-rw-r--r--arch/mips/math-emu/dsemul.c333
-rw-r--r--arch/mips/mm/c-r4k.c284
-rw-r--r--arch/mips/mm/dma-default.c20
-rw-r--r--arch/mips/mm/sc-debugfs.c4
-rw-r--r--arch/mips/mm/sc-rm7k.c2
-rw-r--r--arch/mips/mm/tlbex.c12
-rw-r--r--arch/mips/mm/uasm-mips.c2
-rw-r--r--arch/mips/mm/uasm.c6
-rw-r--r--arch/mips/mti-malta/malta-dtshim.c4
-rw-r--r--arch/mips/mti-malta/malta-memory.c2
-rw-r--r--arch/mips/mti-malta/malta-setup.c2
-rw-r--r--arch/mips/net/bpf_jit.c6
-rw-r--r--arch/mips/netlogic/common/nlm-dma.c4
-rw-r--r--arch/mips/pic32/pic32mzda/init.c4
-rw-r--r--arch/mips/pistachio/init.c25
-rw-r--r--arch/mips/ralink/mt7620.c2
-rw-r--r--arch/mips/sgi-ip22/ip22-reset.c2
-rw-r--r--arch/mips/sni/time.c1
-rw-r--r--arch/mn10300/Kconfig4
-rw-r--r--arch/mn10300/include/asm/rtc-regs.h4
-rw-r--r--arch/mn10300/include/asm/rtc.h2
-rw-r--r--arch/mn10300/kernel/rtc.c104
-rw-r--r--arch/mn10300/mm/dma-alloc.c8
-rw-r--r--arch/mn10300/proc-mn103e010/proc-init.c3
-rw-r--r--arch/mn10300/proc-mn2ws0050/proc-init.c1
-rw-r--r--arch/nios2/mm/dma-mapping.c12
-rw-r--r--arch/openrisc/kernel/dma.c21
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/include/asm/hash.h146
-rw-r--r--arch/parisc/include/asm/mc146818rtc.h9
-rw-r--r--arch/parisc/include/asm/rtc.h131
-rw-r--r--arch/parisc/kernel/firmware.c6
-rw-r--r--arch/parisc/kernel/pci-dma.c18
-rw-r--r--arch/parisc/kernel/time.c36
-rw-r--r--arch/parisc/lib/iomap.c64
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/Kconfig.debug19
-rw-r--r--arch/powerpc/Makefile22
-rw-r--r--arch/powerpc/crypto/crc32c-vpmsum_glue.c3
-rw-r--r--arch/powerpc/include/asm/book3s/64/hugetlb-radix.h15
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu-hash.h10
-rw-r--r--arch/powerpc/include/asm/book3s/64/mmu.h16
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush-hash.h5
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush-radix.h16
-rw-r--r--arch/powerpc/include/asm/book3s/64/tlbflush.h27
-rw-r--r--arch/powerpc/include/asm/cacheflush.h1
-rw-r--r--arch/powerpc/include/asm/cpu_has_feature.h53
-rw-r--r--arch/powerpc/include/asm/cpuidle.h13
-rw-r--r--arch/powerpc/include/asm/cputable.h15
-rw-r--r--arch/powerpc/include/asm/cputime.h1
-rw-r--r--arch/powerpc/include/asm/dbell.h1
-rw-r--r--arch/powerpc/include/asm/dcr-native.h1
-rw-r--r--arch/powerpc/include/asm/dma-mapping.h7
-rw-r--r--arch/powerpc/include/asm/feature-fixups.h1
-rw-r--r--arch/powerpc/include/asm/hugetlb.h2
-rw-r--r--arch/powerpc/include/asm/iommu.h10
-rw-r--r--arch/powerpc/include/asm/jump_label.h5
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h3
-rw-r--r--arch/powerpc/include/asm/machdep.h2
-rw-r--r--arch/powerpc/include/asm/mman.h1
-rw-r--r--arch/powerpc/include/asm/mmu.h98
-rw-r--r--arch/powerpc/include/asm/reg.h9
-rw-r--r--arch/powerpc/include/asm/rtc.h78
-rw-r--r--arch/powerpc/include/asm/time.h3
-rw-r--r--arch/powerpc/include/asm/tlb.h13
-rw-r--r--arch/powerpc/include/asm/tlbflush.h1
-rw-r--r--arch/powerpc/include/asm/uaccess.h21
-rw-r--r--arch/powerpc/include/asm/xics.h2
-rw-r--r--arch/powerpc/include/asm/xor.h1
-rw-r--r--arch/powerpc/include/uapi/asm/elf.h5
-rw-r--r--arch/powerpc/kernel/align.c1
-rw-r--r--arch/powerpc/kernel/cputable.c37
-rw-r--r--arch/powerpc/kernel/dma-iommu.c12
-rw-r--r--arch/powerpc/kernel/dma.c18
-rw-r--r--arch/powerpc/kernel/eeh.c4
-rw-r--r--arch/powerpc/kernel/entry_64.S2
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S77
-rw-r--r--arch/powerpc/kernel/ibmebus.c12
-rw-r--r--arch/powerpc/kernel/idle_book3s.S19
-rw-r--r--arch/powerpc/kernel/iommu.c12
-rw-r--r--arch/powerpc/kernel/irq.c1
-rw-r--r--arch/powerpc/kernel/mce.c3
-rw-r--r--arch/powerpc/kernel/paca.c2
-rw-r--r--arch/powerpc/kernel/pci-common.c7
-rw-r--r--arch/powerpc/kernel/process.c1
-rw-r--r--arch/powerpc/kernel/prom.c17
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/ptrace.c1551
-rw-r--r--arch/powerpc/kernel/setup-common.c1
-rw-r--r--arch/powerpc/kernel/setup_32.c10
-rw-r--r--arch/powerpc/kernel/setup_64.c11
-rw-r--r--arch/powerpc/kernel/smp.c1
-rw-r--r--arch/powerpc/kernel/time.c29
-rw-r--r--arch/powerpc/kernel/vdso.c1
-rw-r--r--arch/powerpc/kernel/vdso32/Makefile6
-rw-r--r--arch/powerpc/kernel/vdso64/Makefile6
-rw-r--r--arch/powerpc/kernel/vio.c12
-rw-r--r--arch/powerpc/kvm/book3s_xics.c12
-rw-r--r--arch/powerpc/lib/checksum_32.S7
-rw-r--r--arch/powerpc/lib/feature-fixups.c42
-rw-r--r--arch/powerpc/mm/hash_native_64.c8
-rw-r--r--arch/powerpc/mm/hash_utils_64.c53
-rw-r--r--arch/powerpc/mm/hugetlbpage-radix.c39
-rw-r--r--arch/powerpc/mm/init_64.c22
-rw-r--r--arch/powerpc/mm/pgtable-book3s64.c7
-rw-r--r--arch/powerpc/mm/pgtable-radix.c7
-rw-r--r--arch/powerpc/mm/pgtable.c2
-rw-r--r--arch/powerpc/mm/tlb-radix.c90
-rw-r--r--arch/powerpc/mm/tlb_hash32.c11
-rw-r--r--arch/powerpc/mm/tlb_nohash.c6
-rw-r--r--arch/powerpc/perf/power9-events-list.h6
-rw-r--r--arch/powerpc/platforms/Kconfig11
-rw-r--r--arch/powerpc/platforms/cell/iommu.c28
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c1
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c4
-rw-r--r--arch/powerpc/platforms/pasemi/iommu.c7
-rw-r--r--arch/powerpc/platforms/powernv/npu-dma.c8
-rw-r--r--arch/powerpc/platforms/powernv/opal-irqchip.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal.c1
-rw-r--r--arch/powerpc/platforms/powernv/pci-ioda.c36
-rw-r--r--arch/powerpc/platforms/powernv/pci.c2
-rw-r--r--arch/powerpc/platforms/powernv/pci.h2
-rw-r--r--arch/powerpc/platforms/ps3/system-bus.c18
-rw-r--r--arch/powerpc/platforms/ps3/time.c2
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c26
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c6
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c2
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c1
-rw-r--r--arch/powerpc/sysdev/xics/Kconfig1
-rw-r--r--arch/powerpc/sysdev/xics/ics-opal.c4
-rw-r--r--arch/powerpc/sysdev/xics/ics-rtas.c4
-rw-r--r--arch/powerpc/sysdev/xics/xics-common.c59
-rw-r--r--arch/powerpc/xmon/ppc-dis.c1
-rw-r--r--arch/s390/Kconfig14
-rw-r--r--arch/s390/boot/compressed/head.S11
-rw-r--r--arch/s390/configs/default_defconfig2
-rw-r--r--arch/s390/configs/gcov_defconfig2
-rw-r--r--arch/s390/configs/performance_defconfig2
-rw-r--r--arch/s390/crypto/crc32-vx.c6
-rw-r--r--arch/s390/defconfig2
-rw-r--r--arch/s390/include/asm/dma-mapping.h1
-rw-r--r--arch/s390/kernel/head.S4
-rw-r--r--arch/s390/kvm/kvm-s390.c5
-rw-r--r--arch/s390/lib/string.c16
-rw-r--r--arch/s390/lib/uaccess.c2
-rw-r--r--arch/s390/mm/pageattr.c2
-rw-r--r--arch/s390/pci/pci_dma.c23
-rw-r--r--arch/sh/Kconfig34
-rw-r--r--arch/sh/Makefile3
-rw-r--r--arch/sh/boards/Kconfig1
-rw-r--r--arch/sh/boards/board-secureedge5410.c3
-rw-r--r--arch/sh/boards/of-generic.c15
-rw-r--r--arch/sh/boot/dts/Makefile3
-rwxr-xr-xarch/sh/boot/dts/j2_mimas_v2.dts96
-rw-r--r--arch/sh/configs/j2_defconfig40
-rw-r--r--arch/sh/drivers/heartbeat.c32
-rw-r--r--arch/sh/include/asm/atomic.h8
-rw-r--r--arch/sh/include/asm/barrier.h5
-rw-r--r--arch/sh/include/asm/bitops-cas.h93
-rw-r--r--arch/sh/include/asm/bitops.h2
-rw-r--r--arch/sh/include/asm/cmpxchg-cas.h24
-rw-r--r--arch/sh/include/asm/cmpxchg-xchg.h2
-rw-r--r--arch/sh/include/asm/cmpxchg.h2
-rw-r--r--arch/sh/include/asm/dma-mapping.h4
-rw-r--r--arch/sh/include/asm/futex-cas.h34
-rw-r--r--arch/sh/include/asm/futex-irq.h86
-rw-r--r--arch/sh/include/asm/futex-llsc.h41
-rw-r--r--arch/sh/include/asm/futex.h97
-rw-r--r--arch/sh/include/asm/mc146818rtc.h7
-rw-r--r--arch/sh/include/asm/processor.h2
-rw-r--r--arch/sh/include/asm/rtc.h11
-rw-r--r--arch/sh/include/asm/spinlock-cas.h117
-rw-r--r--arch/sh/include/asm/spinlock-llsc.h224
-rw-r--r--arch/sh/include/asm/spinlock.h222
-rw-r--r--arch/sh/include/uapi/asm/cpu-features.h1
-rw-r--r--arch/sh/include/uapi/asm/sigcontext.h3
-rw-r--r--arch/sh/include/uapi/asm/unistd_32.h16
-rw-r--r--arch/sh/include/uapi/asm/unistd_64.h16
-rw-r--r--arch/sh/kernel/cpu/clock.c4
-rw-r--r--arch/sh/kernel/cpu/init.c6
-rw-r--r--arch/sh/kernel/cpu/proc.c1
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile4
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S55
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh2/smp-j2.c139
-rw-r--r--arch/sh/kernel/dma-nommu.c4
-rw-r--r--arch/sh/kernel/dwarf.c6
-rw-r--r--arch/sh/kernel/head_32.S6
-rw-r--r--arch/sh/kernel/setup.c6
-rw-r--r--arch/sh/kernel/syscalls_32.S14
-rw-r--r--arch/sh/kernel/syscalls_64.S14
-rw-r--r--arch/sh/kernel/time.c36
-rw-r--r--arch/sh/mm/Makefile3
-rw-r--r--arch/sh/mm/asids-debugfs.c5
-rw-r--r--arch/sh/mm/cache-j2.c65
-rw-r--r--arch/sh/mm/cache.c13
-rw-r--r--arch/sh/mm/consistent.c4
-rw-r--r--arch/sparc/Kconfig1
-rw-r--r--arch/sparc/include/asm/io_32.h10
-rw-r--r--arch/sparc/include/asm/uaccess_32.h14
-rw-r--r--arch/sparc/include/asm/uaccess_64.h11
-rw-r--r--arch/sparc/kernel/iommu.c12
-rw-r--r--arch/sparc/kernel/ioport.c24
-rw-r--r--arch/sparc/kernel/pci_sun4v.c12
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S7
-rw-r--r--arch/tile/kernel/pci-dma.c28
-rw-r--r--arch/tile/kernel/vmlinux.lds.S12
-rw-r--r--arch/um/Kconfig.common5
-rw-r--r--arch/um/include/asm/irqflags.h18
-rw-r--r--arch/um/kernel/Makefile5
-rw-r--r--arch/um/kernel/initrd.c2
-rw-r--r--arch/um/kernel/um_arch.c8
-rw-r--r--arch/um/os-Linux/Makefile3
-rw-r--r--arch/um/os-Linux/signal.c5
-rw-r--r--arch/unicore32/include/asm/mmu_context.h2
-rw-r--r--arch/unicore32/mm/dma-swiotlb.c4
-rw-r--r--arch/x86/Kconfig3
-rw-r--r--arch/x86/entry/Makefile2
-rw-r--r--arch/x86/entry/common.c6
-rw-r--r--arch/x86/entry/entry_64.S25
-rw-r--r--arch/x86/entry/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/entry/vdso/vclock_gettime.c25
-rw-r--r--arch/x86/entry/vdso/vdso2c.h6
-rw-r--r--arch/x86/events/core.c11
-rw-r--r--arch/x86/events/intel/uncore_snb.c14
-rw-r--r--arch/x86/events/intel/uncore_snbep.c10
-rw-r--r--arch/x86/include/asm/apic.h2
-rw-r--r--arch/x86/include/asm/dma-mapping.h5
-rw-r--r--arch/x86/include/asm/elf.h4
-rw-r--r--arch/x86/include/asm/fpu/internal.h16
-rw-r--r--arch/x86/include/asm/hardirq.h4
-rw-r--r--arch/x86/include/asm/init.h4
-rw-r--r--arch/x86/include/asm/mc146818rtc.h1
-rw-r--r--arch/x86/include/asm/mmu_context.h2
-rw-r--r--arch/x86/include/asm/pgtable_64.h4
-rw-r--r--arch/x86/include/asm/pvclock.h39
-rw-r--r--arch/x86/include/asm/realmode.h10
-rw-r--r--arch/x86/include/asm/rtc.h1
-rw-r--r--arch/x86/include/asm/swiotlb.h4
-rw-r--r--arch/x86/include/asm/syscall.h5
-rw-r--r--arch/x86/include/asm/thread_info.h47
-rw-r--r--arch/x86/include/asm/tlbflush.h7
-rw-r--r--arch/x86/include/asm/uaccess.h26
-rw-r--r--arch/x86/include/asm/uaccess_32.h2
-rw-r--r--arch/x86/include/asm/uaccess_64.h2
-rw-r--r--arch/x86/include/asm/uv/bios.h5
-rw-r--r--arch/x86/include/asm/xen/page-coherent.h9
-rw-r--r--arch/x86/kernel/amd_gart_64.c20
-rw-r--r--arch/x86/kernel/apic/apic.c30
-rw-r--r--arch/x86/kernel/apic/vector.c2
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c13
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c42
-rw-r--r--arch/x86/kernel/fpu/signal.c12
-rw-r--r--arch/x86/kernel/fpu/xstate.c138
-rw-r--r--arch/x86/kernel/head32.c2
-rw-r--r--arch/x86/kernel/head64.c1
-rw-r--r--arch/x86/kernel/hpet.c3
-rw-r--r--arch/x86/kernel/irq.c3
-rw-r--r--arch/x86/kernel/nmi.c1
-rw-r--r--arch/x86/kernel/pci-calgary_64.c14
-rw-r--r--arch/x86/kernel/pci-dma.c4
-rw-r--r--arch/x86/kernel/pci-nommu.c4
-rw-r--r--arch/x86/kernel/pci-swiotlb.c4
-rw-r--r--arch/x86/kernel/ptrace.c15
-rw-r--r--arch/x86/kernel/pvclock.c17
-rw-r--r--arch/x86/kernel/rtc.c3
-rw-r--r--arch/x86/kernel/setup.c27
-rw-r--r--arch/x86/kernel/signal.c40
-rw-r--r--arch/x86/kernel/tsc.c4
-rw-r--r--arch/x86/kernel/uprobes.c22
-rw-r--r--arch/x86/kvm/irq.h3
-rw-r--r--arch/x86/kvm/lapic.c3
-rw-r--r--arch/x86/kvm/vmx.c15
-rw-r--r--arch/x86/lib/hweight.S2
-rw-r--r--arch/x86/lib/kaslr.c2
-rw-r--r--arch/x86/mm/ident_map.c19
-rw-r--r--arch/x86/mm/init.c14
-rw-r--r--arch/x86/mm/kaslr.c2
-rw-r--r--arch/x86/pci/sta2x11-fixup.c2
-rw-r--r--arch/x86/pci/vmd.c16
-rw-r--r--arch/x86/platform/efi/efi.c1
-rw-r--r--arch/x86/platform/efi/efi_64.c1
-rw-r--r--arch/x86/platform/efi/quirks.c21
-rw-r--r--arch/x86/platform/intel-mid/intel_mid_vrtc.c1
-rw-r--r--arch/x86/platform/uv/bios_uv.c11
-rw-r--r--arch/x86/power/hibernate_64.c20
-rw-r--r--arch/x86/power/hibernate_asm_64.S2
-rw-r--r--arch/x86/realmode/init.c47
-rw-r--r--arch/x86/um/vdso/Makefile3
-rw-r--r--arch/xtensa/kernel/pci-dma.c12
-rw-r--r--block/Kconfig13
-rw-r--r--block/bio-integrity.c2
-rw-r--r--block/bio.c21
-rw-r--r--block/blk-core.c26
-rw-r--r--block/blk-merge.c8
-rw-r--r--block/blk-mq-sysfs.c12
-rw-r--r--block/blk-mq.c25
-rw-r--r--block/blk-throttle.c13
-rw-r--r--block/cfq-iosched.c4
-rw-r--r--block/genhd.c3
-rw-r--r--crypto/Kconfig2
-rw-r--r--crypto/sha3_generic.c16
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/acpi/acpi_cmos_rtc.c2
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/ec.c41
-rw-r--r--drivers/acpi/nfit/core.c3
-rw-r--r--drivers/base/power/opp/core.c31
-rw-r--r--drivers/base/power/trace.c6
-rw-r--r--drivers/base/power/wakeup.c18
-rw-r--r--drivers/block/brd.c19
-rw-r--r--drivers/block/drbd/drbd_main.c8
-rw-r--r--drivers/block/drbd/drbd_receiver.c2
-rw-r--r--drivers/block/drbd/drbd_req.c6
-rw-r--r--drivers/block/drbd/drbd_worker.c2
-rw-r--r--drivers/block/floppy.c21
-rw-r--r--drivers/block/loop.c67
-rw-r--r--drivers/block/nbd.c12
-rw-r--r--drivers/block/pktcdvd.c2
-rw-r--r--drivers/block/rbd.c10
-rw-r--r--drivers/block/umem.c2
-rw-r--r--drivers/block/virtio_blk.c26
-rw-r--r--drivers/block/zram/zram_drv.c29
-rw-r--r--drivers/char/Kconfig28
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/genrtc.c539
-rw-r--r--drivers/clocksource/arm_arch_timer.c26
-rw-r--r--drivers/cpufreq/Kconfig1
-rw-r--r--drivers/cpufreq/intel_pstate.c2
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c21
-rw-r--r--drivers/crypto/caam/caamalg.c13
-rw-r--r--drivers/crypto/caam/caamhash.c1
-rw-r--r--drivers/edac/sb_edac.c15
-rw-r--r--drivers/firmware/broadcom/bcm47xx_sprom.c2
-rw-r--r--drivers/firmware/efi/capsule-loader.c8
-rw-r--r--drivers/firmware/efi/capsule.c6
-rw-r--r--drivers/fpga/Kconfig1
-rw-r--r--drivers/gpu/drm/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c8
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c13
-rw-r--r--drivers/gpu/drm/drm_atomic.c4
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c7
-rw-r--r--drivers/gpu/drm/drm_blend.c238
-rw-r--r--drivers/gpu/drm/drm_crtc.c8
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h4
-rw-r--r--drivers/gpu/drm/drm_edid.c22
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c20
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.h2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c67
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c30
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c25
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_gem.c13
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_gem.h2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c13
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c4
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c9
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vsp.c14
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c17
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.h2
-rw-r--r--drivers/gpu/drm/sti/sti_cursor.c4
-rw-r--r--drivers/gpu/drm/sti/sti_gdp.c4
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c4
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c9
-rw-r--r--drivers/gpu/drm/sti/sti_plane.c78
-rw-r--r--drivers/gpu/drm/sti/sti_plane.h7
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c3
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c10
-rw-r--r--drivers/infiniband/Kconfig1
-rw-r--r--drivers/infiniband/core/cma.c98
-rw-r--r--drivers/infiniband/core/device.c9
-rw-r--r--drivers/infiniband/core/iwcm.c54
-rw-r--r--drivers/infiniband/core/iwcm.h2
-rw-r--r--drivers/infiniband/core/iwpm_util.c3
-rw-r--r--drivers/infiniband/core/multicast.c12
-rw-r--r--drivers/infiniband/core/netlink.c6
-rw-r--r--drivers/infiniband/core/rw.c24
-rw-r--r--drivers/infiniband/core/sa_query.c41
-rw-r--r--drivers/infiniband/core/sysfs.c15
-rw-r--r--drivers/infiniband/core/ucma.c18
-rw-r--r--drivers/infiniband/core/umem.c7
-rw-r--r--drivers/infiniband/core/uverbs.h14
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c535
-rw-r--r--drivers/infiniband/core/uverbs_main.c75
-rw-r--r--drivers/infiniband/core/verbs.c172
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c4
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_provider.c27
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c193
-rw-r--r--drivers/infiniband/hw/cxgb4/cq.c42
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c2
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h24
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c127
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c31
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c40
-rw-r--r--drivers/infiniband/hw/hfi1/Kconfig4
-rw-r--r--drivers/infiniband/hw/hfi1/Makefile2
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.c567
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.h38
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c296
-rw-r--r--drivers/infiniband/hw/hfi1/chip.h5
-rw-r--r--drivers/infiniband/hw/hfi1/chip_registers.h4
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c52
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c93
-rw-r--r--drivers/infiniband/hw/hfi1/firmware.c125
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h123
-rw-r--r--drivers/infiniband/hw/hfi1/init.c51
-rw-r--r--drivers/infiniband/hw/hfi1/mad.c60
-rw-r--r--drivers/infiniband/hw/hfi1/mad.h7
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.c254
-rw-r--r--drivers/infiniband/hw/hfi1/mmu_rb.h37
-rw-r--r--drivers/infiniband/hw/hfi1/pcie.c68
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c21
-rw-r--r--drivers/infiniband/hw/hfi1/platform.c20
-rw-r--r--drivers/infiniband/hw/hfi1/qp.c68
-rw-r--r--drivers/infiniband/hw/hfi1/qp.h4
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.c409
-rw-r--r--drivers/infiniband/hw/hfi1/qsfp.h3
-rw-r--r--drivers/infiniband/hw/hfi1/rc.c90
-rw-r--r--drivers/infiniband/hw/hfi1/ruc.c57
-rw-r--r--drivers/infiniband/hw/hfi1/sysfs.c25
-rw-r--r--drivers/infiniband/hw/hfi1/trace.h1333
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ctxts.h141
-rw-r--r--drivers/infiniband/hw/hfi1/trace_dbg.h155
-rw-r--r--drivers/infiniband/hw/hfi1/trace_ibhdrs.h209
-rw-r--r--drivers/infiniband/hw/hfi1/trace_misc.h81
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rc.h123
-rw-r--r--drivers/infiniband/hw/hfi1/trace_rx.h322
-rw-r--r--drivers/infiniband/hw/hfi1/trace_tx.h642
-rw-r--r--drivers/infiniband/hw/hfi1/twsi.c489
-rw-r--r--drivers/infiniband/hw/hfi1/twsi.h65
-rw-r--r--drivers/infiniband/hw/hfi1/uc.c61
-rw-r--r--drivers/infiniband/hw/hfi1/ud.c86
-rw-r--r--drivers/infiniband/hw/hfi1/user_exp_rcv.c124
-rw-r--r--drivers/infiniband/hw/hfi1/user_pages.c19
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c301
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.h8
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c89
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.h8
-rw-r--r--drivers/infiniband/hw/hfi1/verbs_txreq.h2
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_cm.c4
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_d.h3
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_puda.c4
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_type.h2
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_uk.c29
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_user.h2
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_verbs.c76
-rw-r--r--drivers/infiniband/hw/mlx4/cq.c4
-rw-r--r--drivers/infiniband/hw/mlx4/main.c222
-rw-r--r--drivers/infiniband/hw/mlx4/mlx4_ib.h9
-rw-r--r--drivers/infiniband/hw/mlx5/cq.c87
-rw-r--r--drivers/infiniband/hw/mlx5/gsi.c19
-rw-r--r--drivers/infiniband/hw/mlx5/main.c429
-rw-r--r--drivers/infiniband/hw/mlx5/mlx5_ib.h74
-rw-r--r--drivers/infiniband/hw/mlx5/mr.c4
-rw-r--r--drivers/infiniband/hw/mlx5/qp.c691
-rw-r--r--drivers/infiniband/hw/mlx5/srq.c112
-rw-r--r--drivers/infiniband/hw/mlx5/user.h88
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c24
-rw-r--r--drivers/infiniband/hw/mthca/mthca_reset.c42
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c33
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c19
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c43
-rw-r--r--drivers/infiniband/hw/qib/qib_ud.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c16
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_sysfs.c17
-rw-r--r--drivers/infiniband/sw/Makefile1
-rw-r--r--drivers/infiniband/sw/rdmavt/Kconfig1
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.c1
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.c124
-rw-r--r--drivers/infiniband/sw/rdmavt/mr.h2
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.c246
-rw-r--r--drivers/infiniband/sw/rdmavt/vt.c10
-rw-r--r--drivers/infiniband/sw/rxe/Kconfig24
-rw-r--r--drivers/infiniband/sw/rxe/Makefile24
-rw-r--r--drivers/infiniband/sw/rxe/rxe.c386
-rw-r--r--drivers/infiniband/sw/rxe/rxe.h77
-rw-r--r--drivers/infiniband/sw/rxe/rxe_av.c98
-rw-r--r--drivers/infiniband/sw/rxe/rxe_comp.c734
-rw-r--r--drivers/infiniband/sw/rxe/rxe_cq.c165
-rw-r--r--drivers/infiniband/sw/rxe/rxe_dma.c166
-rw-r--r--drivers/infiniband/sw/rxe/rxe_hdr.h952
-rw-r--r--drivers/infiniband/sw/rxe/rxe_icrc.c96
-rw-r--r--drivers/infiniband/sw/rxe/rxe_loc.h286
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mcast.c190
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mmap.c173
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mr.c643
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c708
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.h53
-rw-r--r--drivers/infiniband/sw/rxe/rxe_opcode.c961
-rw-r--r--drivers/infiniband/sw/rxe/rxe_opcode.h129
-rw-r--r--drivers/infiniband/sw/rxe/rxe_param.h172
-rw-r--r--drivers/infiniband/sw/rxe/rxe_pool.c502
-rw-r--r--drivers/infiniband/sw/rxe/rxe_pool.h163
-rw-r--r--drivers/infiniband/sw/rxe/rxe_qp.c851
-rw-r--r--drivers/infiniband/sw/rxe/rxe_queue.c217
-rw-r--r--drivers/infiniband/sw/rxe/rxe_queue.h178
-rw-r--r--drivers/infiniband/sw/rxe/rxe_recv.c420
-rw-r--r--drivers/infiniband/sw/rxe/rxe_req.c726
-rw-r--r--drivers/infiniband/sw/rxe/rxe_resp.c1380
-rw-r--r--drivers/infiniband/sw/rxe/rxe_srq.c193
-rw-r--r--drivers/infiniband/sw/rxe/rxe_sysfs.c157
-rw-r--r--drivers/infiniband/sw/rxe/rxe_task.c154
-rw-r--r--drivers/infiniband/sw/rxe/rxe_task.h95
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.c1330
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.h480
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_verbs.c10
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c2
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.h1
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c10
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.h6
-rw-r--r--drivers/input/joystick/xpad.c43
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c19
-rw-r--r--drivers/input/misc/rotary_encoder.c23
-rw-r--r--drivers/input/mouse/elan_i2c_core.c79
-rw-r--r--drivers/input/mouse/elantech.c8
-rw-r--r--drivers/input/rmi4/rmi_bus.c5
-rw-r--r--drivers/input/serio/i8042.c16
-rw-r--r--drivers/input/serio/libps2.c10
-rw-r--r--drivers/input/touchscreen/Kconfig25
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/ili210x.c2
-rw-r--r--drivers/input/touchscreen/silead.c565
-rw-r--r--drivers/input/touchscreen/sis_i2c.c413
-rw-r--r--drivers/iommu/amd_iommu.c12
-rw-r--r--drivers/iommu/dma-iommu.c22
-rw-r--r--drivers/iommu/intel-iommu.c12
-rw-r--r--drivers/iommu/mtk_iommu.h6
-rw-r--r--drivers/irqchip/irq-mips-gic.c2
-rw-r--r--drivers/md/bcache/request.c12
-rw-r--r--drivers/md/bcache/super.c2
-rw-r--r--drivers/md/bcache/writeback.h2
-rw-r--r--drivers/md/dm-cache-target.c8
-rw-r--r--drivers/md/dm-crypt.c4
-rw-r--r--drivers/md/dm-era-target.c2
-rw-r--r--drivers/md/dm-flakey.c29
-rw-r--r--drivers/md/dm-io.c6
-rw-r--r--drivers/md/dm-log-writes.c4
-rw-r--r--drivers/md/dm-mpath.c26
-rw-r--r--drivers/md/dm-raid.c4
-rw-r--r--drivers/md/dm-raid1.c10
-rw-r--r--drivers/md/dm-region-hash.c4
-rw-r--r--drivers/md/dm-rq.c20
-rw-r--r--drivers/md/dm-snap.c6
-rw-r--r--drivers/md/dm-stripe.c4
-rw-r--r--drivers/md/dm-thin.c8
-rw-r--r--drivers/md/dm-zero.c2
-rw-r--r--drivers/md/dm.c24
-rw-r--r--drivers/md/linear.c2
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/multipath.c8
-rw-r--r--drivers/md/raid0.c2
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c8
-rw-r--r--drivers/md/raid5-cache.c2
-rw-r--r--drivers/md/raid5.c20
-rw-r--r--drivers/media/dvb-frontends/cxd2841er.c10
-rw-r--r--drivers/media/i2c/adv7180.c18
-rw-r--r--drivers/media/i2c/adv7511.c24
-rw-r--r--drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c4
-rw-r--r--drivers/media/platform/sti/bdisp/bdisp-hw.c26
-rw-r--r--drivers/media/platform/vim2m.c15
-rw-r--r--drivers/media/platform/vivid/vivid-cec.c10
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-contig.c30
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-sg.c21
-rw-r--r--drivers/media/v4l2-core/videobuf2-vmalloc.c2
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/misc/cxl/context.c3
-rw-r--r--drivers/misc/cxl/cxl.h2
-rw-r--r--drivers/misc/cxl/native.c2
-rw-r--r--drivers/misc/cxl/pci.c12
-rw-r--r--drivers/misc/cxl/vphb.c2
-rw-r--r--drivers/misc/lkdtm_usercopy.c2
-rw-r--r--drivers/misc/mic/Kconfig4
-rw-r--r--drivers/misc/mic/host/mic_boot.c20
-rw-r--r--drivers/mtd/bcm47xxpart.c2
-rw-r--r--drivers/mtd/ubi/attach.c141
-rw-r--r--drivers/mtd/ubi/build.c13
-rw-r--r--drivers/mtd/ubi/fastmap.c65
-rw-r--r--drivers/mtd/ubi/gluebi.c5
-rw-r--r--drivers/mtd/ubi/io.c2
-rw-r--r--drivers/mtd/ubi/ubi.h46
-rw-r--r--drivers/mtd/ubi/vmt.c25
-rw-r--r--drivers/mtd/ubi/wl.c41
-rw-r--r--drivers/net/caif/Kconfig2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c40
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/srq.c265
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/transobj.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c10
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c2
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c2
-rw-r--r--drivers/net/wireless/ath/regd.c4
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.c49
-rw-r--r--drivers/ntb/ntb_transport.c38
-rw-r--r--drivers/ntb/test/ntb_perf.c240
-rw-r--r--drivers/ntb/test/ntb_pingpong.c62
-rw-r--r--drivers/ntb/test/ntb_tool.c459
-rw-r--r--drivers/nvdimm/btt.c19
-rw-r--r--drivers/nvdimm/btt_devs.c20
-rw-r--r--drivers/nvdimm/nd.h1
-rw-r--r--drivers/nvdimm/pmem.c16
-rw-r--r--drivers/nvme/host/pci.c20
-rw-r--r--drivers/nvme/host/rdma.c83
-rw-r--r--drivers/nvme/target/admin-cmd.c6
-rw-r--r--drivers/nvme/target/core.c4
-rw-r--r--drivers/nvme/target/loop.c4
-rw-r--r--drivers/nvme/target/nvmet.h1
-rw-r--r--drivers/nvme/target/rdma.c100
-rw-r--r--drivers/of/platform.c20
-rw-r--r--drivers/parisc/ccio-dma.c16
-rw-r--r--drivers/parisc/sba_iommu.c16
-rw-r--r--drivers/pci/ecam.c2
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c6
-rw-r--r--drivers/pci/msi.c2
-rw-r--r--drivers/perf/arm_pmu.c25
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c1
-rw-r--r--drivers/pinctrl/meson/pinctrl-meson.c8
-rw-r--r--drivers/pinctrl/pinctrl-amd.c20
-rw-r--r--drivers/pinctrl/pinctrl-pistachio.c9
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c17
-rw-r--r--drivers/platform/x86/dell-wmi.c4
-rw-r--r--drivers/pnp/pnpbios/core.c1
-rw-r--r--drivers/power/max17042_battery.c15
-rw-r--r--drivers/power/reset/Kconfig2
-rw-r--r--drivers/power/reset/hisi-reboot.c5
-rw-r--r--drivers/power/tps65217_charger.c1
-rw-r--r--drivers/pwm/Kconfig26
-rw-r--r--drivers/pwm/Makefile3
-rw-r--r--drivers/pwm/core.c27
-rw-r--r--drivers/pwm/pwm-atmel.c30
-rw-r--r--drivers/pwm/pwm-bcm-iproc.c277
-rw-r--r--drivers/pwm/pwm-cros-ec.c260
-rw-r--r--drivers/pwm/pwm-lpc32xx.c7
-rw-r--r--drivers/pwm/pwm-lpss-pci.c1
-rw-r--r--drivers/pwm/pwm-lpss.c26
-rw-r--r--drivers/pwm/pwm-rockchip.c178
-rw-r--r--drivers/pwm/pwm-stmpe.c319
-rw-r--r--drivers/pwm/pwm-tegra.c69
-rw-r--r--drivers/pwm/pwm-tiecap.c37
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c38
-rw-r--r--drivers/pwm/pwm-tipwmss.c49
-rw-r--r--drivers/pwm/pwm-tipwmss.h39
-rw-r--r--drivers/pwm/sysfs.c17
-rw-r--r--drivers/rapidio/rio_cm.c24
-rw-r--r--drivers/regulator/pwm-regulator.c162
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c7
-rw-r--r--drivers/rtc/Kconfig26
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/interface.c32
-rw-r--r--drivers/rtc/rtc-abx80x.c12
-rw-r--r--drivers/rtc/rtc-asm9260.c1
-rw-r--r--drivers/rtc/rtc-at91sam9.c1
-rw-r--r--drivers/rtc/rtc-cmos.c17
-rw-r--r--drivers/rtc/rtc-da9052.c1
-rw-r--r--drivers/rtc/rtc-da9055.c1
-rw-r--r--drivers/rtc/rtc-davinci.c2
-rw-r--r--drivers/rtc/rtc-ds1286.c2
-rw-r--r--drivers/rtc/rtc-ds1305.c7
-rw-r--r--drivers/rtc/rtc-ds1307.c33
-rw-r--r--drivers/rtc/rtc-ds1343.c6
-rw-r--r--drivers/rtc/rtc-ds1685.c53
-rw-r--r--drivers/rtc/rtc-ds2404.c2
-rw-r--r--drivers/rtc/rtc-ds3232.c6
-rw-r--r--drivers/rtc/rtc-efi.c6
-rw-r--r--drivers/rtc/rtc-generic.c36
-rw-r--r--drivers/rtc/rtc-hym8563.c5
-rw-r--r--drivers/rtc/rtc-isl12057.c33
-rw-r--r--drivers/rtc/rtc-m41t80.c34
-rw-r--r--drivers/rtc/rtc-m48t86.c2
-rw-r--r--drivers/rtc/rtc-max6916.c164
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c (renamed from include/asm-generic/rtc.h)69
-rw-r--r--drivers/rtc/rtc-mrst.c10
-rw-r--r--drivers/rtc/rtc-pcf2123.c4
-rw-r--r--drivers/rtc/rtc-pcf85063.c59
-rw-r--r--drivers/rtc/rtc-pcf8563.c5
-rw-r--r--drivers/rtc/rtc-rc5t583.c1
-rw-r--r--drivers/rtc/rtc-rs5c372.c6
-rw-r--r--drivers/rtc/rtc-rv8803.c205
-rw-r--r--drivers/rtc/rtc-rx8010.c8
-rw-r--r--drivers/rtc/rtc-rx8025.c5
-rw-r--r--drivers/rtc/rtc-s35390a.c157
-rw-r--r--drivers/rtc/rtc-s3c.c16
-rw-r--r--drivers/rtc/rtc-sh.c42
-rw-r--r--drivers/rtc/rtc-tegra.c6
-rw-r--r--drivers/rtc/rtc-v3020.c2
-rw-r--r--drivers/s390/block/dasd.c10
-rw-r--r--drivers/s390/block/dasd_eckd.c10
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_status.c7
-rw-r--r--drivers/s390/cio/io_sch.h1
-rw-r--r--drivers/s390/cio/qdio_main.c113
-rw-r--r--drivers/s390/virtio/Makefile6
-rw-r--r--drivers/s390/virtio/kvm_virtio.c4
-rw-r--r--drivers/scsi/Kconfig17
-rw-r--r--drivers/scsi/Makefile1
-rw-r--r--drivers/scsi/cxlflash/main.c10
-rw-r--r--drivers/scsi/fcoe/fcoe.c52
-rw-r--r--drivers/scsi/fcoe/fcoe.h1
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.h2
-rw-r--r--drivers/scsi/ibmvscsi_tgt/Makefile3
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c4087
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h346
-rw-r--r--drivers/scsi/ibmvscsi_tgt/libsrp.c427
-rw-r--r--drivers/scsi/ibmvscsi_tgt/libsrp.h123
-rw-r--r--drivers/scsi/ipr.c15
-rw-r--r--drivers/scsi/ipr.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c15
-rw-r--r--drivers/ssb/driver_gpio.c22
-rw-r--r--drivers/staging/emxx_udc/Kconfig2
-rw-r--r--drivers/staging/emxx_udc/emxx_udc.c36
-rw-r--r--drivers/staging/lustre/lustre/llite/dcache.c2
-rw-r--r--drivers/staging/lustre/lustre/llite/statahead.c4
-rw-r--r--drivers/staging/media/Kconfig2
-rw-r--r--drivers/staging/media/cec/cec-adap.c2
-rw-r--r--drivers/target/iscsi/iscsi_target.c22
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c5
-rw-r--r--drivers/target/target_core_device.c8
-rw-r--r--drivers/target/target_core_file.c5
-rw-r--r--drivers/target/target_core_iblock.c5
-rw-r--r--drivers/target/target_core_internal.h1
-rw-r--r--drivers/target/target_core_sbc.c2
-rw-r--r--drivers/target/target_core_transport.c94
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c2
-rw-r--r--drivers/thermal/clock_cooling.c1
-rw-r--r--drivers/thermal/fair_share.c2
-rw-r--r--drivers/thermal/gov_bang_bang.c2
-rw-r--r--drivers/thermal/intel_pch_thermal.c60
-rw-r--r--drivers/thermal/intel_powerclamp.c11
-rw-r--r--drivers/thermal/power_allocator.c2
-rw-r--r--drivers/thermal/step_wise.c2
-rw-r--r--drivers/thermal/thermal_core.c10
-rw-r--r--drivers/thermal/thermal_hwmon.c2
-rw-r--r--drivers/tty/serial/ar933x_uart.c4
-rw-r--r--drivers/usb/serial/cp210x.c4
-rw-r--r--drivers/usb/serial/generic.c18
-rw-r--r--drivers/usb/serial/option.c3
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c271
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h259
-rw-r--r--drivers/vfio/pci/vfio_pci_intrs.c85
-rw-r--r--drivers/vhost/Kconfig18
-rw-r--r--drivers/vhost/Kconfig.vringh5
-rw-r--r--drivers/vhost/Makefile4
-rw-r--r--drivers/vhost/net.c67
-rw-r--r--drivers/vhost/test.c8
-rw-r--r--drivers/vhost/vhost.c927
-rw-r--r--drivers/vhost/vhost.h64
-rw-r--r--drivers/vhost/vsock.c723
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-main.c12
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb.h3
-rw-r--r--drivers/virtio/virtio_balloon.c2
-rw-r--r--drivers/virtio/virtio_ring.c18
-rw-r--r--drivers/xen/swiotlb-xen.c14
-rw-r--r--fs/9p/fid.c26
-rw-r--r--fs/9p/fid.h9
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/9p/vfs_inode_dotl.c2
-rw-r--r--fs/9p/xattr.c4
-rw-r--r--fs/Kconfig6
-rw-r--r--fs/Kconfig.binfmt3
-rw-r--r--fs/adfs/dir.c6
-rw-r--r--fs/affs/amigaffs.c4
-rw-r--r--fs/affs/namei.c12
-rw-r--r--fs/autofs4/root.c8
-rw-r--r--fs/autofs4/waitq.c4
-rw-r--r--fs/binfmt_elf_fdpic.c38
-rw-r--r--fs/binfmt_flat.c525
-rw-r--r--fs/binfmt_misc.c41
-rw-r--r--fs/block_dev.c11
-rw-r--r--fs/btrfs/acl.c3
-rw-r--r--fs/btrfs/async-thread.c31
-rw-r--r--fs/btrfs/async-thread.h6
-rw-r--r--fs/btrfs/backref.c4
-rw-r--r--fs/btrfs/check-integrity.c10
-rw-r--r--fs/btrfs/compression.c10
-rw-r--r--fs/btrfs/ctree.c91
-rw-r--r--fs/btrfs/ctree.h101
-rw-r--r--fs/btrfs/dedupe.h24
-rw-r--r--fs/btrfs/delayed-inode.c4
-rw-r--r--fs/btrfs/delayed-ref.c44
-rw-r--r--fs/btrfs/delayed-ref.h3
-rw-r--r--fs/btrfs/dev-replace.c4
-rw-r--r--fs/btrfs/disk-io.c103
-rw-r--r--fs/btrfs/disk-io.h3
-rw-r--r--fs/btrfs/extent-tree.c124
-rw-r--r--fs/btrfs/extent_io.c38
-rw-r--r--fs/btrfs/extent_map.c2
-rw-r--r--fs/btrfs/file-item.c4
-rw-r--r--fs/btrfs/file.c20
-rw-r--r--fs/btrfs/free-space-cache.c8
-rw-r--r--fs/btrfs/free-space-tree.c16
-rw-r--r--fs/btrfs/inode-map.c16
-rw-r--r--fs/btrfs/inode.c270
-rw-r--r--fs/btrfs/ioctl.c40
-rw-r--r--fs/btrfs/ordered-data.c2
-rw-r--r--fs/btrfs/props.c6
-rw-r--r--fs/btrfs/qgroup.c25
-rw-r--r--fs/btrfs/qgroup.h9
-rw-r--r--fs/btrfs/relocation.c20
-rw-r--r--fs/btrfs/root-tree.c10
-rw-r--r--fs/btrfs/scrub.c12
-rw-r--r--fs/btrfs/send.c173
-rw-r--r--fs/btrfs/super.c218
-rw-r--r--fs/btrfs/sysfs.c2
-rw-r--r--fs/btrfs/tests/btrfs-tests.c67
-rw-r--r--fs/btrfs/tests/btrfs-tests.h36
-rw-r--r--fs/btrfs/tests/extent-buffer-tests.c23
-rw-r--r--fs/btrfs/tests/free-space-tests.c14
-rw-r--r--fs/btrfs/tests/free-space-tree-tests.c18
-rw-r--r--fs/btrfs/tests/inode-tests.c46
-rw-r--r--fs/btrfs/tests/qgroup-tests.c23
-rw-r--r--fs/btrfs/transaction.c37
-rw-r--r--fs/btrfs/transaction.h1
-rw-r--r--fs/btrfs/tree-log.c107
-rw-r--r--fs/btrfs/volumes.c144
-rw-r--r--fs/cachefiles/namei.c5
-rw-r--r--fs/ceph/caps.c5
-rw-r--r--fs/ceph/mds_client.c1
-rw-r--r--fs/cifs/dir.c4
-rw-r--r--fs/dcache.c59
-rw-r--r--fs/efivarfs/super.c3
-rw-r--r--fs/exec.c33
-rw-r--r--fs/ext2/dir.c6
-rw-r--r--fs/ext2/ext2.h4
-rw-r--r--fs/f2fs/data.c1
-rw-r--r--fs/f2fs/dir.c4
-rw-r--r--fs/f2fs/f2fs.h4
-rw-r--r--fs/fat/namei_msdos.c4
-rw-r--r--fs/fat/namei_vfat.c12
-rw-r--r--fs/fs-writeback.c7
-rw-r--r--fs/fuse/dir.c4
-rw-r--r--fs/fuse/fuse_i.h2
-rw-r--r--fs/fuse/inode.c8
-rw-r--r--fs/gfs2/inode.c2
-rw-r--r--fs/hfs/catalog.c12
-rw-r--r--fs/hfs/hfs_fs.h16
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfs/string.c2
-rw-r--r--fs/hfs/trans.c2
-rw-r--r--fs/hfsplus/catalog.c12
-rw-r--r--fs/hfsplus/hfsplus_fs.h13
-rw-r--r--fs/hfsplus/unicode.c4
-rw-r--r--fs/hostfs/hostfs_kern.c7
-rw-r--r--fs/hpfs/dentry.c4
-rw-r--r--fs/inode.c7
-rw-r--r--fs/internal.h2
-rw-r--r--fs/isofs/inode.c15
-rw-r--r--fs/isofs/namei.c2
-rw-r--r--fs/jfs/namei.c2
-rw-r--r--fs/logfs/dir.c4
-rw-r--r--fs/mpage.c2
-rw-r--r--fs/namei.c2
-rw-r--r--fs/ncpfs/dir.c6
-rw-r--r--fs/nfs/nfs3proc.c8
-rw-r--r--fs/nfs/nfs42proc.c2
-rw-r--r--fs/nfs/nfs4_fs.h9
-rw-r--r--fs/nfs/nfs4namespace.c4
-rw-r--r--fs/nfs/nfs4proc.c25
-rw-r--r--fs/nfs/nfs4renewd.c20
-rw-r--r--fs/nfs/nfs4state.c9
-rw-r--r--fs/nfs/proc.c8
-rw-r--r--fs/nfs/unlink.c2
-rw-r--r--fs/nfsd/Kconfig19
-rw-r--r--fs/nfsd/Makefile1
-rw-r--r--fs/nfsd/blocklayout.c2
-rw-r--r--fs/nfsd/blocklayoutxdr.c4
-rw-r--r--fs/nfsd/export.c14
-rw-r--r--fs/nfsd/export.h2
-rw-r--r--fs/nfsd/flexfilelayout.c133
-rw-r--r--fs/nfsd/flexfilelayoutxdr.c115
-rw-r--r--fs/nfsd/flexfilelayoutxdr.h49
-rw-r--r--fs/nfsd/nfs4layouts.c16
-rw-r--r--fs/nfsd/nfs4proc.c48
-rw-r--r--fs/nfsd/nfs4state.c139
-rw-r--r--fs/nfsd/nfs4xdr.c81
-rw-r--r--fs/nfsd/nfsd.h5
-rw-r--r--fs/nfsd/nfsfh.c18
-rw-r--r--fs/nfsd/nfsproc.c7
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/pnfs.h4
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/vfs.c145
-rw-r--r--fs/nfsd/vfs.h3
-rw-r--r--fs/nfsd/xdr4.h5
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c4
-rw-r--r--fs/ocfs2/dlmfs/dlmfs.c4
-rw-r--r--fs/ocfs2/dlmfs/userdlm.c2
-rw-r--r--fs/ocfs2/dlmfs/userdlm.h2
-rw-r--r--fs/open.c20
-rw-r--r--fs/pipe.c4
-rw-r--r--fs/proc/meminfo.c2
-rw-r--r--fs/proc/proc_sysctl.c4
-rw-r--r--fs/pstore/ram.c29
-rw-r--r--fs/ubifs/gc.c4
-rw-r--r--fs/ubifs/super.c19
-rw-r--r--fs/ubifs/ubifs.h4
-rw-r--r--fs/ubifs/xattr.c6
-rw-r--r--fs/utimes.c3
-rw-r--r--fs/xfs/Makefile8
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c149
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h52
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c12
-rw-r--r--fs/xfs/libxfs/xfs_attr.c71
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c4
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c19
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c241
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h54
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c32
-rw-r--r--fs/xfs/libxfs/xfs_btree.c914
-rw-r--r--fs/xfs/libxfs/xfs_btree.h88
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c6
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.h4
-rw-r--r--fs/xfs/libxfs/xfs_da_format.h1
-rw-r--r--fs/xfs/libxfs/xfs_defer.c463
-rw-r--r--fs/xfs/libxfs/xfs_defer.h97
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c15
-rw-r--r--fs/xfs/libxfs/xfs_dir2.h8
-rw-r--r--fs/xfs/libxfs/xfs_format.h131
-rw-r--r--fs/xfs/libxfs/xfs_fs.h1
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c23
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c18
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c1
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h63
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c1399
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h209
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c511
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h61
-rw-r--r--fs/xfs/libxfs/xfs_sb.c9
-rw-r--r--fs/xfs/libxfs/xfs_shared.h2
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c62
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h10
-rw-r--r--fs/xfs/libxfs/xfs_types.h4
-rw-r--r--fs/xfs/xfs_bmap_util.c139
-rw-r--r--fs/xfs/xfs_bmap_util.h4
-rw-r--r--fs/xfs/xfs_discard.c2
-rw-r--r--fs/xfs/xfs_dquot.c13
-rw-r--r--fs/xfs/xfs_error.h6
-rw-r--r--fs/xfs/xfs_export.c2
-rw-r--r--fs/xfs/xfs_extfree_item.c69
-rw-r--r--fs/xfs/xfs_extfree_item.h3
-rw-r--r--fs/xfs/xfs_filestream.c3
-rw-r--r--fs/xfs/xfs_fsops.c106
-rw-r--r--fs/xfs/xfs_inode.c99
-rw-r--r--fs/xfs/xfs_inode.h4
-rw-r--r--fs/xfs/xfs_ioctl.c8
-rw-r--r--fs/xfs/xfs_iomap.c31
-rw-r--r--fs/xfs/xfs_log_recover.c336
-rw-r--r--fs/xfs/xfs_mount.c7
-rw-r--r--fs/xfs/xfs_mount.h6
-rw-r--r--fs/xfs/xfs_ondisk.h3
-rw-r--r--fs/xfs/xfs_pnfs.h4
-rw-r--r--fs/xfs/xfs_rmap_item.c536
-rw-r--r--fs/xfs/xfs_rmap_item.h95
-rw-r--r--fs/xfs/xfs_rtalloc.c11
-rw-r--r--fs/xfs/xfs_stats.c1
-rw-r--r--fs/xfs/xfs_stats.h18
-rw-r--r--fs/xfs/xfs_super.c30
-rw-r--r--fs/xfs/xfs_symlink.c25
-rw-r--r--fs/xfs/xfs_trace.c2
-rw-r--r--fs/xfs/xfs_trace.h374
-rw-r--r--fs/xfs/xfs_trans.h26
-rw-r--r--fs/xfs/xfs_trans_extfree.c215
-rw-r--r--fs/xfs/xfs_trans_rmap.c271
-rw-r--r--include/asm-generic/qrwlock.h27
-rw-r--r--include/drm/drm_crtc.h20
-rw-r--r--include/drm/ttm/ttm_bo_driver.h3
-rw-r--r--include/kvm/arm_vgic.h7
-rw-r--r--include/linux/backing-dev-defs.h1
-rw-r--r--include/linux/backing-dev.h1
-rw-r--r--include/linux/binfmts.h2
-rw-r--r--include/linux/bio.h7
-rw-r--r--include/linux/bitmap.h7
-rw-r--r--include/linux/blk-cgroup.h4
-rw-r--r--include/linux/blk_types.h15
-rw-r--r--include/linux/blkdev.h3
-rw-r--r--include/linux/bvec.h3
-rw-r--r--include/linux/dcache.h4
-rw-r--r--include/linux/dma-attrs.h71
-rw-r--r--include/linux/dma-iommu.h6
-rw-r--r--include/linux/dma-mapping.h128
-rw-r--r--include/linux/ds17287rtc.h66
-rw-r--r--include/linux/dynamic_debug.h60
-rw-r--r--include/linux/extable.h32
-rw-r--r--include/linux/fence.h2
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/i8042.h6
-rw-r--r--include/linux/jump_label.h46
-rw-r--r--include/linux/kvm_host.h24
-rw-r--r--include/linux/lsm_hooks.h2
-rw-r--r--include/linux/mc146818rtc.h5
-rw-r--r--include/linux/mfd/cros_ec.h15
-rw-r--r--include/linux/mfd/cros_ec_commands.h31
-rw-r--r--include/linux/mlx4/device.h7
-rw-r--r--include/linux/mlx5/cq.h2
-rw-r--r--include/linux/mlx5/driver.h6
-rw-r--r--include/linux/mlx5/qp.h4
-rw-r--r--include/linux/mlx5/srq.h25
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--include/linux/module.h37
-rw-r--r--include/linux/msi.h2
-rw-r--r--include/linux/nfs4.h11
-rw-r--r--include/linux/nfs_xdr.h19
-rw-r--r--include/linux/pagemap.h2
-rw-r--r--include/linux/perf_event.h4
-rw-r--r--include/linux/platform_data/rtc-ds2404.h (renamed from include/linux/rtc-ds2404.h)0
-rw-r--r--include/linux/platform_data/rtc-m48t86.h (renamed from include/linux/m48t86.h)0
-rw-r--r--include/linux/platform_data/rtc-v3020.h (renamed from include/linux/rtc-v3020.h)0
-rw-r--r--include/linux/printk.h48
-rw-r--r--include/linux/pwm.h113
-rw-r--r--include/linux/rtc/ds1286.h (renamed from include/linux/ds1286.h)0
-rw-r--r--include/linux/security.h4
-rw-r--r--include/linux/serio.h24
-rw-r--r--include/linux/slab.h12
-rw-r--r--include/linux/sunrpc/cache.h2
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--include/linux/sunrpc/svc_xprt.h2
-rw-r--r--include/linux/sunrpc/xprt.h3
-rw-r--r--include/linux/swiotlb.h10
-rw-r--r--include/linux/thread_info.h24
-rw-r--r--include/linux/uaccess.h4
-rw-r--r--include/linux/virtio_config.h13
-rw-r--r--include/linux/virtio_vsock.h154
-rw-r--r--include/linux/ww_mutex.h4
-rw-r--r--include/media/videobuf2-core.h6
-rw-r--r--include/media/videobuf2-dma-contig.h2
-rw-r--r--include/net/af_vsock.h6
-rw-r--r--include/rdma/ib_sa.h13
-rw-r--r--include/rdma/ib_verbs.h125
-rw-r--r--include/rdma/opa_port_info.h16
-rw-r--r--include/rdma/rdma_cm.h4
-rw-r--r--include/rdma/rdma_vt.h7
-rw-r--r--include/rdma/rdmavt_mr.h1
-rw-r--r--include/rdma/rdmavt_qp.h92
-rw-r--r--include/scsi/viosrp.h (renamed from drivers/scsi/ibmvscsi/viosrp.h)13
-rw-r--r--include/target/target_core_backend.h2
-rw-r--r--include/target/target_core_base.h1
-rw-r--r--include/target/target_core_fabric.h1
-rw-r--r--include/trace/events/bcache.h8
-rw-r--r--include/trace/events/block.h14
-rw-r--r--include/trace/events/btrfs.h295
-rw-r--r--include/trace/events/sunrpc.h118
-rw-r--r--include/trace/events/timer.h14
-rw-r--r--include/trace/events/vsock_virtio_transport_common.h144
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/btrfs.h2
-rw-r--r--include/uapi/linux/elf.h14
-rw-r--r--include/uapi/linux/kvm.h5
-rw-r--r--include/uapi/linux/vhost.h33
-rw-r--r--include/uapi/linux/virtio_config.h10
-rw-r--r--include/uapi/linux/virtio_ids.h1
-rw-r--r--include/uapi/linux/virtio_vsock.h94
-rw-r--r--include/uapi/misc/cxl.h4
-rw-r--r--include/uapi/rdma/Kbuild1
-rw-r--r--include/uapi/rdma/hfi/hfi1_user.h2
-rw-r--r--include/uapi/rdma/ib_user_verbs.h95
-rw-r--r--include/uapi/rdma/rdma_user_cm.h9
-rw-r--r--include/uapi/rdma/rdma_user_rxe.h144
-rw-r--r--include/xen/swiotlb-xen.h12
-rw-r--r--init/Kconfig2
-rw-r--r--kernel/events/core.c79
-rw-r--r--kernel/futex.c23
-rw-r--r--kernel/irq/msi.c11
-rw-r--r--kernel/jump_label.c61
-rw-r--r--kernel/livepatch/core.c2
-rw-r--r--kernel/locking/qspinlock_paravirt.h2
-rw-r--r--kernel/locking/qspinlock_stat.h1
-rw-r--r--kernel/module.c121
-rw-r--r--kernel/power/hibernate.c4
-rw-r--r--kernel/printk/internal.h16
-rw-r--r--kernel/printk/nmi.c13
-rw-r--r--kernel/printk/printk.c27
-rw-r--r--kernel/ptrace.c4
-rw-r--r--kernel/sched/core.c19
-rw-r--r--kernel/sched/cpudeadline.c2
-rw-r--r--kernel/sched/cputime.c10
-rw-r--r--kernel/sched/deadline.c5
-rw-r--r--kernel/sched/fair.c2
-rw-r--r--kernel/seccomp.c6
-rw-r--r--kernel/time/timer.c5
-rw-r--r--kernel/trace/blktrace.c6
-rw-r--r--lib/dma-noop.c9
-rw-r--r--lib/dynamic_debug.c7
-rw-r--r--lib/strncpy_from_user.c8
-rw-r--r--lib/strnlen_user.c7
-rw-r--r--lib/swiotlb.c13
-rw-r--r--mm/Kconfig1
-rw-r--r--mm/Makefile4
-rw-r--r--mm/backing-dev.c19
-rw-r--r--mm/filemap.c6
-rw-r--r--mm/hugetlb.c11
-rw-r--r--mm/kasan/quarantine.c7
-rw-r--r--mm/memblock.c9
-rw-r--r--mm/memcontrol.c82
-rw-r--r--mm/memory_hotplug.c2
-rw-r--r--mm/oom_kill.c2
-rw-r--r--mm/page_alloc.c76
-rw-r--r--mm/page_io.c5
-rw-r--r--mm/rmap.c7
-rw-r--r--mm/shmem.c7
-rw-r--r--mm/slab.c30
-rw-r--r--mm/slub.c48
-rw-r--r--mm/usercopy.c268
-rw-r--r--net/9p/trans_virtio.c4
-rw-r--r--net/ceph/mon_client.c2
-rw-r--r--net/ceph/osd_client.c2
-rw-r--r--net/ceph/string_table.c8
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c8
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c5
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/clnt.c24
-rw-r--r--net/sunrpc/svc_xprt.c51
-rw-r--r--net/sunrpc/svcsock.c150
-rw-r--r--net/sunrpc/xprt.c26
-rw-r--r--net/sunrpc/xprtsock.c60
-rw-r--r--net/vmw_vsock/Kconfig20
-rw-r--r--net/vmw_vsock/Makefile6
-rw-r--r--net/vmw_vsock/af_vsock.c25
-rw-r--r--net/vmw_vsock/virtio_transport.c620
-rw-r--r--net/vmw_vsock/virtio_transport_common.c992
-rw-r--r--net/vmw_vsock/vmci_transport.c2
-rw-r--r--net/wireless/chan.c2
-rw-r--r--samples/kprobes/jprobe_example.c6
-rw-r--r--samples/kprobes/kprobe_example.c29
-rw-r--r--samples/kprobes/kretprobe_example.c14
-rw-r--r--scripts/Kbuild.include10
-rw-r--r--scripts/Makefile.gcc-plugins39
-rwxr-xr-xscripts/gcc-plugin.sh14
-rw-r--r--scripts/gcc-plugins/Makefile12
-rwxr-xr-xscripts/get_maintainer.pl2
-rw-r--r--security/Kconfig28
-rw-r--r--security/security.c2
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--sound/arm/Kconfig15
-rw-r--r--sound/hda/array.c4
-rw-r--r--sound/pci/hda/hda_intel.c34
-rw-r--r--sound/pci/hda/patch_realtek.c37
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h9
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h2
-rw-r--r--tools/arch/x86/include/asm/required-features.h2
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h4
-rw-r--r--tools/include/linux/bitmap.h37
-rw-r--r--tools/include/uapi/linux/bpf.h86
-rw-r--r--tools/lib/bitmap.c44
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/perf/Documentation/perf-probe.txt10
-rw-r--r--tools/perf/Documentation/perf-record.txt3
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Makefile.config (renamed from tools/perf/config/Makefile)0
-rw-r--r--tools/perf/Makefile.perf6
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c27
-rw-r--r--tools/perf/builtin-record.c1
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/builtin-stat.c31
-rw-r--r--tools/perf/builtin-top.c6
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Build4
-rw-r--r--tools/perf/tests/Build1
-rw-r--r--tools/perf/tests/bitmap.c53
-rw-r--r--tools/perf/tests/bpf-script-example.c4
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/code-reading.c100
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/ui/browsers/annotate.c9
-rw-r--r--tools/perf/ui/gtk/annotate.c8
-rw-r--r--tools/perf/util/annotate.c116
-rw-r--r--tools/perf/util/annotate.h22
-rw-r--r--tools/perf/util/evlist.c22
-rw-r--r--tools/perf/util/evsel.c30
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/hist.c15
-rw-r--r--tools/perf/util/hist.h4
-rw-r--r--tools/perf/util/probe-event.c60
-rw-r--r--tools/perf/util/probe-event.h6
-rw-r--r--tools/perf/util/probe-finder.c15
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/target.c6
-rw-r--r--tools/testing/nvdimm/test/nfit.c2
-rwxr-xr-xtools/testing/selftests/ntb/ntb_test.sh422
-rw-r--r--tools/testing/selftests/powerpc/Makefile2
-rw-r--r--tools/testing/selftests/timers/rtctest.c13
-rw-r--r--tools/virtio/linux/dma-mapping.h16
-rw-r--r--tools/virtio/linux/kernel.h14
-rw-r--r--tools/virtio/linux/slab.h4
-rw-r--r--tools/virtio/linux/virtio.h6
-rw-r--r--tools/virtio/linux/virtio_config.h13
-rw-r--r--tools/virtio/ringtest/ptr_ring.c1
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c21
-rw-r--r--virt/kvm/arm/vgic/vgic-irqfd.c116
-rw-r--r--virt/kvm/arm/vgic/vgic.c7
-rw-r--r--virt/kvm/irqchip.c28
-rw-r--r--virt/kvm/kvm_main.c16
1675 files changed, 54988 insertions, 76330 deletions
diff --git a/.mailmap b/.mailmap
index c0d57049d3f0..2a91c14c80bf 100644
--- a/.mailmap
+++ b/.mailmap
@@ -96,7 +96,13 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
Mark Brown <broonie@sirena.org.uk>
Matthieu CASTET <castet.matthieu@free.fr>
-Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com> <mchehab@infradead.org> <mchehab@redhat.com> <m.chehab@samsung.com> <mchehab@osg.samsung.com> <mchehab@s-opensource.com>
+Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@brturbo.com.br>
+Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com>
+Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@infradead.org>
+Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@redhat.com>
+Mauro Carvalho Chehab <mchehab@kernel.org> <m.chehab@samsung.com>
+Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@osg.samsung.com>
+Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@s-opensource.com>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
Mayuresh Janorkar <mayur@ti.com>
@@ -132,7 +138,10 @@ Santosh Shilimkar <santosh.shilimkar@oracle.org>
Sascha Hauer <s.hauer@pengutronix.de>
S.Çağlar Onur <caglar@pardus.org.tr>
Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
-Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com> <shuah.khan@hp.com> <shuahkh@osg.samsung.com> <shuah.kh@samsung.com>
+Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
+Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
+Shuah Khan <shuah@kernel.org> <shuahkh@osg.samsung.com>
+Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
Simon Kelley <simon@thekelleys.org.uk>
Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
Stephen Hemminger <shemminger@osdl.org>
diff --git a/Documentation/ABI/testing/sysfs-class-pwm b/Documentation/ABI/testing/sysfs-class-pwm
index c479d77b67c5..c20e61354561 100644
--- a/Documentation/ABI/testing/sysfs-class-pwm
+++ b/Documentation/ABI/testing/sysfs-class-pwm
@@ -77,3 +77,12 @@ Description:
Enable/disable the PWM signal.
0 is disabled
1 is enabled
+
+What: /sys/class/pwm/pwmchipN/pwmX/capture
+Date: June 2016
+KernelVersion: 4.8
+Contact: Lee Jones <lee.jones@linaro.org>
+Description:
+ Capture information about a PWM signal. The output format is a
+ pair unsigned integers (period and duty cycle), separated by a
+ single space.
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f279c3b..1d26eeb6b5f6 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -369,35 +369,32 @@ See also dma_map_single().
dma_addr_t
dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
void
dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
int
dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
void
dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
The four functions above are just like the counterpart functions
without the _attrs suffixes, except that they pass an optional
-struct dma_attrs*.
-
-struct dma_attrs encapsulates a set of "DMA attributes". For the
-definition of struct dma_attrs see linux/dma-attrs.h.
+dma_attrs.
The interpretation of DMA attributes is architecture-specific, and
each attribute should be documented in Documentation/DMA-attributes.txt.
-If struct dma_attrs* is NULL, the semantics of each of these
-functions is identical to those of the corresponding function
+If dma_attrs are 0, the semantics of each of these functions
+is identical to those of the corresponding function
without the _attrs suffix. As a result dma_map_single_attrs()
can generally replace dma_map_single(), etc.
@@ -405,15 +402,15 @@ As an example of the use of the *_attrs functions, here's how
you could pass an attribute DMA_ATTR_FOO when mapping memory
for DMA:
-#include <linux/dma-attrs.h>
-/* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and
+#include <linux/dma-mapping.h>
+/* DMA_ATTR_FOO should be defined in linux/dma-mapping.h and
* documented in Documentation/DMA-attributes.txt */
...
- DEFINE_DMA_ATTRS(attrs);
- dma_set_attr(DMA_ATTR_FOO, &attrs);
+ unsigned long attr;
+ attr |= DMA_ATTR_FOO;
....
- n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, &attr);
+ n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, attr);
....
Architectures that care about DMA_ATTR_FOO would check for its
@@ -422,12 +419,10 @@ routines, e.g.:
void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
....
- int foo = dma_get_attr(DMA_ATTR_FOO, attrs);
- ....
- if (foo)
+ if (attrs & DMA_ATTR_FOO)
/* twizzle the frobnozzle */
....
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index e8cf9cf873b3..2d455a5cf671 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -2,7 +2,7 @@
==============
This document describes the semantics of the DMA attributes that are
-defined in linux/dma-attrs.h.
+defined in linux/dma-mapping.h.
DMA_ATTR_WRITE_BARRIER
----------------------
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 8e6dd4b14314..64460a897f56 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -6,8 +6,6 @@
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
-ifeq ($(IGNORE_DOCBOOKS),)
-
DOCBOOKS := z8530book.xml device-drivers.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
writing_usb_driver.xml networking.xml \
@@ -16,10 +14,16 @@ DOCBOOKS := z8530book.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_api.xml w1.xml \
+ tracepoint.xml w1.xml \
writing_musb_glue_layer.xml crypto-API.xml iio.xml
-include Documentation/DocBook/media/Makefile
+ifeq ($(DOCBOOKS),)
+
+# Skip DocBook build if the user explicitly requested no DOCBOOKS.
+.DEFAULT:
+ @echo " SKIP DocBook $@ target (DOCBOOKS=\"\" specified)."
+
+else
###
# The build process is as follows (targets):
@@ -49,7 +53,6 @@ pdfdocs: $(PDF)
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
htmldocs: $(HTML)
$(call cmd,build_main_index)
- $(call install_media_images)
MAN := $(patsubst %.xml, %.9, $(BOOKS))
mandocs: $(MAN)
@@ -217,19 +220,7 @@ silent_gen_xml = :
-e "s/>/\\&gt;/g"; \
echo "</programlisting>") > $@
-else
-
-# Needed, due to cleanmediadocs
-include Documentation/DocBook/media/Makefile
-
-htmldocs:
-pdfdocs:
-psdocs:
-xmldocs:
-installmandocs:
-
-endif # IGNORE_DOCBOOKS
-
+endif # DOCBOOKS=""
###
# Help targets as used by the top-level makefile
@@ -246,7 +237,7 @@ dochelp:
@echo ' make DOCBOOKS="s1.xml s2.xml" [target] Generate only docs s1.xml s2.xml'
@echo ' valid values for DOCBOOKS are: $(DOCBOOKS)'
@echo
- @echo " make IGNORE_DOCBOOKS=1 [target] Don't generate docs from Docbook"
+ @echo " make DOCBOOKS=\"\" [target] Don't generate docs from Docbook"
@echo ' This is useful to generate only the ReST docs (Sphinx)'
@@ -269,7 +260,7 @@ clean-files := $(DOCBOOKS) \
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
-cleandocs: cleanmediadocs
+cleandocs:
$(Q)rm -f $(call objectify, $(clean-files))
$(Q)rm -rf $(call objectify, $(clean-dirs))
diff --git a/Documentation/DocBook/media/.gitignore b/Documentation/DocBook/media/.gitignore
deleted file mode 100644
index e461c585fde8..000000000000
--- a/Documentation/DocBook/media/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!*.svg
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
deleted file mode 100644
index fdc138624800..000000000000
--- a/Documentation/DocBook/media/Makefile
+++ /dev/null
@@ -1,427 +0,0 @@
-###
-# 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 -f `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/uapi/linux/videodev2.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/audio.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/ca.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/dmx.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/cec.h) \
- $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
-
-DEFINES = \
- $(shell perl -ne 'print "$$1 " if /\#define\s+(DTV_[^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
-
-TYPES = \
- $(shell perl -ne 'print "$$1 " if /^typedef\s+.*\s+(\S+)\;/' $(srctree)/include/uapi/linux/videodev2.h) \
- $(shell perl -ne 'print "$$1 " if /^typedef\s+.*\s+(\S+)\;/' $(srctree)/include/uapi/linux/dvb/frontend.h)
-
-ENUMS = \
- $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' \
- $(srctree)/include/uapi/linux/videodev2.h \
- $(srctree)/include/uapi/linux/dvb/audio.h \
- $(srctree)/include/uapi/linux/dvb/ca.h \
- $(srctree)/include/uapi/linux/dvb/dmx.h \
- $(srctree)/include/uapi/linux/dvb/frontend.h \
- $(srctree)/include/uapi/linux/dvb/net.h \
- $(srctree)/include/uapi/linux/dvb/video.h \
- $(srctree)/include/uapi/linux/media.h \
- $(srctree)/include/uapi/linux/v4l2-mediabus.h \
- $(srctree)/include/uapi/linux/v4l2-subdev.h)
-
-ENUM_DEFS = \
- $(shell perl -e 'open IN,"cat @ARGV| cpp -fpreprocessed |"; while (<IN>) { if ($$enum) {print "$$1\n" if (/\s*([A-Z]\S+)\b/); } $$enum = 0 if ($$enum && /^\}/); $$enum = 1 if(/^\s*enum\s/); }; close IN;' \
- $(srctree)/include/uapi/linux/dvb/dmx.h \
- $(srctree)/include/uapi/linux/dvb/frontend.h)
-
-STRUCTS = \
- $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \
- $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/uapi/linux/dvb/audio.h) \
- $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/ca.h) \
- $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/dmx.h) \
- $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/frontend.h) \
- $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/ && !/_old/)' $(srctree)/include/uapi/linux/dvb/net.h) \
- $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \
- $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
- $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/cec.h) \
- $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
- $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/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_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
- -e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
- -e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
-
-DVB_DOCUMENTED = \
- -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,\(define\s\+\)\(DTV_[A-Z0-9_]\+\)\(\s\+\),\1\<link linkend=\"\2\">\2\<\/link\>\3,g" \
- -e "s,<link\s\+linkend=\".*\">\(__.*_OLD\)<\/link>,\1,g" \
- -e "s/\(linkend\=\"\)FE_SET_PROPERTY/\1FE_GET_PROPERTY/g" \
- -e "s,<link\s\+linkend=\".*\">\(DTV_ISDBS_TS_ID_LEGACY\|DTV_MAX_COMMAND\|DTV_IOCTL_MAX_MSGS\)<\/link>,\1,g" \
-
-#
-# Media targets and dependencies
-#
-
-install_media_images = \
- $(Q)if [ "x$(findstring media_api.xml,$(DOCBOOKS))" != "x" ]; then \
- mkdir -p $(MEDIA_OBJ_DIR)/media_api; \
- cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/*.svg $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api; \
- fi
-
-$(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64
- $(Q)base64 -d $< >$@
-
-$(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES)
- @$($(quiet)gen_xml)
- @(ln -sf `cd $(MEDIA_SRC_DIR) && /bin/pwd`/v4l/*xml $(MEDIA_OBJ_DIR)/)
- @(ln -sf `cd $(MEDIA_SRC_DIR) && /bin/pwd`/dvb/*xml $(MEDIA_OBJ_DIR)/)
-
-$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/uapi/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/uapi/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/uapi/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/uapi/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
- @$($(quiet)gen_xml)
- @( \
- echo "<programlisting>") > $@
- @( \
- for ident in $(ENUM_DEFS) ; do \
- entity=`echo $$ident | tr _ -` ; \
- r="$$r s/([^\w\-])$$ident([^\w\-])/\1\&$$entity\;\2/g;";\
- done; \
- expand --tabs=8 < $< | \
- sed $(ESCAPE) $(DVB_DOCUMENTED) | \
- sed 's/i\.e\./&ie;/' | \
- perl -ne "$$r print $$_;") >> $@
- @( \
- echo "</programlisting>") >> $@
-
-$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/uapi/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
- @$($(quiet)gen_xml)
- @( \
- echo "<programlisting>") > $@
- @( \
- for ident in $(ENUM_DEFS) ; do \
- entity=`echo $$ident | tr _ -` ; \
- r="$$r s/([^\w\-])$$ident([^\w\-])/\1\&$$entity\;\2/g;";\
- done; \
- expand --tabs=8 < $< | \
- sed $(ESCAPE) $(DVB_DOCUMENTED) | \
- sed 's/i\.e\./&ie;/' | \
- perl -ne "$$r print $$_;") >> $@
- @( \
- echo "</programlisting>") >> $@
-
-$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/uapi/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/uapi/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 `echo $(IOCTLS) | sed -e "s,VIDIOC_RESERVED,,"`; do\
- entity=`echo $$ident | tr _ -` ; \
- id=`grep -e "<refname>$$ident" -e "<section id=\"$$ident\"" $$(find $(MEDIA_SRC_DIR) -name *.xml -type f)| sed -r s,"^.*/(.*).xml.*","\1",` ; \
- if [ "$$id" != "" ]; then echo "<!ENTITY $$entity \"<link" \
- "linkend='$$id'><constant>$$ident</constant></link>\">" \
- >>$@ ; else \
- echo "Warning: undocumented ioctl: $$ident. Please document it at the media DocBook!" >&2; \
- fi; \
- done)
- @( \
- echo -e "\n<!-- Defines -->") >>$@
- @( \
- for ident in $(DEFINES) ; do \
- entity=`echo $$ident | tr _ -` ; \
- echo "<!ENTITY $$entity \"<link" \
- "linkend='$$entity'><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<!-- Enum definitions -->") >>$@
- @( \
- for ident in $(ENUM_DEFS) ; do \
- entity=`echo $$ident | tr _ -` ; \
- echo "<!ENTITY $$entity \"<link" \
- "linkend='$$entity'><constant>$$ident</constant></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
deleted file mode 100644
index ccdf2bcda95c..000000000000
--- a/Documentation/DocBook/media/bayer.png.b64
+++ /dev/null
@@ -1,171 +0,0 @@
-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/constraints.png.b64 b/Documentation/DocBook/media/constraints.png.b64
deleted file mode 100644
index 125b4a94962c..000000000000
--- a/Documentation/DocBook/media/constraints.png.b64
+++ /dev/null
@@ -1,59 +0,0 @@
-iVBORw0KGgoAAAANSUhEUgAAAlQAAAFYCAYAAACVsmLPAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
-/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sLCBIAKVtZsMAAAAxxSURBVHja
-7d3ZbqvIAkDRLsv//8v0QytXvpYZap7Wko56OAnE2AXbBSbhOI7jHwAAkr1sAgAAQQUAIKgAAAQV
-AICgAgBAUAEACCoAAEEFACCoAAAQVAAAzb2jvyMEWw0AmFvh37xnhgoAQFABAPT1zvruwtNlAADV
-VLxsyQwVAICgAgAQVAAAggoAQFABACCoYEohuFkugKACsmLq178DIKiAyJgSVQCCCigQU6IKQFAB
-BWJKVAEIKqBgKIkqAEEFFAgkUQUgqIACYSSqAAQViKkwxjIAEFSwbUyJKgBBBWJq8GUCIKhgm5gS
-VQCCCsSUqAIQVMBYoSOqAAQVLOk41lwXAIIKhoqqJyFUYhkACCpYMqpiQqjEMgAQVLBUVKWEUIll
-ACCoYImoygmhEssAQFDBElHVexkACCoAAEEFACCoAAAQVAAAggoAQFABAAgqAAAEFQCAoAIAEFQA
-AIIKAABBBQAgqAAABBUAgKACAOA/b5sAGjsO2wBgMWaoAAAEFQCAoAIAEFQAADtzUXohIQQbAYDi
-Dh9kmYIZKgAAQQUAIKgAAAQVAICgAgAgmU/5VeSTGQDE8InxeZmhAgAQVAAAggoAQFABAAgqAAAE
-FQCAoAIAEFQAAHtyY0/o4O7efe4JCzAXM1QAAIIKAEBQAQAIKgAAQQUAgKACABBUAACCCgBAUAEA
-IKgAAAQVAICgAgAQVAAACCoAAEEFACCoAAAEFVBICGMsAwBBBVPHVE4QlVgGAIIKpo6ps/9utQwA
-BBUsEVMpQVRiGQAIKlgqpmKCqMQyABBUsGRMzbouAAQVNHMca64LAEEFy0WVmAIQVCCqxBSAoAL6
-hI+YAhBUIKrEFICgAvqEkJgCEFQgqo4+3wuAoILto0pMAQgqICOQxBSAoAIyQklMAQgqICOYxBSA
-oAIyokpMAQgqICOqxBTAvN42AYwTVQDMyQwVAICgAgAQVAAAggoAQFABAJDMp/y4FIJtwJx8ehJo
-yQwVAICgAgDoyyk/HnMKhdE5RQ30YoYKAEBQAQAIKgAAQQUAIKgAABBUAACCCgBAUAEACCoAAAQV
-AICgAgAQVAAAggoAAEEFACCoAAAEFQCAoAIAQFABAAgqAABBBQAgqAAAEFQAAIIKAEBQAQAIKgAA
-BBUAgKACABBUAACCCgAAQQUAIKgAAAQVAICgAgBAUAEACCoAAEEFACCoAAAQVAAAggoAQFABAAgq
-AACGCKoQPAs2JQAIquwCUAI2JQAIqowCOPtvbEoAEFQRBaAEbEoAEFQFCkAJ2JQAIKgKFIASsClh
-szEKrDGoXkNuiOPwwim4iezYoc9+39iDfQbVq+mGEFOiCjZ7E23swR6D6tV8Q4gpUQWb7PeNPdhn
-UL26bAgxJapgk/2+sQd7DKr3EDE1y96mUPT1fqgh6Ffosbsz9mDdQfXquiEY/rUKlBtLYgoqDJZB
-Dmjlg8qRWlSBMSSmYLOoKhtUjtCiCowdMQUbRtXLswUgpkBU5XkXf9CmPJZ9nQJrft6Gife9XmC/
-t0mHg9tr3FcJYgrmjilgn8Fa55SfI7WYAvtnYKNBW+8+VLGn/zY6wtd4qDY1iCngx+BtdNCre1G6
-W3gPt7MXUwAwW1CJKjEFCzB2wODtH1SiSkyB/TKw+KB9DfnARJWYAvtnYKLB+m7+AJ+UgL2WTQmT
-jz1jEJVf0ASD7jXck2/vY1PCQscwE+6wfkz1CaqrB6wAbEoQVcBkMdUvqH49cAVgU4KoAiaMqb5B
-9bkBFIBNCaIKmDSm+geVArApYaOxZ4zCuoPq5VkDqL//F1Ow9qASVACV9/9iCtYfVIIKoOL+X0zB
-HoNKUAFU2v+LKdhnUAkqgAZvqoG1B5WgAgAQVAAAggoAQFABAAgqAAAEFQCAoAIAEFQAAIIKAABB
-BQAgqAAABBUAgKACAEBQAQAIKgAAQQUAIKgAABBUAACCCgBAUAEACCoAAAQVAICgAgAY3NsmIEYI
-//3zONK/7u/v/nx+zdPl/1rO0++LWd6vZZ59Xe7jSfnZSq3z6jnJ2ValX09PHj9AD2aoiPJ34Lo6
-wJWKiJQD7N2BN/WAzbNtZTsCuzJDRZeD8XHkH3zPZo5CSJudeTKbdrX+lkE7QkzFbq8VHj/AGTNU
-dDkY1ziw1jjY7nAA/wzKqxnIu5gSPICggoTIuDroXh1YRz3ohuCUlcgESOOUH81iZdR1fJ9+zL1Q
-use1Y6nrvLsearR46rHNAQQVw6l14HtyOurJz5USVqs9LynXt8V+ShBAUMHHQfdzFuMsQGqHSW5M
-PQmrVtdsjRCkOwY5gKBiGne3Okg5WJaMqbuw2uX5+P6aX4H8/f922F4AgorlgyD3hp47z3ycPfZf
-p/FSb00BIKjg4kD8/cm4mFNjKfd/OpsJyb2GJ+V+UzEXSK9wAfuvqGr9s7ooHRiV2yYgDCe8xUOp
-gHny2GNjVdwAOzJDRbUYSfnep8srfdCOWV6tr225ztzt3PpxiTRgdGaoAAAEFQBAX075sbS7C6dH
-OJU0w8/ocQEIKjY2w0F71bAQTMBOnPIDABBUAAB9OeXHY36tCAD8ZoYKAEBQAQD05ZQfl3xSCwDu
-maECABBUAACCCgBAUAEACCqgiRDczwtAUAFZMfXr3wEQVEBkTIkqAEEFFIgpUQUgqIACMSWqAAQV
-UDCURBWAoAIKBJKoAhBUQIEwElUAggrEVBhjGQAIKtg2pkQVgKACMTX4MgEQVLBNTIkqAEEFYkpU
-AQgqYKzQEVUAggqWdBxrrgsAQQVDRdWTECqxDAAEFSwZVTEhVGIZAAgqWCqqUkKoxDIAEFSwRFTl
-hFCJZQAgqGCJqOq9DAAEFQCAoAIAEFQAAAgqAABBBQAwibdNAECqcPKLJo8fH1cNN7+U8up7jpOP
-v6as//PvPr+/xPpTlsEazFABUDSmnsRTie/pvX74ZIYKgKz4+J55+fu7EMLPWZmU2auY9YsjejBD
-BUDRmDk7pdZq/Vf/P2bZT7/2OI7/rU/ICSoAiHIVLS2uFyq5Dtc3kcspPwCairmQvHUghhBOT1U+
-eQx/fyfQBBUALBNrtcPmc/l/QYagAoDqYi9ib/2zPZ2l+hVw7Ms1VAAkKXXbgpIXkH9eIF7r8T15
-bEJLUAHA4wD6FQ5PPoVXc/0ll3/3db/+sCen/ABIio7PU3U5YfIdY0++78n6RzPqxfiUYYYKqh94
-rv/AzFGV8nelouLue3JC5e5XzTx57E777SUcsa+4zxeIo8HlOw/vOgBwLBlqA1drGDNUAACCCgBA
-UAEATM2n/CpyQSIA7MEMFQCAoAIAEFQAAIIKAGBnLkovxI3XAGBfZqgAAAQVAEBfTvlBbXf3I3O6
-GGB6ZqgAAAQVAICgAgAQVAAAggoAAEEFACCoAAAEFQCAoAIAQFABAAgqAABBBQAgqAAAEFQAAIIK
-AEBQAQAIKiBFCGMsAwBBBVPHVE4QlVgGAM29bQIoGFOf/30c7ZcBrV/zd6/Rq6/7fs1/fs3T5Z+9
-AckZO2dvaL6XeffGJ/XxpPxspdZ59ZzkbKve278BM1RQOqaeDvbSy4CW/g5WV6/RUhHRcuwYc2W2
-VY3tP/hzY4YKar5bfLIDeLIMM1WsOnaOI/9AeTZzETt2YmbTrtbfMmhH2PfFbq/Syxxk/2iGCmrF
-1Kzrgplez78OpjUOsDu8qfkMyqsZyLvwSdleNZYpqGASLQe3GSpGHgNXB92r1+6or+sQvInptV+a
-eF/nlB/kDv7aO14xxUpahErqOr7Hc+yF9y3Hbul13l27NPJ+aJBTgYIKRo4qMcXK46b2wTVlHb9m
-3VpcXD/i85Kyb4v9lGCvZQoq2CiqxBQzvfY/ZzHOAqR2mOTG1JOwanXN1ghBunucR3INFYw4qMUU
-K/sLsO9rlXKuXSoZU99jcfXxmPpp5LP7f5W+B9Ukz4GggtGiSkxBn5ja/UL0v3D5/nO1jyq1zWos
-szGn/KDGTinnoliY9TV/FzZnr++U+z+dfcIw93qblPtNxVwUvcIF7N/7uZJRlbLMQS5KN0MFtQ4w
-YgrWGberjs+Y21vExmqN/eDAz0M4jsifrtZ5alh5ZyWmAMbaJxfe75qhgl7veMUUwDIEFfSMKjEF
-sAQXpUOrqJrk5nSwpLvT7yOMxxl+Ro9LUMFQUSWmoP348zN6XIIK7FgAWDWo/DZuAAAXpQMACCoA
-gM7iT/m5BgQA4P+YoQIAEFQAAIIKAEBQAQAIKgAABBUAgKACABBUAAB7+hfHbDX87cMFJQAAAABJ
-RU5ErkJggg==
diff --git a/Documentation/DocBook/media/crop.gif.b64 b/Documentation/DocBook/media/crop.gif.b64
deleted file mode 100644
index 11d936ae72e8..000000000000
--- a/Documentation/DocBook/media/crop.gif.b64
+++ /dev/null
@@ -1,105 +0,0 @@
-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
diff --git a/Documentation/DocBook/media/dvb/.gitignore b/Documentation/DocBook/media/dvb/.gitignore
deleted file mode 100644
index d7ec32eafac9..000000000000
--- a/Documentation/DocBook/media/dvb/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!*.xml
diff --git a/Documentation/DocBook/media/dvb/audio.xml b/Documentation/DocBook/media/dvb/audio.xml
deleted file mode 100644
index ea56743ddbe7..000000000000
--- a/Documentation/DocBook/media/dvb/audio.xml
+++ /dev/null
@@ -1,1314 +0,0 @@
-<title>DVB Audio Device</title>
-<para>The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It
-can be accessed through <constant>/dev/dvb/adapter?/audio?</constant>. Data types and and
-ioctl definitions can be accessed by including <constant>linux/dvb/audio.h</constant> in your
-application.
-</para>
-<para>Please note that some DVB cards don&#8217;t have their own MPEG decoder, which results in
-the omission of the audio and video device.
-</para>
-<para>
-These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
-of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
-have been created to replace that functionality.</para>
-
-<section id="audio_data_types">
-<title>Audio Data Types</title>
-<para>This section describes the structures, data types and defines used when talking to the
-audio device.
-</para>
-
-<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;
-</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
-is selected the stream comes from the application through the <constant>write()</constant> system
-call.
-</para>
-
-</section>
-<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;
-</programlisting>
-
-</section>
-<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_MONO,
- AUDIO_STEREO_SWAPPED
-} audio_channel_select_t;
-</programlisting>
-
-</section>
-<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_mixer_t mixer_state;
-} audio_status_t;
-</programlisting>
-
-</section>
-<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;
-</programlisting>
-
-</section>
-<section id="audio_encodings">
-<title>audio encodings</title>
-<para>A call to AUDIO_GET_CAPABILITIES returns an unsigned integer with the following
-bits set according to the hardwares capabilities.
-</para>
-<programlisting>
- #define AUDIO_CAP_DTS 1
- #define AUDIO_CAP_LPCM 2
- #define AUDIO_CAP_MP1 4
- #define AUDIO_CAP_MP2 8
- #define AUDIO_CAP_MP3 16
- #define AUDIO_CAP_AAC 32
- #define AUDIO_CAP_OGG 64
- #define AUDIO_CAP_SDDS 128
- #define AUDIO_CAP_AC3 256
-</programlisting>
-
-</section>
-<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;
-</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
-right channel at 100% each. Ff Melody is non-zero, the melody channel gets mixed into left
-and right.
-</para>
-
-</section>
-<section id="audio-attributes-t">
-<title>audio attributes</title>
-<para>The following attributes can be set by a call to AUDIO_SET_ATTRIBUTES:
-</para>
-<programlisting>
- typedef uint16_t audio_attributes_t;
- /&#x22C6; bits: descr. &#x22C6;/
- /&#x22C6; 15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, &#x22C6;/
- /&#x22C6; 12 multichannel extension &#x22C6;/
- /&#x22C6; 11-10 audio type (0=not spec, 1=language included) &#x22C6;/
- /&#x22C6; 9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) &#x22C6;/
- /&#x22C6; 7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit, &#x22C6;/
- /&#x22C6; 5- 4 Sample frequency fs (0=48kHz, 1=96kHz) &#x22C6;/
- /&#x22C6; 2- 0 number of audio channels (n+1 channels) &#x22C6;/
-</programlisting>
- </section></section>
-<section id="audio_function_calls">
-<title>Audio Function Calls</title>
-
-
-<section id="audio_fopen">
-<title>open()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call opens a named audio device (e.g. /dev/dvb/adapter0/audio0)
- for subsequent use. When an open() call has succeeded, the device will be ready
- for use. The significance of blocking or non-blocking mode is described in the
- documentation for functions where there is a difference. It does not affect the
- semantics of the open() call itself. A device opened in blocking mode can later
- be put into non-blocking mode (and vice versa) using the F_SETFL command
- of the fcntl system call. This is a standard system call, documented in the Linux
- manual page for fcntl. Only one user can open the Audio Device in O_RDWR
- mode. All other attempts to open the device in this mode will fail, and an error
- code will be returned. If the Audio Device is opened in O_RDONLY mode, the
- only ioctl call that can be used is AUDIO_GET_STATUS. All other call will
- return with an error code.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int open(const char &#x22C6;deviceName, int flags);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>const char
- *deviceName</para>
-</entry><entry
- align="char">
-<para>Name of specific audio device.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int flags</para>
-</entry><entry
- align="char">
-<para>A bit-wise OR of the following flags:</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDONLY read-only access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDWR read/write access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_NONBLOCK open in non-blocking mode</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>(blocking mode is the default)</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<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>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></tbody></tgroup></informaltable>
-
-</section>
-<section id="audio_fclose">
-<title>close()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call closes a previously opened audio device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int close(int fd);</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></tbody></tgroup></informaltable>
-<para>RETURN VALUE</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>
-
-</section>
-<section id="audio_fwrite">
-<title>write()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call can only be used if AUDIO_SOURCE_MEMORY is selected
- in the ioctl call AUDIO_SELECT_SOURCE. The data provided shall be in
- PES format. If O_NONBLOCK is not specified the function will block until
- buffer space is available. The amount of data to be transferred is implied by
- count.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>size_t write(int fd, const void &#x22C6;buf, size_t count);</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>void *buf</para>
-</entry><entry
- align="char">
-<para>Pointer to the buffer containing the PES data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t count</para>
-</entry><entry
- align="char">
-<para>Size of buf.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURN VALUE</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Mode AUDIO_SOURCE_MEMORY not selected.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOMEM</para>
-</entry><entry
- align="char">
-<para>Attempted to write more data than the internal buffer can
- hold.</para>
-</entry>
- </row><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>
-
-</section><section id="AUDIO_STOP"
-role="subsection"><title>AUDIO_STOP</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to stop playing the current stream.</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_STOP);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_STOP for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_PLAY"
-role="subsection"><title>AUDIO_PLAY</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to start playing an audio stream from the
- selected source.</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_PLAY);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_PLAY for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_PAUSE"
-role="subsection"><title>AUDIO_PAUSE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call suspends the audio stream being played. Decoding and playing
- are paused. It is then possible to restart again decoding and playing process of
- the audio stream using AUDIO_CONTINUE command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>If AUDIO_SOURCE_MEMORY is selected in the ioctl call
- AUDIO_SELECT_SOURCE, the DVB-subsystem will not decode (consume)
- any more data until the ioctl call AUDIO_CONTINUE or AUDIO_PLAY is
- performed.</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_PAUSE);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_PAUSE for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&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>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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_CONTINUE for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SELECT_SOURCE"
-role="subsection"><title>AUDIO_SELECT_SOURCE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call informs the audio device which source shall be used
- for the input data. The possible sources are demux or memory. If
- AUDIO_SOURCE_MEMORY is selected, the data is fed to the Audio Device
- through the write command.</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_SELECT_SOURCE,
- audio_stream_source_t source);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SELECT_SOURCE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_stream_source_t
- source</para>
-</entry><entry
- align="char">
-<para>Indicates the source that shall be used for the Audio
- stream.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_MUTE"
-role="subsection"><title>AUDIO_SET_MUTE</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-&VIDIOC-DECODER-CMD; with the <constant>V4L2_DEC_CMD_START_MUTE_AUDIO</constant> flag instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the audio device to mute the stream that is currently being
- played.</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_SET_MUTE,
- boolean state);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_MUTE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>boolean state</para>
-</entry><entry
- align="char">
-<para>Indicates if audio device shall mute or not.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>TRUE Audio Mute</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>FALSE Audio Un-mute</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_AV_SYNC"
-role="subsection"><title>AUDIO_SET_AV_SYNC</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to turn ON or OFF A/V synchronization.</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_SET_AV_SYNC,
- boolean state);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_AV_SYNC for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>boolean state</para>
-</entry><entry
- align="char">
-<para>Tells the DVB subsystem if A/V synchronization shall be
- ON or OFF.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>TRUE AV-sync ON</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>FALSE AV-sync OFF</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_BYPASS_MODE"
-role="subsection"><title>AUDIO_SET_BYPASS_MODE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to bypass the Audio decoder and forward
- the stream without decoding. This mode shall be used if streams that can&#8217;t be
- handled by the DVB system shall be decoded. Dolby DigitalTM streams are
- automatically forwarded by the DVB subsystem if the hardware can handle it.</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_SET_BYPASS_MODE, boolean mode);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_BYPASS_MODE for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>boolean mode</para>
-</entry><entry
- align="char">
-<para>Enables or disables the decoding of the current Audio
- stream in the DVB subsystem.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>TRUE Bypass is disabled</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>FALSE Bypass is enabled</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_CHANNEL_SELECT"
-role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-<constant>V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK</constant> control instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to select the requested channel if possible.</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_CHANNEL_SELECT, audio_channel_select_t);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_CHANNEL_SELECT for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_channel_select_t
- ch</para>
-</entry><entry
- align="char">
-<para>Select the output format of the audio (mono left/right,
- stereo).</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_BILINGUAL_CHANNEL_SELECT"
-role="subsection"><title>AUDIO_BILINGUAL_CHANNEL_SELECT</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. It has been replaced by
-the V4L2 <constant>V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK</constant> control
-for MPEG decoders controlled through V4L2.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to select the requested channel for bilingual streams if possible.</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_BILINGUAL_CHANNEL_SELECT, audio_channel_select_t);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_BILINGUAL_CHANNEL_SELECT for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_channel_select_t
-ch</para>
-</entry><entry
- align="char">
-<para>Select the output format of the audio (mono left/right,
- stereo).</para>
-</entry>
- </row>
-</tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_GET_PTS"
-role="subsection"><title>AUDIO_GET_PTS</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. If you need this functionality,
-then please contact the linux-media mailing list (&v4l-ml;).</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to return the current PTS timestamp.</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_GET_PTS, __u64 *pts);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_GET_PTS for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u64 *pts
-</para>
-</entry><entry
- align="char">
-<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
-</para>
-<para>
-The PTS should belong to the currently played
-frame if possible, but may also be a value close to it
-like the PTS of the last decoded frame or the last PTS
-extracted by the PES parser.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_GET_STATUS"
-role="subsection"><title>AUDIO_GET_STATUS</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to return the current state of the Audio
- 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 = AUDIO_GET_STATUS,
- struct audio_status &#x22C6;status);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_GET_STATUS for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct audio_status
- *status</para>
-</entry><entry
- align="char">
-<para>Returns the current state of Audio Device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_GET_CAPABILITIES"
-role="subsection"><title>AUDIO_GET_CAPABILITIES</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to tell us about the decoding capabilities
- of the audio hardware.</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_GET_CAPABILITIES, unsigned int &#x22C6;cap);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_GET_CAPABILITIES for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>unsigned int *cap</para>
-</entry><entry
- align="char">
-<para>Returns a bit array of supported sound formats.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_CLEAR_BUFFER"
-role="subsection"><title>AUDIO_CLEAR_BUFFER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Audio Device to clear all software and hardware buffers
- of the audio decoder 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 = AUDIO_CLEAR_BUFFER);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_CLEAR_BUFFER for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_ID"
-role="subsection"><title>AUDIO_SET_ID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl selects which sub-stream is to be decoded if a program or system
- stream is sent to the video device. If no audio stream type is set the id has to be
- in [0xC0,0xDF] for MPEG sound, in [0x80,0x87] for AC3 and in [0xA0,0xA7]
- for LPCM. More specifications may follow for other stream types. If the stream
- type is set the id just specifies the substream id of the audio stream and only
- the first 5 bits are recognized.</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_SET_ID, int
- id);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_ID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int id</para>
-</entry><entry
- align="char">
-<para>audio sub-stream id</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_MIXER"
-role="subsection"><title>AUDIO_SET_MIXER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl lets you adjust the mixer settings of the audio decoder.</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_SET_MIXER,
- audio_mixer_t &#x22C6;mix);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_ID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_mixer_t *mix</para>
-</entry><entry
- align="char">
-<para>mixer settings.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="AUDIO_SET_STREAMTYPE"
-role="subsection"><title>AUDIO_SET_STREAMTYPE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl tells the driver which kind of audio stream to expect. This is useful
- if the stream offers several audio sub-streams like LPCM and AC3.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = AUDIO_SET_STREAMTYPE,
- int type);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_STREAMTYPE for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int type</para>
-</entry><entry
- align="char">
-<para>stream type</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><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>
-
-</section><section id="AUDIO_SET_EXT_ID"
-role="subsection"><title>AUDIO_SET_EXT_ID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl can be used to set the extension id for MPEG streams in DVD
- playback. Only the first 3 bits are recognized.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = AUDIO_SET_EXT_ID, int
- id);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_EXT_ID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int id</para>
-</entry><entry
- align="char">
-<para>audio sub_stream_id</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>id is not a valid id.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="AUDIO_SET_ATTRIBUTES"
-role="subsection"><title>AUDIO_SET_ATTRIBUTES</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is intended for DVD playback and allows you to set certain
- information about the audio stream.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = AUDIO_SET_ATTRIBUTES,
- audio_attributes_t attr );</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_ATTRIBUTES for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_attributes_t
- attr</para>
-</entry><entry
- align="char">
-<para>audio attributes according to section ??</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>attr is not a valid or supported attribute setting.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="AUDIO_SET_KARAOKE"
-role="subsection"><title>AUDIO_SET_KARAOKE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl allows one to set the mixer settings for a karaoke DVD.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = AUDIO_SET_KARAOKE,
- audio_karaoke_t &#x22C6;karaoke);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals AUDIO_SET_KARAOKE for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>audio_karaoke_t
- *karaoke</para>
-</entry><entry
- align="char">
-<para>karaoke settings according to section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>karaoke is not a valid or supported karaoke setting.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section>
-</section>
diff --git a/Documentation/DocBook/media/dvb/ca.xml b/Documentation/DocBook/media/dvb/ca.xml
deleted file mode 100644
index d0b07e763908..000000000000
--- a/Documentation/DocBook/media/dvb/ca.xml
+++ /dev/null
@@ -1,582 +0,0 @@
-<title>DVB CA Device</title>
-<para>The DVB CA device controls the conditional access hardware. It can be accessed through
-<constant>/dev/dvb/adapter?/ca?</constant>. Data types and and ioctl definitions can be accessed by
-including <constant>linux/dvb/ca.h</constant> in your application.
-</para>
-
-<section id="ca_data_types">
-<title>CA Data Types</title>
-
-
-<section id="ca-slot-info">
-<title>ca_slot_info_t</title>
- <programlisting>
-typedef struct ca_slot_info {
- 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;/
-
- 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">
-<title>ca_descr_info_t</title>
-<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-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">
-<title>ca_msg_t</title>
-<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">
-<title>ca_descr_t</title>
-<programlisting>
-typedef struct ca_descr {
- unsigned int index;
- unsigned int parity;
- unsigned char cw[8];
-} ca_descr_t;
-</programlisting>
-</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>
-
-
-<section id="ca_fopen">
-<title>open()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call opens a named ca device (e.g. /dev/ost/ca) for subsequent use.</para>
-<para>When an open() call has succeeded, the device will be ready for use.
- The significance of blocking or non-blocking mode is described in the
- documentation for functions where there is a difference. It does not affect the
- semantics of the open() call itself. A device opened in blocking mode can later
- be put into non-blocking mode (and vice versa) using the F_SETFL command
- of the fcntl system call. This is a standard system call, documented in the Linux
- manual page for fcntl. Only one user can open the CA Device in O_RDWR
- mode. All other attempts to open the device in this mode will fail, and an error
- code will be returned.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int open(const char &#x22C6;deviceName, int flags);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>const char
- *deviceName</para>
-</entry><entry
- align="char">
-<para>Name of specific video device.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int flags</para>
-</entry><entry
- align="char">
-<para>A bit-wise OR of the following flags:</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDONLY read-only access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDWR read/write access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_NONBLOCK open in non-blocking mode</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>(blocking mode is the default)</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<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">
-<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></tbody></tgroup></informaltable>
-
-</section>
-<section id="ca_fclose">
-<title>close()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call closes a previously opened audio device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int close(int fd);</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></tbody></tgroup></informaltable>
-<para>RETURN VALUE</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>
- </section>
-
-<section id="CA_RESET"
-role="subsection"><title>CA_RESET</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_RESET);
-</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_RESET for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_GET_CAP"
-role="subsection"><title>CA_GET_CAP</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_GET_CAP,
- ca_caps_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_GET_CAP for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_caps_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_GET_SLOT_INFO"
-role="subsection"><title>CA_GET_SLOT_INFO</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_GET_SLOT_INFO,
- ca_slot_info_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_GET_SLOT_INFO for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_slot_info_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_GET_DESCR_INFO"
-role="subsection"><title>CA_GET_DESCR_INFO</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_GET_DESCR_INFO,
- ca_descr_info_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_GET_DESCR_INFO for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_descr_info_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_GET_MSG"
-role="subsection"><title>CA_GET_MSG</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_GET_MSG,
- ca_msg_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_GET_MSG for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_msg_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_SEND_MSG"
-role="subsection"><title>CA_SEND_MSG</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_SEND_MSG,
- ca_msg_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_SEND_MSG for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_msg_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_SET_DESCR"
-role="subsection"><title>CA_SET_DESCR</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_SET_DESCR,
- ca_descr_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_SET_DESCR for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_descr_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="CA_SET_PID"
-role="subsection"><title>CA_SET_PID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = CA_SET_PID,
- ca_pid_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals CA_SET_PID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ca_pid_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-</section>
diff --git a/Documentation/DocBook/media/dvb/demux.xml b/Documentation/DocBook/media/dvb/demux.xml
deleted file mode 100644
index 34f2fb1cd601..000000000000
--- a/Documentation/DocBook/media/dvb/demux.xml
+++ /dev/null
@@ -1,1162 +0,0 @@
-<title>DVB Demux Device</title>
-
-<para>The DVB demux device controls the filters of the DVB hardware/software. It can be
-accessed through <constant>/dev/adapter?/demux?</constant>. Data types and and ioctl definitions can be
-accessed by including <constant>linux/dvb/dmx.h</constant> in your application.
-</para>
-<section id="dmx_types">
-<title>Demux Data Types</title>
-
-<section id="dmx-output-t">
-<title>Output for the demux</title>
-
-<table pgwide="1" frame="none" id="dmx-output">
- <title>enum dmx_output</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="DMX-OUT-DECODER">DMX_OUT_DECODER</entry>
- <entry>Streaming directly to decoder.</entry>
- </row><row>
- <entry align="char" id="DMX-OUT-TAP">DMX_OUT_TAP</entry>
- <entry>Output going to a memory buffer (to be retrieved via the
- read command). Delivers the stream output to the demux
- device on which the ioctl is called.</entry>
- </row><row>
- <entry align="char" id="DMX-OUT-TS-TAP">DMX_OUT_TS_TAP</entry>
- <entry>Output multiplexed into a new TS (to be retrieved by
- reading from the logical DVR device). Routes output to the
- logical DVR device <constant>/dev/dvb/adapter?/dvr?</constant>,
- which delivers a TS multiplexed from all filters for which
- <constant>DMX_OUT_TS_TAP</constant> was specified.</entry>
- </row><row>
- <entry align="char" id="DMX-OUT-TSDEMUX-TAP">DMX_OUT_TSDEMUX_TAP</entry>
- <entry>Like &DMX-OUT-TS-TAP; but retrieved from the DMX
- device.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-</section>
-
-<section id="dmx-input-t">
-<title>dmx_input_t</title>
-<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">
-<title>dmx_pes_type_t</title>
-<programlisting>
-typedef enum
-{
- DMX_PES_AUDIO0,
- DMX_PES_VIDEO0,
- DMX_PES_TELETEXT0,
- DMX_PES_SUBTITLE0,
- DMX_PES_PCR0,
-
- DMX_PES_AUDIO1,
- DMX_PES_VIDEO1,
- DMX_PES_TELETEXT1,
- DMX_PES_SUBTITLE1,
- DMX_PES_PCR1,
-
- 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">
-<title>struct dmx_filter</title>
- <programlisting>
- typedef struct dmx_filter
-{
- __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">
-<title>struct dmx_sct_filter_params</title>
-<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">
-<title>struct dmx_pes_filter_params</title>
-<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">
-<title>struct dmx_event</title>
- <programlisting>
- struct dmx_event
- {
- dmx_event_t event;
- time_t timeStamp;
- union
- {
- dmx_scrambling_status_t scrambling;
- } u;
- };
-</programlisting>
-</section>
-
-<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;/
- __u64 stc; /&#x22C6; output: stc in 'base'&#x22C6;90 kHz units &#x22C6;/
-};
-</programlisting>
-</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>
-
-<section id="dmx_fopen">
-<title>open()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call, used with a device name of /dev/dvb/adapter0/demux0,
- allocates a new filter and returns a handle which can be used for subsequent
- control of that filter. This call has to be made for each filter to be used, i.e. every
- returned file descriptor is a reference to a single filter. /dev/dvb/adapter0/dvr0
- is a logical device to be used for retrieving Transport Streams for digital
- video recording. When reading from this device a transport stream containing
- the packets from all PES filters set in the corresponding demux device
- (/dev/dvb/adapter0/demux0) having the output set to DMX_OUT_TS_TAP. A
- recorded Transport Stream is replayed by writing to this device. </para>
-<para>The significance of blocking or non-blocking mode is described in the
- documentation for functions where there is a difference. It does not affect the
- semantics of the open() call itself. A device opened in blocking mode can later
- be put into non-blocking mode (and vice versa) using the F_SETFL command
- of the fcntl system call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int open(const char &#x22C6;deviceName, int flags);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>const char
- *deviceName</para>
-</entry><entry
- align="char">
-<para>Name of demux device.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int flags</para>
-</entry><entry
- align="char">
-<para>A bit-wise OR of the following flags:</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDWR read/write access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_NONBLOCK open in non-blocking mode</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>(blocking mode is the default)</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<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>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EMFILE</para>
-</entry><entry
- align="char">
-<para>&#8220;Too many open files&#8221;, i.e. no more filters available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ENOMEM</para>
-</entry><entry
- align="char">
-<para>The driver failed to allocate enough memory.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="dmx_fclose">
-<title>close()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call deactivates and deallocates a filter that was previously
- allocated via the open() call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int close(int fd);</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></tbody></tgroup></informaltable>
-<para>RETURN VALUE</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>
-</section>
-
-<section id="dmx_fread">
-<title>read()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call returns filtered data, which might be section or PES data. The
- filtered data is transferred from the driver&#8217;s internal circular buffer to buf. The
- maximum amount of data to be transferred is implied by count.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>When returning section data the driver always tries to return a complete single
- section (even though buf would provide buffer space for more data). If the size
- of the buffer is smaller than the section as much as possible will be returned,
- and the remaining data will be provided in subsequent calls.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The size of the internal buffer is 2 * 4096 bytes (the size of two maximum
- sized sections) by default. The size of this buffer may be changed by using the
- DMX_SET_BUFFER_SIZE function. If the buffer is not large enough, or if
- the read operations are not performed fast enough, this may result in a buffer
- overflow error. In this case EOVERFLOW will be returned, and the circular
- buffer will be emptied. This call is blocking if there is no data to return, i.e. the
- process will be put to sleep waiting for data, unless the O_NONBLOCK flag
- is specified.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>Note that in order to be able to read, the filtering process has to be started
- by defining either a section or a PES filter by means of the ioctl functions,
- and then starting the filtering process via the DMX_START ioctl function
- or by setting the DMX_IMMEDIATE_START flag. If the reading is done
- from a logical DVR demux device, the data will constitute a Transport Stream
- including the packets from all PES filters in the corresponding demux device
- /dev/dvb/adapter0/demux0 having the output set to DMX_OUT_TS_TAP.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>size_t read(int fd, void &#x22C6;buf, size_t count);</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>void *buf</para>
-</entry><entry
- align="char">
-<para>Pointer to the buffer to be used for returned filtered data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t count</para>
-</entry><entry
- align="char">
-<para>Size of buf.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURN VALUE</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EWOULDBLOCK</para>
-</entry><entry
- align="char">
-<para>No data to return and O_NONBLOCK was specified.</para>
-</entry>
- </row><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>ECRC</para>
-</entry><entry
- align="char">
-<para>Last section had a CRC error - no data returned. The
- buffer is flushed.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EOVERFLOW</para>
-</entry><entry
- align="char">
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>The filtered data was not read from the buffer in due
- time, resulting in non-read data being lost. The buffer is
- flushed.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>ETIMEDOUT</para>
-</entry><entry
- align="char">
-<para>The section was not loaded within the stated timeout
- period. See ioctl DMX_SET_FILTER for how to set a
- timeout.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>The driver failed to write to the callers buffer due to an
- invalid *buf pointer.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="dmx_fwrite">
-<title>write()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call is only provided by the logical device /dev/dvb/adapter0/dvr0,
- associated with the physical demux device that provides the actual DVR
- functionality. It is used for replay of a digitally recorded Transport Stream.
- Matching filters have to be defined in the corresponding physical demux
- device, /dev/dvb/adapter0/demux0. The amount of data to be transferred is
- implied by count.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>ssize_t write(int fd, const void &#x22C6;buf, size_t
- count);</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>void *buf</para>
-</entry><entry
- align="char">
-<para>Pointer to the buffer containing the Transport Stream.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t count</para>
-</entry><entry
- align="char">
-<para>Size of buf.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURN VALUE</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EWOULDBLOCK</para>
-</entry><entry
- align="char">
-<para>No data was written. This
- might happen if O_NONBLOCK was specified and there
- is no more buffer space available (if O_NONBLOCK is
- not specified the function will block until buffer space is
- available).</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>This error code indicates that there are conflicting
- requests. The corresponding demux device is setup to
- receive data from the front- end. Make sure that these
- filters are stopped and that the filters with input set to
- DMX_IN_DVR are started.</para>
-</entry>
- </row><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>
-</section>
-
-<section id="DMX_START">
-<title>DMX_START</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call is used to start the actual filtering operation defined via the ioctl
- calls DMX_SET_FILTER or DMX_SET_PES_FILTER.</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 = DMX_START);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_START for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid argument, i.e. no filtering parameters provided via
- the DMX_SET_FILTER or DMX_SET_PES_FILTER
- functions.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>This error code indicates that there are conflicting
- requests. There are active filters filtering data from
- another input source. Make sure that these filters are
- stopped before starting this filter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="DMX_STOP">
-<title>DMX_STOP</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call is used to stop the actual filtering operation defined via the
- ioctl calls DMX_SET_FILTER or DMX_SET_PES_FILTER and started via
- the DMX_START command.</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 = DMX_STOP);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_STOP for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_SET_FILTER">
-<title>DMX_SET_FILTER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call sets up a filter according to the filter and mask parameters
- provided. A timeout may be defined stating number of seconds to wait for a
- section to be loaded. A value of 0 means that no timeout should be applied.
- Finally there is a flag field where it is possible to state whether a section should
- be CRC-checked, whether the filter should be a &#8221;one-shot&#8221; filter, i.e. if the
- filtering operation should be stopped after the first section is received, and
- whether the filtering operation should be started immediately (without waiting
- for a DMX_START ioctl call). If a filter was previously set-up, this filter will
- be canceled, and the receive buffer will be flushed.</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 = DMX_SET_FILTER,
- struct dmx_sct_filter_params &#x22C6;params);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_SET_FILTER for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- dmx_sct_filter_params
- *params</para>
-</entry><entry
- align="char">
-<para>Pointer to structure containing filter parameters.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_SET_PES_FILTER">
-<title>DMX_SET_PES_FILTER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call sets up a PES filter according to the parameters provided. By a
- PES filter is meant a filter that is based just on the packet identifier (PID), i.e.
- no PES header or payload filtering capability is supported.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The transport stream destination for the filtered output may be set. Also the
- PES type may be stated in order to be able to e.g. direct a video stream directly
- to the video decoder. Finally there is a flag field where it is possible to state
- whether the filtering operation should be started immediately (without waiting
- for a DMX_START ioctl call). If a filter was previously set-up, this filter will
- be cancelled, and the receive buffer will be flushed.</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 = DMX_SET_PES_FILTER,
- struct dmx_pes_filter_params &#x22C6;params);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_SET_PES_FILTER for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- dmx_pes_filter_params
- *params</para>
-</entry><entry
- align="char">
-<para>Pointer to structure containing filter parameters.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EBUSY</para>
-</entry><entry
- align="char">
-<para>This error code indicates that there are conflicting
- requests. There are active filters filtering data from
- another input source. Make sure that these filters are
- stopped before starting this filter.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="DMX_SET_BUFFER_SIZE">
-<title>DMX_SET_BUFFER_SIZE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call is used to set the size of the circular buffer used for filtered data.
- The default size is two maximum sized sections, i.e. if this function is not called
- a buffer size of 2 * 4096 bytes will be used.</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 =
- DMX_SET_BUFFER_SIZE, unsigned long size);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_SET_BUFFER_SIZE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>unsigned long size</para>
-</entry><entry
- align="char">
-<para>Size of circular buffer.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_GET_EVENT">
-<title>DMX_GET_EVENT</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns an event if available. If an event is not available,
- the behavior depends on whether the device is in blocking or non-blocking
- mode. In the latter case, the call fails immediately with errno set to
- EWOULDBLOCK. In the former case, the call blocks until an event becomes
- available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The standard Linux poll() and/or select() system calls can be used with the
- device file descriptor to watch for new events. For select(), the file descriptor
- should be included in the exceptfds argument, and for poll(), POLLPRI should
- be specified as the wake-up condition. Only the latest event for each filter is
- saved.</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 = DMX_GET_EVENT,
- struct dmx_event &#x22C6;ev);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_GET_EVENT for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct dmx_event *ev</para>
-</entry><entry
- align="char">
-<para>Pointer to the location where the event is to be stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EWOULDBLOCK</para>
-</entry><entry
- align="char">
-<para>There is no event pending, and the device is in
- non-blocking mode.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-</section>
-
-<section id="DMX_GET_STC">
-<title>DMX_GET_STC</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns the current value of the system time counter (which is driven
- by a PES filter of type DMX_PES_PCR). Some hardware supports more than one
- STC, so you must specify which one by setting the num field of stc before the ioctl
- (range 0...n). The result is returned in form of a ratio with a 64 bit numerator
- and a 32 bit denominator, so the real 90kHz STC value is stc-&#x003E;stc /
- stc-&#x003E;base
- .</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 = DMX_GET_STC, struct
- dmx_stc &#x22C6;stc);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_GET_STC for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct dmx_stc *stc</para>
-</entry><entry
- align="char">
-<para>Pointer to the location where the stc is to be stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid stc number.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section>
-
-<section id="DMX_GET_PES_PIDS"
-role="subsection"><title>DMX_GET_PES_PIDS</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = DMX_GET_PES_PIDS,
- __u16[5]);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_GET_PES_PIDS for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16[5]
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_GET_CAPS"
-role="subsection"><title>DMX_GET_CAPS</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = DMX_GET_CAPS,
- dmx_caps_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_GET_CAPS for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_caps_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_SET_SOURCE"
-role="subsection"><title>DMX_SET_SOURCE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is undocumented. Documentation is welcome.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = DMX_SET_SOURCE,
- dmx_source_t *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_SET_SOURCE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>dmx_source_t *
-</para>
-</entry><entry
- align="char">
-<para>Undocumented.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_ADD_PID"
-role="subsection"><title>DMX_ADD_PID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call allows to add multiple PIDs to a transport stream filter
-previously set up with DMX_SET_PES_FILTER and output equal to DMX_OUT_TSDEMUX_TAP.
-</para></entry></row><row><entry align="char"><para>
-It is used by readers of /dev/dvb/adapterX/demuxY.
-</para></entry></row><row><entry align="char"><para>
-It may be called at any time, i.e. before or after the first filter on the
-shared file descriptor was started. It makes it possible to record multiple
-services without the need to de-multiplex or re-multiplex TS packets.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = DMX_ADD_PID,
- __u16 *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_ADD_PID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 *
-</para>
-</entry><entry
- align="char">
-<para>PID number to be filtered.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-<section id="DMX_REMOVE_PID"
-role="subsection"><title>DMX_REMOVE_PID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call allows to remove a PID when multiple PIDs are set on a
-transport stream filter, e. g. a filter previously set up with output equal to
-DMX_OUT_TSDEMUX_TAP, created via either DMX_SET_PES_FILTER or DMX_ADD_PID.
-</para></entry></row><row><entry align="char"><para>
-It is used by readers of /dev/dvb/adapterX/demuxY.
-</para></entry></row><row><entry align="char"><para>
-It may be called at any time, i.e. before or after the first filter on the
-shared file descriptor was started. It makes it possible to record multiple
-services without the need to de-multiplex or re-multiplex TS packets.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = DMX_REMOVE_PID,
- __u16 *);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals DMX_REMOVE_PID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u16 *
-</para>
-</entry><entry
- align="char">
-<para>PID of the PES filter to be removed.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-</section>
-
-
-</section>
diff --git a/Documentation/DocBook/media/dvb/dvbapi.xml b/Documentation/DocBook/media/dvb/dvbapi.xml
deleted file mode 100644
index 8576481e20ae..000000000000
--- a/Documentation/DocBook/media/dvb/dvbapi.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<partinfo>
-<authorgroup>
-<author>
-<firstname>Ralph</firstname>
-<surname>Metzler</surname>
-<othername role="mi">J. K.</othername>
-<affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
-</author>
-<author>
-<firstname>Marcus</firstname>
-<surname>Metzler</surname>
-<othername role="mi">O. C.</othername>
-<affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
-</author>
-</authorgroup>
-<authorgroup>
-<author>
-<firstname>Mauro</firstname>
-<othername role="mi">Carvalho</othername>
-<surname>Chehab</surname>
-<affiliation><address><email>m.chehab@samsung.com</email></address></affiliation>
-<contrib>Ported document to Docbook XML.</contrib>
-</author>
-</authorgroup>
-<copyright>
- <year>2002</year>
- <year>2003</year>
- <holder>Convergence GmbH</holder>
-</copyright>
-<copyright>
- <year>2009-2015</year>
- <holder>Mauro Carvalho Chehab</holder>
-</copyright>
-
-<revhistory>
-<!-- Put document revisions here, newest first. -->
-<revision>
- <revnumber>2.1.0</revnumber>
- <date>2015-05-29</date>
- <authorinitials>mcc</authorinitials>
- <revremark>
- DocBook improvements and cleanups, in order to document the
- system calls on a more standard way and provide more description
- about the current DVB API.
- </revremark>
-</revision>
-<revision>
- <revnumber>2.0.4</revnumber>
- <date>2011-05-06</date>
- <authorinitials>mcc</authorinitials>
- <revremark>
- Add more information about DVB APIv5, better describing the frontend GET/SET props ioctl's.
- </revremark>
-</revision>
-<revision>
- <revnumber>2.0.3</revnumber>
- <date>2010-07-03</date>
- <authorinitials>mcc</authorinitials>
- <revremark>
- Add some frontend capabilities flags, present on kernel, but missing at the specs.
- </revremark>
-</revision>
-<revision>
- <revnumber>2.0.2</revnumber>
- <date>2009-10-25</date>
- <authorinitials>mcc</authorinitials>
- <revremark>
- documents FE_SET_FRONTEND_TUNE_MODE and FE_DISHETWORK_SEND_LEGACY_CMD ioctls.
- </revremark>
-</revision>
-<revision>
-<revnumber>2.0.1</revnumber>
-<date>2009-09-16</date>
-<authorinitials>mcc</authorinitials>
-<revremark>
-Added ISDB-T test originally written by Patrick Boettcher
-</revremark>
-</revision>
-<revision>
-<revnumber>2.0.0</revnumber>
-<date>2009-09-06</date>
-<authorinitials>mcc</authorinitials>
-<revremark>Conversion from LaTex to DocBook XML. The
- contents is the same as the original LaTex version.</revremark>
-</revision>
-<revision>
-<revnumber>1.0.0</revnumber>
-<date>2003-07-24</date>
-<authorinitials>rjkm</authorinitials>
-<revremark>Initial revision on LaTEX.</revremark>
-</revision>
-</revhistory>
-</partinfo>
-
-
-<title>LINUX DVB API</title>
-<subtitle>Version 5.10</subtitle>
-<!-- ADD THE CHAPTERS HERE -->
- <chapter id="dvb_introdution">
- &sub-intro;
- </chapter>
- <chapter id="dvb_frontend">
- &sub-frontend;
- </chapter>
- <chapter id="dvb_demux">
- &sub-demux;
- </chapter>
- <chapter id="dvb_ca">
- &sub-ca;
- </chapter>
- <chapter id="net">
- &sub-net;
- </chapter>
- <chapter id="legacy_dvb_apis">
- <title>DVB Deprecated APIs</title>
- <para>The APIs described here are kept only for historical reasons. There's
- just one driver for a very legacy hardware that uses this API. No
- modern drivers should use it. Instead, audio and video should be using
- the V4L2 and ALSA APIs, and the pipelines should be set using the
- Media Controller API</para>
- <section id="dvb_video">
- &sub-video;
- </section>
- <section id="dvb_audio">
- &sub-audio;
- </section>
- </chapter>
- <chapter id="dvb_examples">
- &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
deleted file mode 100644
index e579ae5088ae..000000000000
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ /dev/null
@@ -1,1680 +0,0 @@
-<section id="frontend-properties">
-<title>DVB Frontend properties</title>
-<para>Tuning into a Digital TV physical channel and starting decoding it
- requires changing a set of parameters, in order to control the
- tuner, the demodulator, the Linear Low-noise Amplifier (LNA) and to set the
- antenna subsystem via Satellite Equipment Control (SEC), on satellite
- systems. The actual parameters are specific to each particular digital
- TV standards, and may change as the digital TV specs evolves.</para>
-<para>In the past, the strategy used was to have a union with the parameters
- needed to tune for DVB-S, DVB-C, DVB-T and ATSC delivery systems grouped
- there. The problem is that, as the second generation standards appeared,
- those structs were not big enough to contain the additional parameters.
- Also, the union didn't have any space left to be expanded without breaking
- userspace. So, the decision was to deprecate the legacy union/struct based
- approach, in favor of a properties set approach.</para>
-
-<para>NOTE: on Linux DVB API version 3, setting a frontend were done via
- <link linkend="dvb-frontend-parameters">struct <constant>dvb_frontend_parameters</constant></link>.
- This got replaced on version 5 (also called "S2API", as this API were
- added originally_enabled to provide support for DVB-S2), because the old
- API has a very limited support to new standards and new hardware. This
- section describes the new and recommended way to set the frontend, with
- suppports all digital TV delivery systems.</para>
-
-<para>Example: with the properties based approach, in order to set the tuner
- to a DVB-C channel at 651 kHz, modulated with 256-QAM, FEC 3/4 and symbol
- rate of 5.217 Mbauds, those properties should be sent to
- <link linkend="FE_GET_PROPERTY"><constant>FE_SET_PROPERTY</constant></link> ioctl:</para>
- <itemizedlist>
- <listitem><para>&DTV-DELIVERY-SYSTEM; = SYS_DVBC_ANNEX_A</para></listitem>
- <listitem><para>&DTV-FREQUENCY; = 651000000</para></listitem>
- <listitem><para>&DTV-MODULATION; = QAM_256</para></listitem>
- <listitem><para>&DTV-INVERSION; = INVERSION_AUTO</para></listitem>
- <listitem><para>&DTV-SYMBOL-RATE; = 5217000</para></listitem>
- <listitem><para>&DTV-INNER-FEC; = FEC_3_4</para></listitem>
- <listitem><para>&DTV-TUNE;</para></listitem>
- </itemizedlist>
-
-<para>The code that would do the above is:</para>
-<programlisting>
-#include &lt;stdio.h&gt;
-#include &lt;fcntl.h&gt;
-#include &lt;sys/ioctl.h&gt;
-#include &lt;linux/dvb/frontend.h&gt;
-
-static struct dtv_property props[] = {
- { .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_DVBC_ANNEX_A },
- { .cmd = DTV_FREQUENCY, .u.data = 651000000 },
- { .cmd = DTV_MODULATION, .u.data = QAM_256 },
- { .cmd = DTV_INVERSION, .u.data = INVERSION_AUTO },
- { .cmd = DTV_SYMBOL_RATE, .u.data = 5217000 },
- { .cmd = DTV_INNER_FEC, .u.data = FEC_3_4 },
- { .cmd = DTV_TUNE }
-};
-
-static struct dtv_properties dtv_prop = {
- .num = 6, .props = props
-};
-
-int main(void)
-{
- int fd = open("/dev/dvb/adapter0/frontend0", O_RDWR);
-
- if (!fd) {
- perror ("open");
- return -1;
- }
- if (ioctl(fd, FE_SET_PROPERTY, &amp;dtv_prop) == -1) {
- perror("ioctl");
- return -1;
- }
- printf("Frontend set\n");
- return 0;
-}
-</programlisting>
-
-<para>NOTE: While it is possible to directly call the Kernel code like the
- above example, it is strongly recommended to use
- <ulink url="https://linuxtv.org/docs/libdvbv5/index.html">libdvbv5</ulink>,
- as it provides abstraction to work with the supported digital TV standards
- and provides methods for usual operations like program scanning and to
- read/write channel descriptor files.</para>
-
-<section id="dtv-stats">
-<title>struct <structname>dtv_stats</structname></title>
-<programlisting>
-struct dtv_stats {
- __u8 scale; /* enum fecap_scale_params type */
- union {
- __u64 uvalue; /* for counters and relative scales */
- __s64 svalue; /* for 1/1000 dB measures */
- };
-} __packed;
-</programlisting>
-</section>
-<section id="dtv-fe-stats">
-<title>struct <structname>dtv_fe_stats</structname></title>
-<programlisting>
-#define MAX_DTV_STATS 4
-
-struct dtv_fe_stats {
- __u8 len;
- &dtv-stats; stat[MAX_DTV_STATS];
-} __packed;
-</programlisting>
-</section>
-
-<section id="dtv-property">
-<title>struct <structname>dtv_property</structname></title>
-<programlisting>
-/* Reserved fields should be set to 0 */
-
-struct dtv_property {
- __u32 cmd;
- __u32 reserved[3];
- union {
- __u32 data;
- &dtv-fe-stats; st;
- 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>struct <structname>dtv_properties</structname></title>
-<programlisting>
-struct dtv_properties {
- __u32 num;
- &dtv-property; *props;
-};
-</programlisting>
-</section>
-
-<section>
- <title>Property types</title>
-<para>
-On <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY and 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.</para>
-
- <para>Notes:</para>
- <para>1)For satellite delivery systems, it is measured in kHz.
- For the other ones, it is measured in Hz.</para>
- <para>2)For ISDB-T, the channels are usually transmitted with an offset of 143kHz.
- E.g. a valid frequency could be 474143 kHz. The stepping is bound to the bandwidth of
- the channel which is 6MHz.</para>
-
- <para>3)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 delivery systems that supports
- more than one modulation type. The modulation can be one of the types
- defined by &fe-modulation;.</para>
-
-
-<section id="fe-modulation-t">
-<title>Modulation property</title>
-
-<para>Most of the digital TV standards currently offers more than one possible
- modulation (sometimes called as "constellation" on some standards). This
- enum contains the values used by the Kernel. Please note that not all
- modulations are supported by a given standard.</para>
-
-<table pgwide="1" frame="none" id="fe-modulation">
- <title>enum fe_modulation</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="QPSK"><constant>QPSK</constant></entry>
- <entry>QPSK modulation</entry>
- </row><row>
- <entry id="QAM-16"><constant>QAM_16</constant></entry>
- <entry>16-QAM modulation</entry>
- </row><row>
- <entry id="QAM-32"><constant>QAM_32</constant></entry>
- <entry>32-QAM modulation</entry>
- </row><row>
- <entry id="QAM-64"><constant>QAM_64</constant></entry>
- <entry>64-QAM modulation</entry>
- </row><row>
- <entry id="QAM-128"><constant>QAM_128</constant></entry>
- <entry>128-QAM modulation</entry>
- </row><row>
- <entry id="QAM-256"><constant>QAM_256</constant></entry>
- <entry>256-QAM modulation</entry>
- </row><row>
- <entry id="QAM-AUTO"><constant>QAM_AUTO</constant></entry>
- <entry>Autodetect QAM modulation</entry>
- </row><row>
- <entry id="VSB-8"><constant>VSB_8</constant></entry>
- <entry>8-VSB modulation</entry>
- </row><row>
- <entry id="VSB-16"><constant>VSB_16</constant></entry>
- <entry>16-VSB modulation</entry>
- </row><row>
- <entry id="PSK-8"><constant>PSK_8</constant></entry>
- <entry>8-PSK modulation</entry>
- </row><row>
- <entry id="APSK-16"><constant>APSK_16</constant></entry>
- <entry>16-APSK modulation</entry>
- </row><row>
- <entry id="APSK-32"><constant>APSK_32</constant></entry>
- <entry>32-APSK modulation</entry>
- </row><row>
- <entry id="DQPSK"><constant>DQPSK</constant></entry>
- <entry>DQPSK modulation</entry>
- </row><row>
- <entry id="QAM-4-NR"><constant>QAM_4_NR</constant></entry>
- <entry>4-QAM-NR modulation</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</section>
-
- </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>Specifies if the frontend should do spectral inversion or not.</para>
-
-<section id="fe-spectral-inversion-t">
-<title>enum fe_modulation: Frontend spectral inversion</title>
-
-<para>This parameter 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. If the hardware
- doesn't support, the DVB core will try to lock at the carrier first with
- inversion off. If it fails, it will try to enable inversion.
-</para>
-
-<table pgwide="1" frame="none" id="fe-spectral-inversion">
- <title>enum fe_modulation</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="INVERSION-OFF"><constant>INVERSION_OFF</constant></entry>
- <entry>Don't do spectral band inversion.</entry>
- </row><row>
- <entry id="INVERSION-ON"><constant>INVERSION_ON</constant></entry>
- <entry>Do spectral band inversion.</entry>
- </row><row>
- <entry id="INVERSION-AUTO"><constant>INVERSION_AUTO</constant></entry>
- <entry>Autodetect spectral band inversion.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</section>
-
- </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>
-<section id="fe-code-rate-t">
-<title>enum fe_code_rate: type of the Forward Error Correction.</title>
-
-<table pgwide="1" frame="none" id="fe-code-rate">
- <title>enum fe_code_rate</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="FEC-NONE"><constant>FEC_NONE</constant></entry>
- <entry>No Forward Error Correction Code</entry>
- </row><row>
- <entry id="FEC-AUTO"><constant>FEC_AUTO</constant></entry>
- <entry>Autodetect Error Correction Code</entry>
- </row><row>
- <entry id="FEC-1-2"><constant>FEC_1_2</constant></entry>
- <entry>Forward Error Correction Code 1/2</entry>
- </row><row>
- <entry id="FEC-2-3"><constant>FEC_2_3</constant></entry>
- <entry>Forward Error Correction Code 2/3</entry>
- </row><row>
- <entry id="FEC-3-4"><constant>FEC_3_4</constant></entry>
- <entry>Forward Error Correction Code 3/4</entry>
- </row><row>
- <entry id="FEC-4-5"><constant>FEC_4_5</constant></entry>
- <entry>Forward Error Correction Code 4/5</entry>
- </row><row>
- <entry id="FEC-5-6"><constant>FEC_5_6</constant></entry>
- <entry>Forward Error Correction Code 5/6</entry>
- </row><row>
- <entry id="FEC-6-7"><constant>FEC_6_7</constant></entry>
- <entry>Forward Error Correction Code 6/7</entry>
- </row><row>
- <entry id="FEC-7-8"><constant>FEC_7_8</constant></entry>
- <entry>Forward Error Correction Code 7/8</entry>
- </row><row>
- <entry id="FEC-8-9"><constant>FEC_8_9</constant></entry>
- <entry>Forward Error Correction Code 8/9</entry>
- </row><row>
- <entry id="FEC-9-10"><constant>FEC_9_10</constant></entry>
- <entry>Forward Error Correction Code 9/10</entry>
- </row><row>
- <entry id="FEC-2-5"><constant>FEC_2_5</constant></entry>
- <entry>Forward Error Correction Code 2/5</entry>
- </row><row>
- <entry id="FEC-3-5"><constant>FEC_3_5</constant></entry>
- <entry>Forward Error Correction Code 3/5</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</section>
- </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>
-
-<table pgwide="1" frame="none" id="fe-sec-voltage">
- <title id="fe-sec-voltage-t">enum fe_sec_voltage</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="SEC-VOLTAGE-13"><constant>SEC_VOLTAGE_13</constant></entry>
- <entry align="char">Set DC voltage level to 13V</entry>
- </row><row>
- <entry align="char" id="SEC-VOLTAGE-18"><constant>SEC_VOLTAGE_18</constant></entry>
- <entry align="char">Set DC voltage level to 18V</entry>
- </row><row>
- <entry align="char" id="SEC-VOLTAGE-OFF"><constant>SEC_VOLTAGE_OFF</constant></entry>
- <entry align="char">Don't send any voltage to the antenna</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </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>
-<table pgwide="1" frame="none" id="fe-pilot">
- <title>enum fe_pilot</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="PILOT-ON"><constant>PILOT_ON</constant></entry>
- <entry align="char">Pilot tones enabled</entry>
- </row><row>
- <entry align="char" id="PILOT-OFF"><constant>PILOT_OFF</constant></entry>
- <entry align="char">Pilot tones disabled</entry>
- </row><row>
- <entry align="char" id="PILOT-AUTO"><constant>PILOT_AUTO</constant></entry>
- <entry align="char">Autodetect pilot tones</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </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>
-<table pgwide="1" frame="none" id="fe-rolloff">
- <title>enum fe_rolloff</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="ROLLOFF-35"><constant>ROLLOFF_35</constant></entry>
- <entry align="char">Roloff factor: &alpha;=35%</entry>
- </row><row>
- <entry align="char" id="ROLLOFF-20"><constant>ROLLOFF_20</constant></entry>
- <entry align="char">Roloff factor: &alpha;=20%</entry>
- </row><row>
- <entry align="char" id="ROLLOFF-25"><constant>ROLLOFF_25</constant></entry>
- <entry align="char">Roloff factor: &alpha;=25%</entry>
- </row><row>
- <entry align="char" id="ROLLOFF-AUTO"><constant>ROLLOFF_AUTO</constant></entry>
- <entry align="char">Auto-detect the roloff factor.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </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>
-
-<table pgwide="1" frame="none" id="fe-delivery-system">
- <title>enum fe_delivery_system</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="SYS-UNDEFINED"><constant>SYS_UNDEFINED</constant></entry>
- <entry>Undefined standard. Generally, indicates an error</entry>
- </row><row>
- <entry id="SYS-DVBC-ANNEX-A"><constant>SYS_DVBC_ANNEX_A</constant></entry>
- <entry>Cable TV: DVB-C following ITU-T J.83 Annex A spec</entry>
- </row><row>
- <entry id="SYS-DVBC-ANNEX-B"><constant>SYS_DVBC_ANNEX_B</constant></entry>
- <entry>Cable TV: DVB-C following ITU-T J.83 Annex B spec (ClearQAM)</entry>
- </row><row>
- <entry id="SYS-DVBC-ANNEX-C"><constant>SYS_DVBC_ANNEX_C</constant></entry>
- <entry>Cable TV: DVB-C following ITU-T J.83 Annex C spec</entry>
- </row><row>
- <entry id="SYS-ISDBC"><constant>SYS_ISDBC</constant></entry>
- <entry>Cable TV: ISDB-C (no drivers yet)</entry>
- </row><row>
- <entry id="SYS-DVBT"><constant>SYS_DVBT</constant></entry>
- <entry>Terrestral TV: DVB-T</entry>
- </row><row>
- <entry id="SYS-DVBT2"><constant>SYS_DVBT2</constant></entry>
- <entry>Terrestral TV: DVB-T2</entry>
- </row><row>
- <entry id="SYS-ISDBT"><constant>SYS_ISDBT</constant></entry>
- <entry>Terrestral TV: ISDB-T</entry>
- </row><row>
- <entry id="SYS-ATSC"><constant>SYS_ATSC</constant></entry>
- <entry>Terrestral TV: ATSC</entry>
- </row><row>
- <entry id="SYS-ATSCMH"><constant>SYS_ATSCMH</constant></entry>
- <entry>Terrestral TV (mobile): ATSC-M/H</entry>
- </row><row>
- <entry id="SYS-DTMB"><constant>SYS_DTMB</constant></entry>
- <entry>Terrestrial TV: DTMB</entry>
- </row><row>
- <entry id="SYS-DVBS"><constant>SYS_DVBS</constant></entry>
- <entry>Satellite TV: DVB-S</entry>
- </row><row>
- <entry id="SYS-DVBS2"><constant>SYS_DVBS2</constant></entry>
- <entry>Satellite TV: DVB-S2</entry>
- </row><row>
- <entry id="SYS-TURBO"><constant>SYS_TURBO</constant></entry>
- <entry>Satellite TV: DVB-S Turbo</entry>
- </row><row>
- <entry id="SYS-ISDBS"><constant>SYS_ISDBS</constant></entry>
- <entry>Satellite TV: ISDB-S</entry>
- </row><row>
- <entry id="SYS-DAB"><constant>SYS_DAB</constant></entry>
- <entry>Digital audio: DAB (not fully supported)</entry>
- </row><row>
- <entry id="SYS-DSS"><constant>SYS_DSS</constant></entry>
- <entry>Satellite TV:"DSS (not fully supported)</entry>
- </row><row>
- <entry id="SYS-CMMB"><constant>SYS_CMMB</constant></entry>
- <entry>Terrestral TV (mobile):CMMB (not fully supported)</entry>
- </row><row>
- <entry id="SYS-DVBH"><constant>SYS_DVBH</constant></entry>
- <entry>Terrestral TV (mobile): DVB-H (standard deprecated)</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-
-</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>Valid values: 0, 1, 2, 4, -1 (AUTO)</para>
- <para>when DTV_ISDBT_SOUND_BROADCASTING is active, value 8 is also valid.</para>
- <para>Note: The real time interleaving length depends on the mode (fft-size). The values
- here are referring to what can be found in the TMCC-structure, as shown in the table below.</para>
- <informaltable id="isdbt-layer-interleaving-table">
- <tgroup cols="4" align="center">
- <tbody>
- <row>
- <entry>DTV_ISDBT_LAYER*_TIME_INTERLEAVING</entry>
- <entry>Mode 1 (2K FFT)</entry>
- <entry>Mode 2 (4K FFT)</entry>
- <entry>Mode 3 (8K FFT)</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>4</entry>
- <entry>2</entry>
- <entry>1</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>8</entry>
- <entry>4</entry>
- <entry>2</entry>
- </row>
- <row>
- <entry>4</entry>
- <entry>16</entry>
- <entry>8</entry>
- <entry>4</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </section>
- <section id="DTV-ATSCMH-FIC-VER">
- <title><constant>DTV_ATSCMH_FIC_VER</constant></title>
- <para>Version number of the FIC (Fast Information Channel) signaling data.</para>
- <para>FIC is used for relaying information to allow rapid service acquisition by the receiver.</para>
- <para>Possible values: 0, 1, 2, 3, ..., 30, 31</para>
- </section>
- <section id="DTV-ATSCMH-PARADE-ID">
- <title><constant>DTV_ATSCMH_PARADE_ID</constant></title>
- <para>Parade identification number</para>
- <para>A parade is a collection of up to eight MH groups, conveying one or two ensembles.</para>
- <para>Possible values: 0, 1, 2, 3, ..., 126, 127</para>
- </section>
- <section id="DTV-ATSCMH-NOG">
- <title><constant>DTV_ATSCMH_NOG</constant></title>
- <para>Number of MH groups per MH subframe for a designated parade.</para>
- <para>Possible values: 1, 2, 3, 4, 5, 6, 7, 8</para>
- </section>
- <section id="DTV-ATSCMH-TNOG">
- <title><constant>DTV_ATSCMH_TNOG</constant></title>
- <para>Total number of MH groups including all MH groups belonging to all MH parades in one MH subframe.</para>
- <para>Possible values: 0, 1, 2, 3, ..., 30, 31</para>
- </section>
- <section id="DTV-ATSCMH-SGN">
- <title><constant>DTV_ATSCMH_SGN</constant></title>
- <para>Start group number.</para>
- <para>Possible values: 0, 1, 2, 3, ..., 14, 15</para>
- </section>
- <section id="DTV-ATSCMH-PRC">
- <title><constant>DTV_ATSCMH_PRC</constant></title>
- <para>Parade repetition cycle.</para>
- <para>Possible values: 1, 2, 3, 4, 5, 6, 7, 8</para>
- </section>
- <section id="DTV-ATSCMH-RS-FRAME-MODE">
- <title><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></title>
- <para>Reed Solomon (RS) frame mode.</para>
- <para>Possible values are:</para>
-<table pgwide="1" frame="none" id="atscmh-rs-frame-mode">
- <title>enum atscmh_rs_frame_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="ATSCMH-RSFRAME-PRI-ONLY"><constant>ATSCMH_RSFRAME_PRI_ONLY</constant></entry>
- <entry>Single Frame: There is only a primary RS Frame for all
- Group Regions.</entry>
- </row><row>
- <entry id="ATSCMH-RSFRAME-PRI-SEC"><constant>ATSCMH_RSFRAME_PRI_SEC</constant></entry>
- <entry>Dual Frame: There are two separate RS Frames: Primary RS
- Frame for Group Region A and B and Secondary RS Frame for Group
- Region C and D.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </section>
- <section id="DTV-ATSCMH-RS-FRAME-ENSEMBLE">
- <title><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></title>
- <para>Reed Solomon(RS) frame ensemble.</para>
- <para>Possible values are:</para>
-<table pgwide="1" frame="none" id="atscmh-rs-frame-ensemble">
- <title>enum atscmh_rs_frame_ensemble</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="ATSCMH-RSFRAME-ENS-PRI"><constant>ATSCMH_RSFRAME_ENS_PRI</constant></entry>
- <entry>Primary Ensemble.</entry>
- </row><row>
- <entry id="ATSCMH-RSFRAME-ENS-SEC"><constant>AATSCMH_RSFRAME_PRI_SEC</constant></entry>
- <entry>Secondary Ensemble.</entry>
- </row><row>
- <entry id="ATSCMH-RSFRAME-RES"><constant>AATSCMH_RSFRAME_RES</constant></entry>
- <entry>Reserved. Shouldn't be used.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </section>
- <section id="DTV-ATSCMH-RS-CODE-MODE-PRI">
- <title><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></title>
- <para>Reed Solomon (RS) code mode (primary).</para>
- <para>Possible values are:</para>
-<table pgwide="1" frame="none" id="atscmh-rs-code-mode">
- <title>enum atscmh_rs_code_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="ATSCMH-RSCODE-211-187"><constant>ATSCMH_RSCODE_211_187</constant></entry>
- <entry>Reed Solomon code (211,187).</entry>
- </row><row>
- <entry id="ATSCMH-RSCODE-223-187"><constant>ATSCMH_RSCODE_223_187</constant></entry>
- <entry>Reed Solomon code (223,187).</entry>
- </row><row>
- <entry id="ATSCMH-RSCODE-235-187"><constant>ATSCMH_RSCODE_235_187</constant></entry>
- <entry>Reed Solomon code (235,187).</entry>
- </row><row>
- <entry id="ATSCMH-RSCODE-RES"><constant>ATSCMH_RSCODE_RES</constant></entry>
- <entry>Reserved. Shouldn't be used.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </section>
- <section id="DTV-ATSCMH-RS-CODE-MODE-SEC">
- <title><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></title>
- <para>Reed Solomon (RS) code mode (secondary).</para>
- <para>Possible values are the same as documented on
- &atscmh-rs-code-mode;:</para>
- </section>
- <section id="DTV-ATSCMH-SCCC-BLOCK-MODE">
- <title><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></title>
- <para>Series Concatenated Convolutional Code Block Mode.</para>
- <para>Possible values are:</para>
-<table pgwide="1" frame="none" id="atscmh-sccc-block-mode">
- <title>enum atscmh_scc_block_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="ATSCMH-SCCC-BLK-SEP"><constant>ATSCMH_SCCC_BLK_SEP</constant></entry>
- <entry>Separate SCCC: the SCCC outer code mode shall be set independently
- for each Group Region (A, B, C, D)</entry>
- </row><row>
- <entry id="ATSCMH-SCCC-BLK-COMB"><constant>ATSCMH_SCCC_BLK_COMB</constant></entry>
- <entry>Combined SCCC: all four Regions shall have the same SCCC outer
- code mode.</entry>
- </row><row>
- <entry id="ATSCMH-SCCC-BLK-RES"><constant>ATSCMH_SCCC_BLK_RES</constant></entry>
- <entry>Reserved. Shouldn't be used.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </section>
- <section id="DTV-ATSCMH-SCCC-CODE-MODE-A">
- <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></title>
- <para>Series Concatenated Convolutional Code Rate.</para>
- <para>Possible values are:</para>
-<table pgwide="1" frame="none" id="atscmh-sccc-code-mode">
- <title>enum atscmh_sccc_code_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="ATSCMH-SCCC-CODE-HLF"><constant>ATSCMH_SCCC_CODE_HLF</constant></entry>
- <entry>The outer code rate of a SCCC Block is 1/2 rate.</entry>
- </row><row>
- <entry id="ATSCMH-SCCC-CODE-QTR"><constant>ATSCMH_SCCC_CODE_QTR</constant></entry>
- <entry>The outer code rate of a SCCC Block is 1/4 rate.</entry>
- </row><row>
- <entry id="ATSCMH-SCCC-CODE-RES"><constant>ATSCMH_SCCC_CODE_RES</constant></entry>
- <entry>to be documented.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
- </section>
- <section id="DTV-ATSCMH-SCCC-CODE-MODE-B">
- <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></title>
- <para>Series Concatenated Convolutional Code Rate.</para>
- <para>Possible values are the same as documented on
- &atscmh-sccc-code-mode;.</para>
- </section>
- <section id="DTV-ATSCMH-SCCC-CODE-MODE-C">
- <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></title>
- <para>Series Concatenated Convolutional Code Rate.</para>
- <para>Possible values are the same as documented on
- &atscmh-sccc-code-mode;.</para>
- </section>
- <section id="DTV-ATSCMH-SCCC-CODE-MODE-D">
- <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></title>
- <para>Series Concatenated Convolutional Code Rate.</para>
- <para>Possible values are the same as documented on
- &atscmh-sccc-code-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
- the ones described at &fe-transmit-mode-t;.
- </para>
- </section>
- <section id="DTV-CODE-RATE-LP">
- <title><constant>DTV_CODE_RATE_LP</constant></title>
- <para>Used on terrestrial transmissions. The acceptable values are
- the ones described at &fe-transmit-mode-t;.
- </para>
-
- </section>
-
- <section id="DTV-GUARD-INTERVAL">
- <title><constant>DTV_GUARD_INTERVAL</constant></title>
-
- <para>Possible values are:</para>
-
-<section id="fe-guard-interval-t">
-<title>Modulation guard interval</title>
-
-<table pgwide="1" frame="none" id="fe-guard-interval">
- <title>enum fe_guard_interval</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="GUARD-INTERVAL-AUTO"><constant>GUARD_INTERVAL_AUTO</constant></entry>
- <entry>Autodetect the guard interval</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-1-128"><constant>GUARD_INTERVAL_1_128</constant></entry>
- <entry>Guard interval 1/128</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-1-32"><constant>GUARD_INTERVAL_1_32</constant></entry>
- <entry>Guard interval 1/32</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-1-16"><constant>GUARD_INTERVAL_1_16</constant></entry>
- <entry>Guard interval 1/16</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-1-8"><constant>GUARD_INTERVAL_1_8</constant></entry>
- <entry>Guard interval 1/8</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-1-4"><constant>GUARD_INTERVAL_1_4</constant></entry>
- <entry>Guard interval 1/4</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-19-128"><constant>GUARD_INTERVAL_19_128</constant></entry>
- <entry>Guard interval 19/128</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-19-256"><constant>GUARD_INTERVAL_19_256</constant></entry>
- <entry>Guard interval 19/256</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-PN420"><constant>GUARD_INTERVAL_PN420</constant></entry>
- <entry>PN length 420 (1/4)</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-PN595"><constant>GUARD_INTERVAL_PN595</constant></entry>
- <entry>PN length 595 (1/6)</entry>
- </row><row>
- <entry id="GUARD-INTERVAL-PN945"><constant>GUARD_INTERVAL_PN945</constant></entry>
- <entry>PN length 945 (1/9)</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
- <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>
- <para>3) DTMB specifies PN420, PN595 and PN945.</para>
-</section>
- </section>
- <section id="DTV-TRANSMISSION-MODE">
- <title><constant>DTV_TRANSMISSION_MODE</constant></title>
-
- <para>Specifies the number of carriers used by the standard.
- This is used only on OFTM-based standards, e. g.
- DVB-T/T2, ISDB-T, DTMB</para>
-
-<section id="fe-transmit-mode-t">
-<title>enum fe_transmit_mode: Number of carriers per channel</title>
-
-<table pgwide="1" frame="none" id="fe-transmit-mode">
- <title>enum fe_transmit_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="TRANSMISSION-MODE-AUTO"><constant>TRANSMISSION_MODE_AUTO</constant></entry>
- <entry>Autodetect transmission mode. The hardware will try to find
- the correct FFT-size (if capable) to fill in the missing
- parameters.</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-1K"><constant>TRANSMISSION_MODE_1K</constant></entry>
- <entry>Transmission mode 1K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-2K"><constant>TRANSMISSION_MODE_2K</constant></entry>
- <entry>Transmission mode 2K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-8K"><constant>TRANSMISSION_MODE_8K</constant></entry>
- <entry>Transmission mode 8K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-4K"><constant>TRANSMISSION_MODE_4K</constant></entry>
- <entry>Transmission mode 4K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-16K"><constant>TRANSMISSION_MODE_16K</constant></entry>
- <entry>Transmission mode 16K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-32K"><constant>TRANSMISSION_MODE_32K</constant></entry>
- <entry>Transmission mode 32K</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-C1"><constant>TRANSMISSION_MODE_C1</constant></entry>
- <entry>Single Carrier (C=1) transmission mode (DTMB)</entry>
- </row><row>
- <entry id="TRANSMISSION-MODE-C3780"><constant>TRANSMISSION_MODE_C3780</constant></entry>
- <entry>Multi Carrier (C=3780) transmission mode (DTMB)</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-
- <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>
- <para>5) DTMB specifies C1 and C3780.</para>
-</section>
- </section>
- <section id="DTV-HIERARCHY">
- <title><constant>DTV_HIERARCHY</constant></title>
- <para>Frontend hierarchy</para>
-
-
-<section id="fe-hierarchy-t">
-<title>Frontend hierarchy</title>
-
-<table pgwide="1" frame="none" id="fe-hierarchy">
- <title>enum fe_hierarchy</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="HIERARCHY-NONE"><constant>HIERARCHY_NONE</constant></entry>
- <entry>No hierarchy</entry>
- </row><row>
- <entry id="HIERARCHY-AUTO"><constant>HIERARCHY_AUTO</constant></entry>
- <entry>Autodetect hierarchy (if supported)</entry>
- </row><row>
- <entry id="HIERARCHY-1"><constant>HIERARCHY_1</constant></entry>
- <entry>Hierarchy 1</entry>
- </row><row>
- <entry id="HIERARCHY-2"><constant>HIERARCHY_2</constant></entry>
- <entry>Hierarchy 2</entry>
- </row><row>
- <entry id="HIERARCHY-4"><constant>HIERARCHY_4</constant></entry>
- <entry>Hierarchy 4</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</section>
-
- </section>
- <section id="DTV-STREAM-ID">
- <title><constant>DTV_STREAM_ID</constant></title>
- <para>DVB-S2, DVB-T2 and ISDB-S support the transmission of several
- streams on a single transport stream.
- This property enables the DVB driver to handle substream filtering,
- when supported by the hardware.
- By default, substream filtering is disabled.
- </para><para>
- For DVB-S2 and DVB-T2, the valid substream id range is from 0 to 255.
- </para><para>
- For ISDB, the valid substream id range is from 1 to 65535.
- </para><para>
- To disable it, you should use the special macro NO_STREAM_ID_FILTER.
- </para><para>
- Note: any value outside the id range also disables filtering.
- </para>
- </section>
- <section id="DTV-DVBT2-PLP-ID-LEGACY">
- <title><constant>DTV_DVBT2_PLP_ID_LEGACY</constant></title>
- <para>Obsolete, replaced with DTV_STREAM_ID.</para>
- </section>
- <section id="DTV-ENUM-DELSYS">
- <title><constant>DTV_ENUM_DELSYS</constant></title>
- <para>A Multi standard frontend needs to advertise the delivery systems provided.
- Applications need to enumerate the provided delivery systems, before using
- any other operation with the frontend. Prior to it's introduction,
- FE_GET_INFO was used to determine a frontend type. A frontend which
- provides more than a single delivery system, FE_GET_INFO doesn't help much.
- Applications which intends to use a multistandard frontend must enumerate
- the delivery systems associated with it, rather than trying to use
- FE_GET_INFO. In the case of a legacy frontend, the result is just the same
- as with FE_GET_INFO, but in a more structured format </para>
- </section>
- <section id="DTV-INTERLEAVING">
- <title><constant>DTV_INTERLEAVING</constant></title>
-
-<para>Time interleaving to be used. Currently, used only on DTMB.</para>
-
-<table pgwide="1" frame="none" id="fe-interleaving">
- <title>enum fe_interleaving</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="INTERLEAVING-NONE"><constant>INTERLEAVING_NONE</constant></entry>
- <entry>No interleaving.</entry>
- </row><row>
- <entry id="INTERLEAVING-AUTO"><constant>INTERLEAVING_AUTO</constant></entry>
- <entry>Auto-detect interleaving.</entry>
- </row><row>
- <entry id="INTERLEAVING-240"><constant>INTERLEAVING_240</constant></entry>
- <entry>Interleaving of 240 symbols.</entry>
- </row><row>
- <entry id="INTERLEAVING-720"><constant>INTERLEAVING_720</constant></entry>
- <entry>Interleaving of 720 symbols.</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
- </section>
- <section id="DTV-LNA">
- <title><constant>DTV_LNA</constant></title>
- <para>Low-noise amplifier.</para>
- <para>Hardware might offer controllable LNA which can be set manually
- using that parameter. Usually LNA could be found only from
- terrestrial devices if at all.</para>
- <para>Possible values: 0, 1, LNA_AUTO</para>
- <para>0, LNA off</para>
- <para>1, LNA on</para>
- <para>use the special macro LNA_AUTO to set LNA auto</para>
- </section>
-</section>
-
- <section id="frontend-stat-properties">
- <title>Frontend statistics indicators</title>
- <para>The values are returned via <constant>dtv_property.stat</constant>.
- If the property is supported, <constant>dtv_property.stat.len</constant> is bigger than zero.</para>
- <para>For most delivery systems, <constant>dtv_property.stat.len</constant>
- will be 1 if the stats is supported, and the properties will
- return a single value for each parameter.</para>
- <para>It should be noted, however, that new OFDM delivery systems
- like ISDB can use different modulation types for each group of
- carriers. On such standards, up to 3 groups of statistics can be
- provided, and <constant>dtv_property.stat.len</constant> is updated
- to reflect the "global" metrics, plus one metric per each carrier
- group (called "layer" on ISDB).</para>
- <para>So, in order to be consistent with other delivery systems, the first
- value at <link linkend="dtv-stats"><constant>dtv_property.stat.dtv_stats</constant></link>
- array refers to the global metric. The other elements of the array
- represent each layer, starting from layer A(index 1),
- layer B (index 2) and so on.</para>
- <para>The number of filled elements are stored at <constant>dtv_property.stat.len</constant>.</para>
- <para>Each element of the <constant>dtv_property.stat.dtv_stats</constant> array consists on two elements:</para>
- <itemizedlist mark='opencircle'>
- <listitem><para><constant>svalue</constant> or <constant>uvalue</constant>, where
- <constant>svalue</constant> is for signed values of the measure (dB measures)
- and <constant>uvalue</constant> is for unsigned values (counters, relative scale)</para></listitem>
- <listitem><para><constant>scale</constant> - Scale for the value. It can be:</para>
- <itemizedlist mark='bullet' id="fecap-scale-params">
- <listitem id="FE-SCALE-NOT-AVAILABLE"><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - The parameter is supported by the frontend, but it was not possible to collect it (could be a transitory or permanent condition)</para></listitem>
- <listitem id="FE-SCALE-DECIBEL"><para><constant>FE_SCALE_DECIBEL</constant> - parameter is a signed value, measured in 1/1000 dB</para></listitem>
- <listitem id="FE-SCALE-RELATIVE"><para><constant>FE_SCALE_RELATIVE</constant> - parameter is a unsigned value, where 0 means 0% and 65535 means 100%.</para></listitem>
- <listitem id="FE-SCALE-COUNTER"><para><constant>FE_SCALE_COUNTER</constant> - parameter is a unsigned value that counts the occurrence of an event, like bit error, block error, or lapsed time.</para></listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
- <section id="DTV-STAT-SIGNAL-STRENGTH">
- <title><constant>DTV_STAT_SIGNAL_STRENGTH</constant></title>
- <para>Indicates the signal strength level at the analog part of the tuner or of the demod.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_DECIBEL</constant> - signal strength is in 0.001 dBm units, power measured in miliwatts. This value is generally negative.</para></listitem>
- <listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for power (actually, 0 to 65535).</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-CNR">
- <title><constant>DTV_STAT_CNR</constant></title>
- <para>Indicates the Signal to Noise ratio for the main carrier.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_DECIBEL</constant> - Signal/Noise ratio is in 0.001 dB units.</para></listitem>
- <listitem><para><constant>FE_SCALE_RELATIVE</constant> - The frontend provides a 0% to 100% measurement for Signal/Noise (actually, 0 to 65535).</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-PRE-ERROR-BIT-COUNT">
- <title><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></title>
- <para>Measures the number of bit errors before the forward error correction (FEC) on the inner coding block (before Viterbi, LDPC or other inner code).</para>
- <para>This measure is taken during the same interval as <constant>DTV_STAT_PRE_TOTAL_BIT_COUNT</constant>.</para>
- <para>In order to get the BER (Bit Error Rate) measurement, it should be divided by
- <link linkend="DTV-STAT-PRE-TOTAL-BIT-COUNT"><constant>DTV_STAT_PRE_TOTAL_BIT_COUNT</constant></link>.</para>
- <para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
- The frontend may reset it when a channel/transponder is tuned.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted before the inner coding.</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-PRE-TOTAL-BIT-COUNT">
- <title><constant>DTV_STAT_PRE_TOTAL_BIT_COUNT</constant></title>
- <para>Measures the amount of bits received before the inner code block, during the same period as
- <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link> measurement was taken.</para>
- <para>It should be noted that this measurement can be smaller than the total amount of bits on the transport stream,
- as the frontend may need to manually restart the measurement, losing some data between each measurement interval.</para>
- <para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
- The frontend may reset it when a channel/transponder is tuned.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
- <link linkend="DTV-STAT-PRE-ERROR-BIT-COUNT"><constant>DTV_STAT_PRE_ERROR_BIT_COUNT</constant></link>.</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-POST-ERROR-BIT-COUNT">
- <title><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></title>
- <para>Measures the number of bit errors after the forward error correction (FEC) done by inner code block (after Viterbi, LDPC or other inner code).</para>
- <para>This measure is taken during the same interval as <constant>DTV_STAT_POST_TOTAL_BIT_COUNT</constant>.</para>
- <para>In order to get the BER (Bit Error Rate) measurement, it should be divided by
- <link linkend="DTV-STAT-POST-TOTAL-BIT-COUNT"><constant>DTV_STAT_POST_TOTAL_BIT_COUNT</constant></link>.</para>
- <para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
- The frontend may reset it when a channel/transponder is tuned.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error bits counted after the inner coding.</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-POST-TOTAL-BIT-COUNT">
- <title><constant>DTV_STAT_POST_TOTAL_BIT_COUNT</constant></title>
- <para>Measures the amount of bits received after the inner coding, during the same period as
- <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link> measurement was taken.</para>
- <para>It should be noted that this measurement can be smaller than the total amount of bits on the transport stream,
- as the frontend may need to manually restart the measurement, losing some data between each measurement interval.</para>
- <para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
- The frontend may reset it when a channel/transponder is tuned.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of bits counted while measuring
- <link linkend="DTV-STAT-POST-ERROR-BIT-COUNT"><constant>DTV_STAT_POST_ERROR_BIT_COUNT</constant></link>.</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-ERROR-BLOCK-COUNT">
- <title><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></title>
- <para>Measures the number of block errors after the outer forward error correction coding (after Reed-Solomon or other outer code).</para>
- <para>This measurement is monotonically increased, as the frontend gets more bit count measurements.
- The frontend may reset it when a channel/transponder is tuned.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of error blocks counted after the outer coding.</para></listitem>
- </itemizedlist>
- </section>
- <section id="DTV-STAT-TOTAL-BLOCK-COUNT">
- <title><constant>DTV-STAT_TOTAL_BLOCK_COUNT</constant></title>
- <para>Measures the total number of blocks received during the same period as
- <link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link> measurement was taken.</para>
- <para>It can be used to calculate the PER indicator, by dividing
- <link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>
- by <link linkend="DTV-STAT-TOTAL-BLOCK-COUNT"><constant>DTV-STAT-TOTAL-BLOCK-COUNT</constant></link>.</para>
- <para>Possible scales for this metric are:</para>
- <itemizedlist mark='bullet'>
- <listitem><para><constant>FE_SCALE_NOT_AVAILABLE</constant> - it failed to measure it, or the measurement was not complete yet.</para></listitem>
- <listitem><para><constant>FE_SCALE_COUNTER</constant> - Number of blocks counted while measuring
- <link linkend="DTV-STAT-ERROR-BLOCK-COUNT"><constant>DTV_STAT_ERROR_BLOCK_COUNT</constant></link>.</para></listitem>
- </itemizedlist>
- </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>
- <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </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-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </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-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-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-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>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </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>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </section>
- <section id="atscmh-params">
- <title>ATSC-MH delivery system</title>
- <para>The following parameters are valid for ATSC-MH:</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-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-FIC-VER"><constant>DTV_ATSCMH_FIC_VER</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-PARADE-ID"><constant>DTV_ATSCMH_PARADE_ID</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-NOG"><constant>DTV_ATSCMH_NOG</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-TNOG"><constant>DTV_ATSCMH_TNOG</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SGN"><constant>DTV_ATSCMH_SGN</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-PRC"><constant>DTV_ATSCMH_PRC</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-MODE"><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-ENSEMBLE"><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-PRI"><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-SEC"><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SCCC-BLOCK-MODE"><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-A"><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-B"><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-C"><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-D"><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </section>
- <section id="dtmb-params">
- <title>DTMB delivery system</title>
- <para>The following parameters are valid for DTMB:</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-INNER-FEC"><constant>DTV_INNER_FEC</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-INTERLEAVING"><constant>DTV_INTERLEAVING</constant></link></para></listitem>
- <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </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 is the widely used cable standard. Transmission uses QAM modulation.</para>
- <para>The DVB-C Annex-C is optimized for 6MHz, and is used in Japan. It supports a subset of the Annex A modulation types, and a roll-off of 0.13, instead of 0.15</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>
- <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </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>
- <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </section>
- </section>
- <section id="frontend-property-satellite-systems">
- <title>Properties used on satellite 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>
- <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>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- <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>In addition to all parameters valid for DVB-S, DVB-S2 supports the following parameters:</para>
- <itemizedlist mark='opencircle'>
- <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</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>
- <listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
- </itemizedlist>
- <para>In addition, the <link linkend="frontend-stat-properties">DTV QoS statistics</link> are also valid.</para>
- </section>
- <section id="turbo-params">
- <title>Turbo code delivery system</title>
- <para>In addition to all parameters valid for DVB-S, turbo code supports the following parameters:</para>
- <itemizedlist mark='opencircle'>
- <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</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-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
- </itemizedlist>
- </section>
- </section>
-</section>
diff --git a/Documentation/DocBook/media/dvb/dvbstb.pdf b/Documentation/DocBook/media/dvb/dvbstb.pdf
deleted file mode 100644
index 0fa75d90c3eb..000000000000
--- a/Documentation/DocBook/media/dvb/dvbstb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/dvb/examples.xml b/Documentation/DocBook/media/dvb/examples.xml
deleted file mode 100644
index 837fb3b64b72..000000000000
--- a/Documentation/DocBook/media/dvb/examples.xml
+++ /dev/null
@@ -1,367 +0,0 @@
-<title>Examples</title>
-<para>In this section we would like to present some examples for using the DVB API.
-</para>
-<para>NOTE: This section is out of date, and the code below won't even
- compile. Please refer to the
- <ulink url="https://linuxtv.org/docs/libdvbv5/index.html">libdvbv5</ulink>
- for updated/recommended examples.
-</para>
-
-<section id="tuning">
-<title>Tuning</title>
-<para>We will start with a generic tuning subroutine that uses the frontend and SEC, as well as
-the demux devices. The example is given for QPSK tuners, but can easily be adjusted for
-QAM.
-</para>
-<programlisting>
- #include &#x003C;sys/ioctl.h&#x003E;
- #include &#x003C;stdio.h&#x003E;
- #include &#x003C;stdint.h&#x003E;
- #include &#x003C;sys/types.h&#x003E;
- #include &#x003C;sys/stat.h&#x003E;
- #include &#x003C;fcntl.h&#x003E;
- #include &#x003C;time.h&#x003E;
- #include &#x003C;unistd.h&#x003E;
-
- #include &#x003C;linux/dvb/dmx.h&#x003E;
- #include &#x003C;linux/dvb/frontend.h&#x003E;
- #include &#x003C;linux/dvb/sec.h&#x003E;
- #include &#x003C;sys/poll.h&#x003E;
-
- #define DMX "/dev/dvb/adapter0/demux1"
- #define FRONT "/dev/dvb/adapter0/frontend1"
- #define SEC "/dev/dvb/adapter0/sec1"
-
- /&#x22C6; routine for checking if we have a signal and other status information&#x22C6;/
- int FEReadStatus(int fd, fe_status_t &#x22C6;stat)
- {
- int ans;
-
- if ( (ans = ioctl(fd,FE_READ_STATUS,stat) &#x003C; 0)){
- perror("FE READ STATUS: ");
- return -1;
- }
-
- if (&#x22C6;stat &amp; FE_HAS_POWER)
- printf("FE HAS POWER\n");
-
- if (&#x22C6;stat &amp; FE_HAS_SIGNAL)
- printf("FE HAS SIGNAL\n");
-
- if (&#x22C6;stat &amp; FE_SPECTRUM_INV)
- printf("SPEKTRUM INV\n");
-
- return 0;
- }
-
-
- /&#x22C6; tune qpsk &#x22C6;/
- /&#x22C6; freq: frequency of transponder &#x22C6;/
- /&#x22C6; vpid, apid, tpid: PIDs of video, audio and teletext TS packets &#x22C6;/
- /&#x22C6; diseqc: DiSEqC address of the used LNB &#x22C6;/
- /&#x22C6; pol: Polarisation &#x22C6;/
- /&#x22C6; srate: Symbol Rate &#x22C6;/
- /&#x22C6; fec. FEC &#x22C6;/
- /&#x22C6; lnb_lof1: local frequency of lower LNB band &#x22C6;/
- /&#x22C6; lnb_lof2: local frequency of upper LNB band &#x22C6;/
- /&#x22C6; lnb_slof: switch frequency of LNB &#x22C6;/
-
- int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
- int diseqc, int pol, int srate, int fec, int lnb_lof1,
- int lnb_lof2, int lnb_slof)
- {
- struct secCommand scmd;
- struct secCmdSequence scmds;
- struct dmx_pes_filter_params pesFilterParams;
- FrontendParameters frp;
- struct pollfd pfd[1];
- FrontendEvent event;
- int demux1, demux2, demux3, front;
-
- frequency = (uint32_t) freq;
- symbolrate = (uint32_t) srate;
-
- if((front = open(FRONT,O_RDWR)) &#x003C; 0){
- perror("FRONTEND DEVICE: ");
- return -1;
- }
-
- if((sec = open(SEC,O_RDWR)) &#x003C; 0){
- perror("SEC DEVICE: ");
- return -1;
- }
-
- if (demux1 &#x003C; 0){
- if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
- &#x003C; 0){
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
-
- if (demux2 &#x003C; 0){
- if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
- &#x003C; 0){
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
-
- if (demux3 &#x003C; 0){
- if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
- &#x003C; 0){
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
-
- if (freq &#x003C; lnb_slof) {
- frp.Frequency = (freq - lnb_lof1);
- scmds.continuousTone = SEC_TONE_OFF;
- } else {
- frp.Frequency = (freq - lnb_lof2);
- scmds.continuousTone = SEC_TONE_ON;
- }
- frp.Inversion = INVERSION_AUTO;
- if (pol) scmds.voltage = SEC_VOLTAGE_18;
- else scmds.voltage = SEC_VOLTAGE_13;
-
- scmd.type=0;
- scmd.u.diseqc.addr=0x10;
- scmd.u.diseqc.cmd=0x38;
- scmd.u.diseqc.numParams=1;
- scmd.u.diseqc.params[0] = 0xF0 | ((diseqc &#x22C6; 4) &amp; 0x0F) |
- (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
- (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
-
- scmds.miniCommand=SEC_MINI_NONE;
- scmds.numCommands=1;
- scmds.commands=&amp;scmd;
- if (ioctl(sec, SEC_SEND_SEQUENCE, &amp;scmds) &#x003C; 0){
- perror("SEC SEND: ");
- return -1;
- }
-
- if (ioctl(sec, SEC_SEND_SEQUENCE, &amp;scmds) &#x003C; 0){
- perror("SEC SEND: ");
- return -1;
- }
-
- frp.u.qpsk.SymbolRate = srate;
- frp.u.qpsk.FEC_inner = fec;
-
- if (ioctl(front, FE_SET_FRONTEND, &amp;frp) &#x003C; 0){
- perror("QPSK TUNE: ");
- return -1;
- }
-
- pfd[0].fd = front;
- pfd[0].events = POLLIN;
-
- if (poll(pfd,1,3000)){
- if (pfd[0].revents &amp; POLLIN){
- printf("Getting QPSK event\n");
- if ( ioctl(front, FE_GET_EVENT, &amp;event)
-
- == -EOVERFLOW){
- perror("qpsk get event");
- return -1;
- }
- printf("Received ");
- switch(event.type){
- case FE_UNEXPECTED_EV:
- printf("unexpected event\n");
- return -1;
- case FE_FAILURE_EV:
- printf("failure event\n");
- return -1;
-
- case FE_COMPLETION_EV:
- printf("completion event\n");
- }
- }
- }
-
-
- pesFilterParams.pid = vpid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_DECODER;
- pesFilterParams.pes_type = DMX_PES_VIDEO;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(demux1, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
- perror("set_vpid");
- return -1;
- }
-
- pesFilterParams.pid = apid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_DECODER;
- pesFilterParams.pes_type = DMX_PES_AUDIO;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(demux2, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
- perror("set_apid");
- return -1;
- }
-
- pesFilterParams.pid = tpid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_DECODER;
- pesFilterParams.pes_type = DMX_PES_TELETEXT;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(demux3, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
- perror("set_tpid");
- return -1;
- }
-
- return has_signal(fds);
- }
-
-</programlisting>
-<para>The program assumes that you are using a universal LNB and a standard DiSEqC
-switch with up to 4 addresses. Of course, you could build in some more checking if
-tuning was successful and maybe try to repeat the tuning process. Depending on the
-external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be
-necessary.
-</para>
-</section>
-
-<section id="the_dvr_device">
-<title>The DVR device</title>
-<para>The following program code shows how to use the DVR device for recording.
-</para>
-<programlisting>
- #include &#x003C;sys/ioctl.h&#x003E;
- #include &#x003C;stdio.h&#x003E;
- #include &#x003C;stdint.h&#x003E;
- #include &#x003C;sys/types.h&#x003E;
- #include &#x003C;sys/stat.h&#x003E;
- #include &#x003C;fcntl.h&#x003E;
- #include &#x003C;time.h&#x003E;
- #include &#x003C;unistd.h&#x003E;
-
- #include &#x003C;linux/dvb/dmx.h&#x003E;
- #include &#x003C;linux/dvb/video.h&#x003E;
- #include &#x003C;sys/poll.h&#x003E;
- #define DVR "/dev/dvb/adapter0/dvr1"
- #define AUDIO "/dev/dvb/adapter0/audio1"
- #define VIDEO "/dev/dvb/adapter0/video1"
-
- #define BUFFY (188&#x22C6;20)
- #define MAX_LENGTH (1024&#x22C6;1024&#x22C6;5) /&#x22C6; record 5MB &#x22C6;/
-
-
- /&#x22C6; switch the demuxes to recording, assuming the transponder is tuned &#x22C6;/
-
- /&#x22C6; demux1, demux2: file descriptor of video and audio filters &#x22C6;/
- /&#x22C6; vpid, apid: PIDs of video and audio channels &#x22C6;/
-
- int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
- {
- struct dmx_pes_filter_params pesFilterParams;
-
- if (demux1 &#x003C; 0){
- if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
- &#x003C; 0){
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
-
- if (demux2 &#x003C; 0){
- if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
- &#x003C; 0){
- perror("DEMUX DEVICE: ");
- return -1;
- }
- }
-
- pesFilterParams.pid = vpid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_TS_TAP;
- pesFilterParams.pes_type = DMX_PES_VIDEO;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(demux1, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
- perror("DEMUX DEVICE");
- return -1;
- }
- pesFilterParams.pid = apid;
- pesFilterParams.input = DMX_IN_FRONTEND;
- pesFilterParams.output = DMX_OUT_TS_TAP;
- pesFilterParams.pes_type = DMX_PES_AUDIO;
- pesFilterParams.flags = DMX_IMMEDIATE_START;
- if (ioctl(demux2, DMX_SET_PES_FILTER, &amp;pesFilterParams) &#x003C; 0){
- perror("DEMUX DEVICE");
- return -1;
- }
- return 0;
- }
-
- /&#x22C6; start recording MAX_LENGTH , assuming the transponder is tuned &#x22C6;/
-
- /&#x22C6; demux1, demux2: file descriptor of video and audio filters &#x22C6;/
- /&#x22C6; vpid, apid: PIDs of video and audio channels &#x22C6;/
- int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
- {
- int i;
- int len;
- int written;
- uint8_t buf[BUFFY];
- uint64_t length;
- struct pollfd pfd[1];
- int dvr, dvr_out;
-
- /&#x22C6; open dvr device &#x22C6;/
- if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) &#x003C; 0){
- perror("DVR DEVICE");
- return -1;
- }
-
- /&#x22C6; switch video and audio demuxes to dvr &#x22C6;/
- printf ("Switching dvr on\n");
- i = switch_to_record(demux1, demux2, vpid, apid);
- printf("finished: ");
-
- printf("Recording %2.0f MB of test file in TS format\n",
- MAX_LENGTH/(1024.0&#x22C6;1024.0));
- length = 0;
-
- /&#x22C6; open output file &#x22C6;/
- if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
- |O_TRUNC, S_IRUSR|S_IWUSR
- |S_IRGRP|S_IWGRP|S_IROTH|
- S_IWOTH)) &#x003C; 0){
- perror("Can't open file for dvr test");
- return -1;
- }
-
- pfd[0].fd = dvr;
- pfd[0].events = POLLIN;
-
- /&#x22C6; poll for dvr data and write to file &#x22C6;/
- while (length &#x003C; MAX_LENGTH ) {
- if (poll(pfd,1,1)){
- if (pfd[0].revents &amp; POLLIN){
- len = read(dvr, buf, BUFFY);
- if (len &#x003C; 0){
- perror("recording");
- return -1;
- }
- if (len &#x003E; 0){
- written = 0;
- while (written &#x003C; len)
- written +=
- write (dvr_out,
- buf, len);
- length += len;
- printf("written %2.0f MB\r",
- length/1024./1024.);
- }
- }
- }
- }
- return 0;
- }
-
-</programlisting>
-
-</section>
diff --git a/Documentation/DocBook/media/dvb/fe-diseqc-recv-slave-reply.xml b/Documentation/DocBook/media/dvb/fe-diseqc-recv-slave-reply.xml
deleted file mode 100644
index 4595dbfff208..000000000000
--- a/Documentation/DocBook/media/dvb/fe-diseqc-recv-slave-reply.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<refentry id="FE_DISEQC_RECV_SLAVE_REPLY">
- <refmeta>
- <refentrytitle>ioctl FE_DISEQC_RECV_SLAVE_REPLY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_DISEQC_RECV_SLAVE_REPLY</refname>
- <refpurpose>Receives reply from a DiSEqC 2.0 command</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 dvb_diseqc_slave_reply *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_DISEQC_RECV_SLAVE_REPLY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>pointer to &dvb-diseqc-slave-reply;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Receives reply from a DiSEqC 2.0 command.</para>
-&return-value-dvb;
-
-<table pgwide="1" frame="none" id="dvb-diseqc-slave-reply">
- <title>struct <structname>dvb_diseqc_slave_reply</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>uint8_t</entry>
- <entry>msg[4]</entry>
- <entry>DiSEqC message (framing, data[3])</entry>
- </row><row>
- <entry>uint8_t</entry>
- <entry>msg_len</entry>
- <entry>Length of the DiSEqC message. Valid values are 0 to 4,
- where 0 means no msg</entry>
- </row><row>
- <entry>int</entry>
- <entry>timeout</entry>
- <entry>Return from ioctl after timeout ms with errorcode when no
- message was received</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-diseqc-reset-overload.xml b/Documentation/DocBook/media/dvb/fe-diseqc-reset-overload.xml
deleted file mode 100644
index c104df77ecd0..000000000000
--- a/Documentation/DocBook/media/dvb/fe-diseqc-reset-overload.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<refentry id="FE_DISEQC_RESET_OVERLOAD">
- <refmeta>
- <refentrytitle>ioctl FE_DISEQC_RESET_OVERLOAD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_DISEQC_RESET_OVERLOAD</refname>
- <refpurpose>Restores the power to the antenna subsystem, if it was powered
- off due to power overload.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>NULL</paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_DISEQC_RESET_OVERLOAD</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>If the bus has been automatically powered off due to power overload, this ioctl
- call restores the power to the bus. The call requires read/write access to the
- device. This call has no effect if the device is manually powered off. Not all
- DVB adapters support this ioctl.</para>
-&return-value-dvb;
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-diseqc-send-burst.xml b/Documentation/DocBook/media/dvb/fe-diseqc-send-burst.xml
deleted file mode 100644
index 9f6a68f32de3..000000000000
--- a/Documentation/DocBook/media/dvb/fe-diseqc-send-burst.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<refentry id="FE_DISEQC_SEND_BURST">
- <refmeta>
- <refentrytitle>ioctl FE_DISEQC_SEND_BURST</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_DISEQC_SEND_BURST</refname>
- <refpurpose>Sends a 22KHz tone burst for 2x1 mini DiSEqC satellite selection.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>enum fe_sec_mini_cmd *<parameter>tone</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_DISEQC_SEND_BURST</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>tone</parameter></term>
- <listitem>
- <para>pointer to &fe-sec-mini-cmd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>This ioctl is used to set the generation of a 22kHz tone burst for mini
- DiSEqC satellite
- selection for 2x1 switches.
- This call requires read/write permissions.</para>
-<para>It provides support for what's specified at
- <ulink url="http://www.eutelsat.com/files/contributed/satellites/pdf/Diseqc/associated%20docs/simple_tone_burst_detec.pdf">Digital Satellite Equipment Control
- (DiSEqC) - Simple "ToneBurst" Detection Circuit specification.</ulink>
- </para>
-&return-value-dvb;
-</refsect1>
-
-<refsect1 id="fe-sec-mini-cmd-t">
-<title>enum fe_sec_mini_cmd</title>
-
-<table pgwide="1" frame="none" id="fe-sec-mini-cmd">
- <title>enum fe_sec_mini_cmd</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="SEC-MINI-A"><constant>SEC_MINI_A</constant></entry>
- <entry align="char">Sends a mini-DiSEqC 22kHz '0' Tone Burst to
- select satellite-A</entry>
- </row><row>
- <entry align="char" id="SEC-MINI-B"><constant>SEC_MINI_B</constant></entry>
- <entry align="char">Sends a mini-DiSEqC 22kHz '1' Data Burst to
- select satellite-B</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-diseqc-send-master-cmd.xml b/Documentation/DocBook/media/dvb/fe-diseqc-send-master-cmd.xml
deleted file mode 100644
index 38cf313e121b..000000000000
--- a/Documentation/DocBook/media/dvb/fe-diseqc-send-master-cmd.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<refentry id="FE_DISEQC_SEND_MASTER_CMD">
- <refmeta>
- <refentrytitle>ioctl FE_DISEQC_SEND_MASTER_CMD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_DISEQC_SEND_MASTER_CMD</refname>
- <refpurpose>Sends a DiSEqC command</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 dvb_diseqc_master_cmd *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_DISEQC_SEND_MASTER_CMD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>pointer to &dvb-diseqc-master-cmd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Sends a DiSEqC command to the antenna subsystem.</para>
-&return-value-dvb;
-
-<table pgwide="1" frame="none" id="dvb-diseqc-master-cmd">
- <title>struct <structname>dvb_diseqc_master_cmd</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>uint8_t</entry>
- <entry>msg[6]</entry>
- <entry>DiSEqC message (framing, address, command, data[3])</entry>
- </row><row>
- <entry>uint8_t</entry>
- <entry>msg_len</entry>
- <entry>Length of the DiSEqC message. Valid values are 3 to 6</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-enable-high-lnb-voltage.xml b/Documentation/DocBook/media/dvb/fe-enable-high-lnb-voltage.xml
deleted file mode 100644
index c11890b184ad..000000000000
--- a/Documentation/DocBook/media/dvb/fe-enable-high-lnb-voltage.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<refentry id="FE_ENABLE_HIGH_LNB_VOLTAGE">
- <refmeta>
- <refentrytitle>ioctl FE_ENABLE_HIGH_LNB_VOLTAGE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_ENABLE_HIGH_LNB_VOLTAGE</refname>
- <refpurpose>Select output DC level between normal LNBf voltages or higher
- LNBf voltages.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>unsigned int <parameter>high</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_ENABLE_HIGH_LNB_VOLTAGE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>high</parameter></term>
- <listitem>
- <para>Valid flags:</para>
- <itemizedlist>
- <listitem><para>0 - normal 13V and 18V.</para></listitem>
- <listitem><para>&gt;0 - enables slightly higher voltages instead of
- 13/18V, in order to compensate for long antenna cables.</para></listitem>
- </itemizedlist>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Select output DC level between normal LNBf voltages or higher
- LNBf voltages between 0 (normal) or a value grater than 0 for higher
- voltages.</para>
-&return-value-dvb;
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-get-info.xml b/Documentation/DocBook/media/dvb/fe-get-info.xml
deleted file mode 100644
index ed0eeb29dd65..000000000000
--- a/Documentation/DocBook/media/dvb/fe-get-info.xml
+++ /dev/null
@@ -1,266 +0,0 @@
-<refentry id="FE_GET_INFO">
- <refmeta>
- <refentrytitle>ioctl FE_GET_INFO</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_GET_INFO</refname>
- <refpurpose>Query DVB frontend capabilities and returns information about
- the front-end. This call only requires read-only access to the device</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 dvb_frontend_info *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_GET_INFO</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>pointer to struct &dvb-frontend-info;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>All DVB frontend devices support the
-<constant>FE_GET_INFO</constant> ioctl. It is used to identify
-kernel devices compatible with this specification and to obtain
-information about driver and hardware capabilities. The ioctl takes a
-pointer to dvb_frontend_info which is filled by the driver. When the
-driver is not compatible with this specification the ioctl returns an error.
-</para>
-&return-value-dvb;
-
- <table pgwide="1" frame="none" id="dvb-frontend-info">
- <title>struct <structname>dvb_frontend_info</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>char</entry>
- <entry>name[128]</entry>
- <entry>Name of the frontend</entry>
- </row><row>
- <entry>fe_type_t</entry>
- <entry>type</entry>
- <entry><emphasis role="bold">DEPRECATED</emphasis>. DVBv3 type. Should not be used on modern programs, as a
- frontend may have more than one type. So, the DVBv5 API should
- be used instead to enumerate and select the frontend type.</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>frequency_min</entry>
- <entry>Minimal frequency supported by the frontend</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>frequency_max</entry>
- <entry>Maximal frequency supported by the frontend</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>frequency_stepsize</entry>
- <entry>Frequency step - all frequencies are multiple of this value</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>frequency_tolerance</entry>
- <entry>Tolerance of the frequency</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>symbol_rate_min</entry>
- <entry>Minimal symbol rate (for Cable/Satellite systems), in bauds</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>symbol_rate_max</entry>
- <entry>Maximal symbol rate (for Cable/Satellite systems), in bauds</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>symbol_rate_tolerance</entry>
- <entry>Maximal symbol rate tolerance, in ppm</entry>
- </row><row>
- <entry>uint32_t</entry>
- <entry>notifier_delay</entry>
- <entry><emphasis role="bold">DEPRECATED</emphasis>. Not used by any driver.</entry>
- </row><row>
- <entry>&fe-caps;</entry>
- <entry>caps</entry>
- <entry>Capabilities supported by the frontend</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>NOTE: The frequencies are specified in Hz for Terrestrial and Cable
- systems. They're specified in kHz for Satellite systems</para>
- </refsect1>
-
-<refsect1 id="fe-caps-t">
-<title>frontend capabilities</title>
-
-<para>Capabilities describe what a frontend can do. Some capabilities are
- supported only on some specific frontend types.</para>
-
-<table pgwide="1" frame="none" id="fe-caps">
- <title>enum fe_caps</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="FE-IS-STUPID"><constant>FE_IS_STUPID</constant></entry>
- <entry>There's something wrong at the frontend, and it can't
- report its capabilities</entry>
- </row>
- <row>
- <entry id="FE-CAN-INVERSION-AUTO"><constant>FE_CAN_INVERSION_AUTO</constant></entry>
- <entry>The frontend is capable of auto-detecting inversion</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-1-2"><constant>FE_CAN_FEC_1_2</constant></entry>
- <entry>The frontend supports FEC 1/2</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-2-3"><constant>FE_CAN_FEC_2_3</constant></entry>
- <entry>The frontend supports FEC 2/3</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-3-4"><constant>FE_CAN_FEC_3_4</constant></entry>
- <entry>The frontend supports FEC 3/4</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-4-5"><constant>FE_CAN_FEC_4_5</constant></entry>
- <entry>The frontend supports FEC 4/5</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-5-6"><constant>FE_CAN_FEC_5_6</constant></entry>
- <entry>The frontend supports FEC 5/6</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-6-7"><constant>FE_CAN_FEC_6_7</constant></entry>
- <entry>The frontend supports FEC 6/7</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-7-8"><constant>FE_CAN_FEC_7_8</constant></entry>
- <entry>The frontend supports FEC 7/8</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-8-9"><constant>FE_CAN_FEC_8_9</constant></entry>
- <entry>The frontend supports FEC 8/9</entry>
- </row>
- <row>
- <entry id="FE-CAN-FEC-AUTO"><constant>FE_CAN_FEC_AUTO</constant></entry>
- <entry>The frontend can autodetect FEC.</entry>
- </row>
- <row>
- <entry id="FE-CAN-QPSK"><constant>FE_CAN_QPSK</constant></entry>
- <entry>The frontend supports QPSK modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-16"><constant>FE_CAN_QAM_16</constant></entry>
- <entry>The frontend supports 16-QAM modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-32"><constant>FE_CAN_QAM_32</constant></entry>
- <entry>The frontend supports 32-QAM modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-64"><constant>FE_CAN_QAM_64</constant></entry>
- <entry>The frontend supports 64-QAM modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-128"><constant>FE_CAN_QAM_128</constant></entry>
- <entry>The frontend supports 128-QAM modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-256"><constant>FE_CAN_QAM_256</constant></entry>
- <entry>The frontend supports 256-QAM modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-QAM-AUTO"><constant>FE_CAN_QAM_AUTO</constant></entry>
- <entry>The frontend can autodetect modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-TRANSMISSION-MODE-AUTO"><constant>FE_CAN_TRANSMISSION_MODE_AUTO</constant></entry>
- <entry>The frontend can autodetect the transmission mode</entry>
- </row>
- <row>
- <entry id="FE-CAN-BANDWIDTH-AUTO"><constant>FE_CAN_BANDWIDTH_AUTO</constant></entry>
- <entry>The frontend can autodetect the bandwidth</entry>
- </row>
- <row>
- <entry id="FE-CAN-GUARD-INTERVAL-AUTO"><constant>FE_CAN_GUARD_INTERVAL_AUTO</constant></entry>
- <entry>The frontend can autodetect the guard interval</entry>
- </row>
- <row>
- <entry id="FE-CAN-HIERARCHY-AUTO"><constant>FE_CAN_HIERARCHY_AUTO</constant></entry>
- <entry>The frontend can autodetect hierarch</entry>
- </row>
- <row>
- <entry id="FE-CAN-8VSB"><constant>FE_CAN_8VSB</constant></entry>
- <entry>The frontend supports 8-VSB modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-16VSB"><constant>FE_CAN_16VSB</constant></entry>
- <entry>The frontend supports 16-VSB modulation</entry>
- </row>
- <row>
- <entry id="FE-HAS-EXTENDED-CAPS"><constant>FE_HAS_EXTENDED_CAPS</constant></entry>
- <entry>Currently, unused</entry>
- </row>
- <row>
- <entry id="FE-CAN-MULTISTREAM"><constant>FE_CAN_MULTISTREAM</constant></entry>
- <entry>The frontend supports multistream filtering</entry>
- </row>
- <row>
- <entry id="FE-CAN-TURBO-FEC"><constant>FE_CAN_TURBO_FEC</constant></entry>
- <entry>The frontend supports turbo FEC modulation</entry>
- </row>
- <row>
- <entry id="FE-CAN-2G-MODULATION"><constant>FE_CAN_2G_MODULATION</constant></entry>
- <entry>The frontend supports "2nd generation modulation" (DVB-S2/T2)></entry>
- </row>
- <row>
- <entry id="FE-NEEDS-BENDING"><constant>FE_NEEDS_BENDING</constant></entry>
- <entry>Not supported anymore, don't use it</entry>
- </row>
- <row>
- <entry id="FE-CAN-RECOVER"><constant>FE_CAN_RECOVER</constant></entry>
- <entry>The frontend can recover from a cable unplug automatically</entry>
- </row>
- <row>
- <entry id="FE-CAN-MUTE-TS"><constant>FE_CAN_MUTE_TS</constant></entry>
- <entry>The frontend can stop spurious TS data output</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-get-property.xml b/Documentation/DocBook/media/dvb/fe-get-property.xml
deleted file mode 100644
index 53a170ed3bd1..000000000000
--- a/Documentation/DocBook/media/dvb/fe-get-property.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<refentry id="FE_GET_PROPERTY">
- <refmeta>
- <refentrytitle>ioctl FE_SET_PROPERTY, FE_GET_PROPERTY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_SET_PROPERTY</refname>
- <refname>FE_GET_PROPERTY</refname>
- <refpurpose>FE_SET_PROPERTY sets one or more frontend properties.
- FE_GET_PROPERTY returns one or more frontend properties.</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 dtv_properties *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_PROPERTY, FE_GET_PROPERTY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>pointer to &dtv-properties;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>All DVB frontend devices support the
-<constant>FE_SET_PROPERTY</constant> and <constant>FE_GET_PROPERTY</constant>
-ioctls. The supported properties and statistics depends on the delivery system
-and on the device:</para>
-<itemizedlist>
-<listitem>
- <para><constant>FE_SET_PROPERTY:</constant></para>
-<itemizedlist>
-<listitem><para>This ioctl is used to set one or more
- frontend properties.</para></listitem>
-<listitem><para>This is the basic command to request the frontend to tune into some
- frequency and to start decoding the digital TV signal.</para></listitem>
-<listitem><para>This call requires read/write access to the device.</para></listitem>
-<listitem><para>At return, the values are updated to reflect the
- actual parameters used.</para></listitem>
-</itemizedlist>
-</listitem>
-<listitem>
- <para><constant>FE_GET_PROPERTY:</constant></para>
-<itemizedlist>
-<listitem><para>This ioctl is used to get properties and
-statistics from the frontend.</para></listitem>
-<listitem><para>No properties are changed, and statistics aren't reset.</para></listitem>
-<listitem><para>This call only requires read-only access to the device.</para></listitem>
-</itemizedlist>
-</listitem>
-</itemizedlist>
-&return-value-dvb;
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-read-status.xml b/Documentation/DocBook/media/dvb/fe-read-status.xml
deleted file mode 100644
index bc0dc2a55f19..000000000000
--- a/Documentation/DocBook/media/dvb/fe-read-status.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<refentry id="FE_READ_STATUS">
- <refmeta>
- <refentrytitle>ioctl FE_READ_STATUS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_READ_STATUS</refname>
- <refpurpose>Returns status information about the front-end. This call only
- requires read-only access to the device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>unsigned int *<parameter>status</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_READ_STATUS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>status</parameter></term>
- <listitem>
- <para>pointer to a bitmask integer filled with the values defined by
- &fe-status;.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>All DVB frontend devices support the
-<constant>FE_READ_STATUS</constant> ioctl. It is used to check about the
-locking status of the frontend after being tuned. The ioctl takes a
-pointer to an integer where the status will be written.
-</para>
-<para>NOTE: the size of status is actually sizeof(enum fe_status), with varies
- according with the architecture. This needs to be fixed in the future.</para>
-&return-value-dvb;
-</refsect1>
-
-<refsect1 id="fe-status-t">
-<title>int fe_status</title>
-
-<para>The fe_status parameter is used to indicate the current state
- and/or state changes of the frontend hardware. It is produced using
- the &fe-status; values on a bitmask</para>
-
-<table pgwide="1" frame="none" id="fe-status">
- <title>enum fe_status</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="FE-HAS-SIGNAL"><constant>FE_HAS_SIGNAL</constant></entry>
- <entry align="char">The frontend has found something above the noise level</entry>
- </row><row>
- <entry align="char" id="FE-HAS-CARRIER"><constant>FE_HAS_CARRIER</constant></entry>
- <entry align="char">The frontend has found a DVB signal</entry>
- </row><row>
- <entry align="char" id="FE-HAS-VITERBI"><constant>FE_HAS_VITERBI</constant></entry>
- <entry align="char">The frontend FEC inner coding (Viterbi, LDPC or other inner code) is stable</entry>
- </row><row>
- <entry align="char" id="FE-HAS-SYNC"><constant>FE_HAS_SYNC</constant></entry>
- <entry align="char">Synchronization bytes was found</entry>
- </row><row>
- <entry align="char" id="FE-HAS-LOCK"><constant>FE_HAS_LOCK</constant></entry>
- <entry align="char">The DVB were locked and everything is working</entry>
- </row><row>
- <entry align="char" id="FE-TIMEDOUT"><constant>FE_TIMEDOUT</constant></entry>
- <entry align="char">no lock within the last about 2 seconds</entry>
- </row><row>
- <entry align="char" id="FE-REINIT"><constant>FE_REINIT</constant></entry>
- <entry align="char">The frontend was reinitialized, application is
- recommended to reset DiSEqC, tone and parameters</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-set-frontend-tune-mode.xml b/Documentation/DocBook/media/dvb/fe-set-frontend-tune-mode.xml
deleted file mode 100644
index 99fa8a015c7a..000000000000
--- a/Documentation/DocBook/media/dvb/fe-set-frontend-tune-mode.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<refentry id="FE_SET_FRONTEND_TUNE_MODE">
- <refmeta>
- <refentrytitle>ioctl FE_SET_FRONTEND_TUNE_MODE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_SET_FRONTEND_TUNE_MODE</refname>
- <refpurpose>Allow setting tuner mode flags to the frontend.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>unsigned int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_FRONTEND_TUNE_MODE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>Valid flags:</para>
- <itemizedlist>
- <listitem><para>0 - normal tune mode</para></listitem>
- <listitem><para>FE_TUNE_MODE_ONESHOT - 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.</para></listitem>
- </itemizedlist>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Allow setting tuner mode flags to the frontend, between 0 (normal)
- or FE_TUNE_MODE_ONESHOT mode</para>
-&return-value-dvb;
-</refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-set-tone.xml b/Documentation/DocBook/media/dvb/fe-set-tone.xml
deleted file mode 100644
index 62d44e4ccc39..000000000000
--- a/Documentation/DocBook/media/dvb/fe-set-tone.xml
+++ /dev/null
@@ -1,91 +0,0 @@
-<refentry id="FE_SET_TONE">
- <refmeta>
- <refentrytitle>ioctl FE_SET_TONE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_SET_TONE</refname>
- <refpurpose>Sets/resets the generation of the continuous 22kHz tone.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>enum fe_sec_tone_mode *<parameter>tone</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_TONE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>tone</parameter></term>
- <listitem>
- <para>pointer to &fe-sec-tone-mode;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>This ioctl is used to set the generation of the continuous 22kHz tone.
- This call requires read/write permissions.</para>
-<para>Usually, satellite antenna subsystems require that the digital TV
- device to send a 22kHz tone in order to select between high/low band on
- some dual-band LNBf. It is also used to send signals to DiSEqC equipment,
- but this is done using the DiSEqC ioctls.</para>
-<para>NOTE: if more than one device is connected to the same antenna,
- setting a tone may interfere on other devices, as they may lose
- the capability of selecting the band. So, it is recommended that
- applications would change to SEC_TONE_OFF when the device is not used.</para>
-
-&return-value-dvb;
-</refsect1>
-
-<refsect1 id="fe-sec-tone-mode-t">
-<title>enum fe_sec_tone_mode</title>
-
-<table pgwide="1" frame="none" id="fe-sec-tone-mode">
- <title>enum fe_sec_tone_mode</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char" id="SEC-TONE-ON"><constant>SEC_TONE_ON</constant></entry>
- <entry align="char">Sends a 22kHz tone burst to the antenna</entry>
- </row><row>
- <entry align="char" id="SEC-TONE-OFF"><constant>SEC_TONE_OFF</constant></entry>
- <entry align="char">Don't send a 22kHz tone to the antenna
- (except if the FE_DISEQC_* ioctls are called)</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/fe-set-voltage.xml b/Documentation/DocBook/media/dvb/fe-set-voltage.xml
deleted file mode 100644
index c89a6f79b5af..000000000000
--- a/Documentation/DocBook/media/dvb/fe-set-voltage.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<refentry id="FE_SET_VOLTAGE">
- <refmeta>
- <refentrytitle>ioctl FE_SET_VOLTAGE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>FE_SET_VOLTAGE</refname>
- <refpurpose>Allow setting the DC level sent to the antenna subsystem.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>enum fe_sec_voltage *<parameter>voltage</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_VOLTAGE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>voltage</parameter></term>
- <listitem>
- <para>pointer to &fe-sec-voltage;</para>
- <para>Valid values are described at &fe-sec-voltage;.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>This ioctl allows to set the DC voltage level sent through the antenna
- cable to 13V, 18V or off.</para>
-<para>Usually, a satellite antenna subsystems require that the digital TV
- device to send a DC voltage to feed power to the LNBf. Depending on the
- LNBf type, the polarization or the intermediate frequency (IF) of the LNBf
- can controlled by the voltage level. Other devices (for example, the ones
- that implement DISEqC and multipoint LNBf's don't need to control the
- voltage level, provided that either 13V or 18V is sent to power up the
- LNBf.</para>
-<para>NOTE: if more than one device is connected to the same antenna,
- setting a voltage level may interfere on other devices, as they may lose
- the capability of setting polarization or IF. So, on those
- cases, setting the voltage to SEC_VOLTAGE_OFF while the device is not is
- used is recommended.</para>
-
-&return-value-dvb;
-</refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/dvb/frontend.xml b/Documentation/DocBook/media/dvb/frontend.xml
deleted file mode 100644
index 01210b33c130..000000000000
--- a/Documentation/DocBook/media/dvb/frontend.xml
+++ /dev/null
@@ -1,269 +0,0 @@
-<title>DVB Frontend API</title>
-
-<para>The DVB frontend API was designed to support three types of delivery systems:</para>
-<itemizedlist>
- <listitem><para>Terrestrial systems: DVB-T, DVB-T2, ATSC, ATSC M/H, ISDB-T, DVB-H, DTMB, CMMB</para></listitem>
- <listitem><para>Cable systems: DVB-C Annex A/C, ClearQAM (DVB-C Annex B), ISDB-C</para></listitem>
- <listitem><para>Satellite systems: DVB-S, DVB-S2, DVB Turbo, ISDB-S, DSS</para></listitem>
-</itemizedlist>
-<para>The DVB frontend controls several sub-devices including:</para>
-<itemizedlist>
- <listitem><para>Tuner</para></listitem>
- <listitem><para>Digital TV demodulator</para></listitem>
- <listitem><para>Low noise amplifier (LNA)</para></listitem>
- <listitem><para>Satellite Equipment Control (SEC) hardware (only for Satellite).</para></listitem>
-</itemizedlist>
-<para>The frontend can be accessed through
- <constant>/dev/dvb/adapter?/frontend?</constant>. Data types and
- ioctl definitions can be accessed by including
- <constant>linux/dvb/frontend.h</constant> in your application.
-</para>
-
-<para>NOTE: Transmission via the internet (DVB-IP)
- is not yet handled by this API but a future extension is possible.</para>
-<para>On Satellite systems, the API support for the Satellite Equipment Control
- (SEC) allows to power control and to send/receive signals to control the
- antenna subsystem, selecting the polarization and choosing the Intermediate
- Frequency IF) of the Low Noise Block Converter Feed Horn (LNBf). It
- supports the DiSEqC and V-SEC protocols. The DiSEqC (digital SEC)
-specification is available at
-<ulink url="http://www.eutelsat.com/satellites/4_5_5.html">Eutelsat</ulink>.</para>
-
-<section id="query-dvb-frontend-info">
-<title>Querying frontend information</title>
-
-<para>Usually, the first thing to do when the frontend is opened is to
- check the frontend capabilities. This is done using <link linkend="FE_GET_INFO">FE_GET_INFO</link>. This ioctl will enumerate
- the DVB API version and other characteristics about the frontend, and
- can be opened either in read only or read/write mode.</para>
-</section>
-
-<section id="dvb-fe-read-status">
-<title>Querying frontend status and statistics</title>
-
-<para>Once <link linkend="FE_GET_PROPERTY"><constant>FE_SET_PROPERTY</constant></link>
- is called, the frontend will run a kernel thread that will periodically
- check for the tuner lock status and provide statistics about the quality
- of the signal.</para>
-<para>The information about the frontend tuner locking status can be queried
- using <link linkend="FE_READ_STATUS">FE_READ_STATUS</link>.</para>
-<para>Signal statistics are provided via <link linkend="FE_GET_PROPERTY"><constant>FE_GET_PROPERTY</constant></link>.
- Please note that several statistics require the demodulator to be fully
- locked (e. g. with FE_HAS_LOCK bit set). See
- <link linkend="frontend-stat-properties">Frontend statistics indicators</link>
- for more details.</para>
-</section>
-
-&sub-dvbproperty;
-
-<section id="frontend_fcalls">
-<title>Frontend Function Calls</title>
-
-<refentry id="frontend_f_open">
- <refmeta>
- <refentrytitle>DVB frontend open()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>fe-open</refname>
- <refpurpose>Open a frontend device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>open</function></funcdef>
- <paramdef>const char *<parameter>device_name</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>device_name</parameter></term>
- <listitem>
- <para>Device to be opened.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>Open flags. Access can either be
- <constant>O_RDWR</constant> or <constant>O_RDONLY</constant>.</para>
- <para>Multiple opens are allowed with <constant>O_RDONLY</constant>. In this mode, only query and read ioctls are allowed.</para>
- <para>Only one open is allowed in <constant>O_RDWR</constant>. In this mode, all ioctls are allowed.</para>
- <para>When the <constant>O_NONBLOCK</constant> flag is given, the system calls may return &EAGAIN; when no data is available or when the device driver is temporarily busy.</para>
- <para>Other flags have no effect.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Description</title>
- <para>This system call opens a named frontend device (<constant>/dev/dvb/adapter?/frontend?</constant>)
- for subsequent use. Usually the first thing to do after a successful open is to
- find out the frontend type with <link linkend="FE_GET_INFO">FE_GET_INFO</link>.</para>
-<para>The device can be opened in read-only mode, which only allows monitoring of
- device status and statistics, or read/write mode, which allows any kind of use
- (e.g. performing tuning operations.)
-</para>
-<para>In a system with multiple front-ends, it is usually the case that multiple devices
- cannot be open in read/write mode simultaneously. As long as a front-end
- device is opened in read/write mode, other open() calls in read/write mode will
- either fail or block, depending on whether non-blocking or blocking mode was
- specified. A front-end device opened in blocking mode can later be put into
- non-blocking mode (and vice versa) using the F_SETFL command of the fcntl
- system call. This is a standard system call, documented in the Linux manual
- page for fcntl. When an open() call has succeeded, the device will be ready
- for use in the specified mode. This implies that the corresponding hardware is
- powered up, and that other front-ends may have been powered down to make
- that possible.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success <function>open</function> returns the new file
-descriptor. On error -1 is returned, and the <varname>errno</varname>
-variable is set appropriately. Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para>The caller has no permission to access the
-device.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The the device driver is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENXIO</errorcode></term>
- <listitem>
- <para>No device corresponding to this device special file
-exists.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOMEM</errorcode></term>
- <listitem>
- <para>Not enough kernel memory was available to complete the
-request.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EMFILE</errorcode></term>
- <listitem>
- <para>The process already has the maximum number of
-files open.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENFILE</errorcode></term>
- <listitem>
- <para>The limit on the total number of files open on the
-system has been reached.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODEV</errorcode></term>
- <listitem>
- <para>The device got removed.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
-
-<refentry id="frontend_f_close">
- <refmeta>
- <refentrytitle>DVB frontend close()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>fe-close</refname>
- <refpurpose>Close a frontend device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>close</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-<para>This system call closes a previously opened front-end device. After closing
- a front-end device, its corresponding hardware might be powered down
- automatically.</para>
-</refsect1>
- <refsect1>
- <title>Return Value</title>
-
- <para>The function returns <returnvalue>0</returnvalue> on
-success, <returnvalue>-1</returnvalue> on failure and the
-<varname>errno</varname> is set appropriately. Possible error
-codes:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid open file
-descriptor.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
-
-&sub-fe-get-info;
-&sub-fe-read-status;
-&sub-fe-get-property;
-&sub-fe-diseqc-reset-overload;
-&sub-fe-diseqc-send-master-cmd;
-&sub-fe-diseqc-recv-slave-reply;
-&sub-fe-diseqc-send-burst;
-&sub-fe-set-tone;
-&sub-fe-set-voltage;
-&sub-fe-enable-high-lnb-voltage;
-&sub-fe-set-frontend-tune-mode;
-
-</section>
-
-<section id="frontend_legacy_dvbv3_api">
-<title>DVB Frontend legacy API (a. k. a. DVBv3)</title>
-<para>The usage of this API is deprecated, as it doesn't support all digital
- TV standards, doesn't provide good statistics measurements and provides
- incomplete information. This is kept only to support legacy applications.</para>
-
-&sub-frontend_legacy_api;
-</section>
diff --git a/Documentation/DocBook/media/dvb/frontend_legacy_api.xml b/Documentation/DocBook/media/dvb/frontend_legacy_api.xml
deleted file mode 100644
index 8fadf3a4ba44..000000000000
--- a/Documentation/DocBook/media/dvb/frontend_legacy_api.xml
+++ /dev/null
@@ -1,654 +0,0 @@
-<section id="frontend_legacy_types">
-<title>Frontend Legacy Data Types</title>
-
-<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 standard</entry>
- <entry><constant>SYS_DVBC_ANNEX_A</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_PROPERTY">FE_GET_PROPERTY/FE_GET_SET_PROPERTY</link> ioctl's, using the <link linkend="DTV-DELIVERY-SYSTEM">DTV_DELIVERY_SYSTEM</link> parameter.
-</para>
-
-<para>In the old days, &dvb-frontend-info; used to contain
- <constant>fe_type_t</constant> field to indicate the delivery systems,
- filled with either FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC. While this is
- still filled to keep backward compatibility, the usage of this
- field is deprecated, as it can report just one delivery system, but some
- devices support multiple delivery systems. Please use
- <link linkend="DTV-ENUM-DELSYS">DTV_ENUM_DELSYS</link> instead.
-</para>
-<para>On devices that support multiple delivery systems,
- &dvb-frontend-info;::<constant>fe_type_t</constant> is filled with the
- currently standard, as selected by the last call to
- <link linkend="FE_GET_PROPERTY">FE_SET_PROPERTY</link>
- using the &DTV-DELIVERY-SYSTEM; property.</para>
-</section>
-
-<section id="fe-bandwidth-t">
-<title>Frontend bandwidth</title>
-
-<table pgwide="1" frame="none" id="fe-bandwidth">
- <title>enum fe_bandwidth</title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry id="BANDWIDTH-AUTO"><constant>BANDWIDTH_AUTO</constant></entry>
- <entry>Autodetect bandwidth (if supported)</entry>
- </row><row>
- <entry id="BANDWIDTH-1-712-MHZ"><constant>BANDWIDTH_1_712_MHZ</constant></entry>
- <entry>1.712 MHz</entry>
- </row><row>
- <entry id="BANDWIDTH-5-MHZ"><constant>BANDWIDTH_5_MHZ</constant></entry>
- <entry>5 MHz</entry>
- </row><row>
- <entry id="BANDWIDTH-6-MHZ"><constant>BANDWIDTH_6_MHZ</constant></entry>
- <entry>6 MHz</entry>
- </row><row>
- <entry id="BANDWIDTH-7-MHZ"><constant>BANDWIDTH_7_MHZ</constant></entry>
- <entry>7 MHz</entry>
- </row><row>
- <entry id="BANDWIDTH-8-MHZ"><constant>BANDWIDTH_8_MHZ</constant></entry>
- <entry>8 MHz</entry>
- </row><row>
- <entry id="BANDWIDTH-10-MHZ"><constant>BANDWIDTH_10_MHZ</constant></entry>
- <entry>10 MHz</entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-
-</section>
-
-<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.</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_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_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:
-<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;
- struct dvb_vsb_parameters vsb;
- } u;
-};
-</programlisting></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>
-</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;/
- &fe-code-rate-t; fec_inner; /&#x22C6; forward error correction (see above) &#x22C6;/
- &fe-modulation-t; modulation; /&#x22C6; modulation type (see above) &#x22C6;/
- };
-</programlisting>
-</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;
- &fe-code-rate-t; code_rate_HP; /&#x22C6; high priority stream code rate &#x22C6;/
- &fe-code-rate-t; code_rate_LP; /&#x22C6; low priority stream code rate &#x22C6;/
- &fe-modulation-t; constellation; /&#x22C6; modulation type (see above) &#x22C6;/
- &fe-transmit-mode-t; transmission_mode;
- &fe-guard-interval-t; guard_interval;
- &fe-hierarchy-t; hierarchy_information;
- };
-</programlisting>
-</section>
-</section>
-
-<section id="dvb-frontend-event">
-<title>frontend events</title>
- <programlisting>
- struct dvb_frontend_event {
- fe_status_t status;
- struct dvb_frontend_parameters parameters;
- };
-</programlisting>
- </section>
-</section>
-
-<section id="frontend_legacy_fcalls">
-<title>Frontend Legacy Function Calls</title>
-
-<para>Those functions are defined at DVB version 3. The support is kept in
- the kernel due to compatibility issues only. Their usage is strongly
- not recommended</para>
-
-<section id="FE_READ_BER">
-<title>FE_READ_BER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns the bit error rate for the signal currently
- received/demodulated by the front-end. For this command, read-only access to
- the device is sufficient.</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_READ_BER">FE_READ_BER</link>,
- uint32_t &#x22C6;ber);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_READ_BER">FE_READ_BER</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>uint32_t *ber</para>
-</entry><entry
- align="char">
-<para>The bit error rate is stored into *ber.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-</section>
-
-<section id="FE_READ_SNR">
-<title>FE_READ_SNR</title>
-
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns the signal-to-noise ratio for the signal currently received
- by the front-end. For this command, read-only access to the device is sufficient.</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_READ_SNR">FE_READ_SNR</link>, uint16_t
- &#x22C6;snr);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_READ_SNR">FE_READ_SNR</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>uint16_t *snr</para>
-</entry><entry
- align="char">
-<para>The signal-to-noise ratio is stored into *snr.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-</section>
-
-<section id="FE_READ_SIGNAL_STRENGTH">
-<title>FE_READ_SIGNAL_STRENGTH</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns the signal strength value for the signal currently received
- by the front-end. For this command, read-only access to the device is sufficient.</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_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link>, uint16_t &#x22C6;strength);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link> for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>uint16_t *strength</para>
-</entry><entry
- align="char">
-<para>The signal strength value is stored into *strength.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-</section>
-
-<section id="FE_READ_UNCORRECTED_BLOCKS">
-<title>FE_READ_UNCORRECTED_BLOCKS</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns the number of uncorrected blocks detected by the device
- driver during its lifetime. For meaningful measurements, the increment in block
- count during a specific time interval should be calculated. For this command,
- read-only access to the device is sufficient.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>Note that the counter will wrap to zero after its maximum count has been
- reached.</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_READ_UNCORRECTED_BLOCKS">FE_READ_UNCORRECTED_BLOCKS</link>, uint32_t &#x22C6;ublocks);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_READ_UNCORRECTED_BLOCKS">FE_READ_UNCORRECTED_BLOCKS</link> for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>uint32_t *ublocks</para>
-</entry><entry
- align="char">
-<para>The total number of uncorrected blocks seen by the driver
- so far.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-</section>
-
-<section id="FE_SET_FRONTEND">
-<title>FE_SET_FRONTEND</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call starts a tuning operation using specified parameters. The result
- of this call will be successful if the parameters were valid and the tuning could
- be initiated. The result of the tuning operation in itself, however, will arrive
- asynchronously as an event (see documentation for <link linkend="FE_GET_EVENT">FE_GET_EVENT</link> and
- FrontendEvent.) If a new <link linkend="FE_SET_FRONTEND">FE_SET_FRONTEND</link> operation is initiated before
- the previous one was completed, the previous operation will be aborted in favor
- of the new one. This command requires read/write 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_FRONTEND">FE_SET_FRONTEND</link>,
- struct dvb_frontend_parameters &#x22C6;p);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_SET_FRONTEND">FE_SET_FRONTEND</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- dvb_frontend_parameters
- *p</para>
-</entry><entry
- align="char">
-<para>Points to parameters for tuning operation.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Maximum supported symbol rate reached.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
-</section>
-
-<section id="FE_GET_FRONTEND">
-<title>FE_GET_FRONTEND</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call queries the currently effective frontend parameters. For this
- command, read-only access to the device is sufficient.</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_FRONTEND">FE_GET_FRONTEND</link>,
- struct dvb_frontend_parameters &#x22C6;p);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_SET_FRONTEND">FE_SET_FRONTEND</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- dvb_frontend_parameters
- *p</para>
-</entry><entry
- align="char">
-<para>Points to parameters for tuning operation.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Maximum supported symbol rate reached.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section>
-
-<section id="FE_GET_EVENT">
-<title>FE_GET_EVENT</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns a frontend event if available. If an event is not
- available, the behavior depends on whether the device is in blocking or
- non-blocking mode. In the latter case, the call fails immediately with errno
- set to EWOULDBLOCK. In the former case, the call blocks until an event
- becomes available.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>The standard Linux poll() and/or select() system calls can be used with the
- device file descriptor to watch for new events. For select(), the file descriptor
- should be included in the exceptfds argument, and for poll(), POLLPRI should
- be specified as the wake-up condition. Since the event queue allocated is
- rather small (room for 8 events), the queue must be serviced regularly to avoid
- overflow. If an overflow happens, the oldest event is discarded from the queue,
- and an error (EOVERFLOW) occurs the next time the queue is read. After
- reporting the error condition in this fashion, subsequent
- <link linkend="FE_GET_EVENT">FE_GET_EVENT</link>
- calls will return events from the queue as usual.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>For the sake of implementation simplicity, this command requires read/write
- 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 = QPSK_GET_EVENT,
- struct dvb_frontend_event &#x22C6;ev);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals <link linkend="FE_GET_EVENT">FE_GET_EVENT</link> for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- dvb_frontend_event
- *ev</para>
-</entry><entry
- align="char">
-<para>Points to the location where the event,</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>if any, is to be stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EWOULDBLOCK</para>
-</entry><entry
- align="char">
-<para>There is no event pending, and the device is in
- non-blocking mode.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EOVERFLOW</para>
-</entry><entry
- align="char">
-<para>Overflow in event queue - one or more events were lost.</para>
-</entry>
-</row></tbody></tgroup></informaltable>
-</section>
-
-<section id="FE_DISHNETWORK_SEND_LEGACY_CMD">
- <title>FE_DISHNETWORK_SEND_LEGACY_CMD</title>
-<para>DESCRIPTION</para>
-<informaltable><tgroup cols="1"><tbody><row>
-<entry align="char">
-<para>WARNING: This is a very obscure legacy command, used only at stv0299 driver. Should not be used on newer drivers.</para>
-<para>It provides a non-standard method for selecting Diseqc voltage on the frontend, for Dish Network legacy switches.</para>
-<para>As support for this ioctl were added in 2004, this means that such dishes were already legacy in 2004.</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_DISHNETWORK_SEND_LEGACY_CMD">FE_DISHNETWORK_SEND_LEGACY_CMD</link>, unsigned long cmd);</para>
-</entry>
-</row></tbody></tgroup></informaltable>
-
-<para>PARAMETERS</para>
-<informaltable><tgroup cols="2"><tbody><row>
-<entry align="char">
- <para>unsigned long cmd</para>
-</entry>
-<entry align="char">
-<para>
-sends the specified raw cmd to the dish via DISEqC.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-&return-value-dvb;
-</section>
-
-</section>
diff --git a/Documentation/DocBook/media/dvb/intro.xml b/Documentation/DocBook/media/dvb/intro.xml
deleted file mode 100644
index b5b701f5d8c2..000000000000
--- a/Documentation/DocBook/media/dvb/intro.xml
+++ /dev/null
@@ -1,211 +0,0 @@
-<title>Introduction</title>
-
-<section id="requisites">
-<title>What you need to know</title>
-
-<para>The reader of this document is required to have some knowledge in
-the area of digital video broadcasting (DVB) and should be familiar with
-part I of the MPEG2 specification ISO/IEC 13818 (aka ITU-T H.222), i.e
-you should know what a program/transport stream (PS/TS) is and what is
-meant by a packetized elementary stream (PES) or an I-frame.</para>
-
-<para>Various DVB standards documents are available from
-<ulink url="http://www.dvb.org" /> and/or
-<ulink url="http://www.etsi.org" />.</para>
-
-<para>It is also necessary to know how to access unix/linux devices and
-how to use ioctl calls. This also includes the knowledge of C or C++.
-</para>
-</section>
-
-<section id="history">
-<title>History</title>
-
-<para>The first API for DVB cards we used at Convergence in late 1999
-was an extension of the Video4Linux API which was primarily developed
-for frame grabber cards. As such it was not really well suited to be
-used for DVB cards and their new features like recording MPEG streams
-and filtering several section and PES data streams at the same time.
-</para>
-
-<para>In early 2000, we were approached by Nokia with a proposal for a
-new standard Linux DVB API. As a commitment to the development of
-terminals based on open standards, Nokia and Convergence made it
-available to all Linux developers and published it on
-<ulink url="https://linuxtv.org" /> in September 2000.
-Convergence is the maintainer of the Linux DVB API. Together with the
-LinuxTV community (i.e. you, the reader of this document), the Linux DVB
-API will be constantly reviewed and improved. With the Linux driver for
-the Siemens/Hauppauge DVB PCI card Convergence provides a first
-implementation of the Linux DVB API.</para>
-</section>
-
-<section id="overview">
-<title>Overview</title>
-
-<figure id="stb_components">
-<title>Components of a DVB card/STB</title>
-<mediaobject>
-<imageobject>
-<imagedata fileref="dvbstb.pdf" format="PS" />
-</imageobject>
-<imageobject>
-<imagedata fileref="dvbstb.png" format="PNG" />
-</imageobject>
-</mediaobject>
-</figure>
-
-<para>A DVB PCI card or DVB set-top-box (STB) usually consists of the
-following main hardware components: </para>
-
-<itemizedlist>
- <listitem>
-
-<para>Frontend consisting of tuner and DVB demodulator</para>
-
-<para>Here the raw signal reaches the DVB hardware from a satellite dish
-or antenna or directly from cable. The frontend down-converts and
-demodulates this signal into an MPEG transport stream (TS). In case of a
-satellite frontend, this includes a facility for satellite equipment
-control (SEC), which allows control of LNB polarization, multi feed
-switches or dish rotors.</para>
-
-</listitem>
- <listitem>
-
-<para>Conditional Access (CA) hardware like CI adapters and smartcard slots
-</para>
-
-<para>The complete TS is passed through the CA hardware. Programs to
-which the user has access (controlled by the smart card) are decoded in
-real time and re-inserted into the TS.</para>
-
-</listitem>
- <listitem>
- <para>Demultiplexer which filters the incoming DVB stream</para>
-
-<para>The demultiplexer splits the TS into its components like audio and
-video streams. Besides usually several of such audio and video streams
-it also contains data streams with information about the programs
-offered in this or other streams of the same provider.</para>
-
-</listitem>
-<listitem>
-
-<para>MPEG2 audio and video decoder</para>
-
-<para>The main targets of the demultiplexer are the MPEG2 audio and
-video decoders. After decoding they pass on the uncompressed audio and
-video to the computer screen or (through a PAL/NTSC encoder) to a TV
-set.</para>
-
-
-</listitem>
-</itemizedlist>
-
-<para><xref linkend="stb_components" /> shows a crude schematic of the control and data flow
-between those components.</para>
-
-<para>On a DVB PCI card not all of these have to be present since some
-functionality can be provided by the main CPU of the PC (e.g. MPEG
-picture and sound decoding) or is not needed (e.g. for data-only uses
-like &#8220;internet over satellite&#8221;). Also not every card or STB
-provides conditional access hardware.</para>
-
-</section>
-
-<section id="dvb_devices">
-<title>Linux DVB Devices</title>
-
-<para>The Linux DVB API lets you control these hardware components
-through currently six Unix-style character devices for video, audio,
-frontend, demux, CA and IP-over-DVB networking. The video and audio
-devices control the MPEG2 decoder hardware, the frontend device the
-tuner and the DVB demodulator. The demux device gives you control over
-the PES and section filters of the hardware. If the hardware does not
-support filtering these filters can be implemented in software. Finally,
-the CA device controls all the conditional access capabilities of the
-hardware. It can depend on the individual security requirements of the
-platform, if and how many of the CA functions are made available to the
-application through this device.</para>
-
-<para>All devices can be found in the <constant>/dev</constant>
-tree under <constant>/dev/dvb</constant>. The individual devices
-are called:</para>
-
-<itemizedlist>
-<listitem>
-
-<para><constant>/dev/dvb/adapterN/audioM</constant>,</para>
-</listitem>
-<listitem>
-<para><constant>/dev/dvb/adapterN/videoM</constant>,</para>
-</listitem>
-<listitem>
-<para><constant>/dev/dvb/adapterN/frontendM</constant>,</para>
-</listitem>
- <listitem>
-
-<para><constant>/dev/dvb/adapterN/netM</constant>,</para>
-</listitem>
- <listitem>
-
-<para><constant>/dev/dvb/adapterN/demuxM</constant>,</para>
-</listitem>
- <listitem>
-
-<para><constant>/dev/dvb/adapterN/dvrM</constant>,</para>
-</listitem>
- <listitem>
-
-<para><constant>/dev/dvb/adapterN/caM</constant>,</para></listitem></itemizedlist>
-
-<para>where N enumerates the DVB PCI cards in a system starting
-from&#x00A0;0, and M enumerates the devices of each type within each
-adapter, starting from&#x00A0;0, too. We will omit the &#8220;
-<constant>/dev/dvb/adapterN/</constant>&#8221; in the further discussion
-of these devices.</para>
-
-<para>More details about the data structures and function calls of all
-the devices are described in the following chapters.</para>
-
-</section>
-
-<section id="include_files">
-<title>API include files</title>
-
-<para>For each of the DVB devices a corresponding include file exists.
-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
-<constant>linux/dvb/version.h</constant> exists, which defines the
-constant <constant>DVB_API_VERSION</constant>. This document
-describes <constant>DVB_API_VERSION 5.10</constant>.
-</para>
-
-</section>
-
diff --git a/Documentation/DocBook/media/dvb/net.xml b/Documentation/DocBook/media/dvb/net.xml
deleted file mode 100644
index da095ed0b75c..000000000000
--- a/Documentation/DocBook/media/dvb/net.xml
+++ /dev/null
@@ -1,238 +0,0 @@
-<title>DVB Network API</title>
-<para>The DVB net device controls the mapping of data packages that are
- part of a transport stream to be mapped into a virtual network interface,
- visible through the standard Linux network protocol stack.</para>
-<para>Currently, two encapsulations are supported:</para>
-<itemizedlist>
- <listitem><para><ulink url="http://en.wikipedia.org/wiki/Multiprotocol_Encapsulation">
- Multi Protocol Encapsulation (MPE)</ulink></para></listitem>
- <listitem><para><ulink url="http://en.wikipedia.org/wiki/Unidirectional_Lightweight_Encapsulation">
- Ultra Lightweight Encapsulation (ULE)</ulink></para></listitem>
-</itemizedlist>
-
-<para>In order to create the Linux virtual network interfaces, an application
- needs to tell to the Kernel what are the PIDs and the encapsulation types
- that are present on the transport stream. This is done through
- <constant>/dev/dvb/adapter?/net?</constant> device node.
- The data will be available via virtual <constant>dvb?_?</constant>
- network interfaces, and will be controlled/routed via the standard
- ip tools (like ip, route, netstat, ifconfig, etc).</para>
-<para> Data types and and ioctl definitions are defined via
- <constant>linux/dvb/net.h</constant> header.</para>
-
-<section id="net_fcalls">
-<title>DVB net Function Calls</title>
-
-
-<refentry id="NET_ADD_IF">
- <refmeta>
- <refentrytitle>ioctl NET_ADD_IF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>NET_ADD_IF</refname>
- <refpurpose>Creates a new network interface for a given Packet ID.</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 dvb_net_if *<parameter>net_if</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_TONE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>net_if</parameter></term>
- <listitem>
- <para>pointer to &dvb-net-if;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>The NET_ADD_IF ioctl system call selects the Packet ID (PID) that
- contains a TCP/IP traffic, the type of encapsulation to be used (MPE or ULE)
- and the interface number for the new interface to be created. When the
- system call successfully returns, a new virtual network interface is created.</para>
-<para>The &dvb-net-if;::ifnum field will be filled with the number of the
- created interface.</para>
-
-&return-value-dvb;
-</refsect1>
-
-<refsect1 id="dvb-net-if-t">
-<title>struct <structname>dvb_net_if</structname> description</title>
-
-<table pgwide="1" frame="none" id="dvb-net-if">
- <title>struct <structname>dvb_net_if</structname></title>
- <tgroup cols="2">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry align="char">pid</entry>
- <entry align="char">Packet ID (PID) of the MPEG-TS that contains
- data</entry>
- </row><row>
- <entry align="char">ifnum</entry>
- <entry align="char">number of the DVB interface.</entry>
- </row><row>
- <entry align="char">feedtype</entry>
- <entry align="char">Encapsulation type of the feed. It can be:
- <constant>DVB_NET_FEEDTYPE_MPE</constant> for MPE encoding
- or
- <constant>DVB_NET_FEEDTYPE_ULE</constant> for ULE encoding.
- </entry>
- </row>
- </tbody>
- </tgroup>
-</table>
-</refsect1>
-</refentry>
-
-<refentry id="NET_REMOVE_IF">
- <refmeta>
- <refentrytitle>ioctl NET_REMOVE_IF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>NET_REMOVE_IF</refname>
- <refpurpose>Removes a network interface.</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>int <parameter>ifnum</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_TONE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>net_if</parameter></term>
- <listitem>
- <para>number of the interface to be removed</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>The NET_REMOVE_IF ioctl deletes an interface previously created
- via &NET-ADD-IF;.</para>
-
-&return-value-dvb;
-</refsect1>
-</refentry>
-
-
-<refentry id="NET_GET_IF">
- <refmeta>
- <refentrytitle>ioctl NET_GET_IF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>NET_GET_IF</refname>
- <refpurpose>Read the configuration data of an interface created via
- &NET-ADD-IF;.</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 dvb_net_if *<parameter>net_if</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fe_fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>FE_SET_TONE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>net_if</parameter></term>
- <listitem>
- <para>pointer to &dvb-net-if;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>The NET_GET_IF ioctl uses the interface number given by the
- &dvb-net-if;::ifnum field and fills the content of &dvb-net-if; with
- the packet ID and encapsulation type used on such interface. If the
- interface was not created yet with &NET-ADD-IF;, it will return -1 and
- fill the <constant>errno</constant> with <constant>EINVAL</constant>
- error code.</para>
-
-&return-value-dvb;
-</refsect1>
-</refentry>
-</section>
diff --git a/Documentation/DocBook/media/dvb/video.xml b/Documentation/DocBook/media/dvb/video.xml
deleted file mode 100644
index 71547fcd7ba0..000000000000
--- a/Documentation/DocBook/media/dvb/video.xml
+++ /dev/null
@@ -1,1968 +0,0 @@
-<title>DVB Video Device</title>
-<para>The DVB video device controls the MPEG2 video decoder of the DVB hardware. It
-can be accessed through <emphasis role="bold">/dev/dvb/adapter0/video0</emphasis>. Data types and and
-ioctl definitions can be accessed by including <emphasis role="bold">linux/dvb/video.h</emphasis> in your
-application.
-</para>
-<para>Note that the DVB video device only controls decoding of the MPEG video stream, not
-its presentation on the TV or computer screen. On PCs this is typically handled by an
-associated video4linux device, e.g. <emphasis role="bold">/dev/video</emphasis>, which allows scaling and defining output
-windows.
-</para>
-<para>Some DVB cards don&#8217;t have their own MPEG decoder, which results in the omission of
-the audio and video device as well as the video4linux device.
-</para>
-<para>The ioctls that deal with SPUs (sub picture units) and navigation packets are only
-supported on some MPEG decoders made for DVD playback.
-</para>
-<para>
-These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
-of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
-have been created to replace that functionality.</para>
-<section id="video_types">
-<title>Video Data Types</title>
-
-<section id="video-format-t">
-<title>video_format_t</title>
-<para>The <constant>video_format_t</constant> data type defined by
-</para>
-<programlisting>
-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
-(??) returned by VIDEO_GET_STATUS (??) and video_event (??) returned by
-VIDEO_GET_EVENT (??) which report about the display format of the current video
-stream.
-</para>
-</section>
-
-<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, /&#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-t">
-<title>video_stream_source_t</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, /&#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
-is selected the stream comes from the application through the <emphasis role="bold">write()</emphasis> system
-call.
-</para>
-</section>
-
-<section id="video-play-state-t">
-<title>video_play_state_t</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, /&#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-command">
-<title>struct video_command</title>
-<para>The structure must be zeroed before use by the application
-This ensures it can be extended safely in the future.</para>
-<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>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 {
- __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">
-<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 {
- 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
-currently frozen, stopped, or being played back. The stream_source corresponds to the seleted
-source for the video stream. It can come either from the demultiplexer or from memory.
-The video_format indicates the aspect ratio (one of 4:3 or 16:9) of the currently
-played video stream. Finally, display_format corresponds to the selected cropping
-mode in case the source video format is not the same as the format of the output
-device.
-</para>
-</section>
-
-<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; /&#x22C6; pointer to a single iframe in memory &#x22C6;/
- int32_t size;
-};
-</programlisting>
-</section>
-
-<section id="video_caps">
-<title>video capabilities</title>
-<para>A call to VIDEO_GET_CAPABILITIES returns an unsigned integer with the following
-bits set according to the hardwares capabilities.
-</para>
-<programlisting>
- /&#x22C6; bit definitions for capabilities: &#x22C6;/
- /&#x22C6; can the hardware decode MPEG1 and/or MPEG2? &#x22C6;/
- #define VIDEO_CAP_MPEG1 1
- #define VIDEO_CAP_MPEG2 2
- /&#x22C6; can you send a system and/or program stream to video device?
- (you still have to open the video and the audio device but only
- send the stream to the video device) &#x22C6;/
- #define VIDEO_CAP_SYS 4
- #define VIDEO_CAP_PROG 8
- /&#x22C6; can the driver also handle SPU, NAVI and CSS encoded data?
- (CSS API is not present yet) &#x22C6;/
- #define VIDEO_CAP_SPU 16
- #define VIDEO_CAP_NAVI 32
- #define VIDEO_CAP_CSS 64
-</programlisting>
-</section>
-
-<section id="video-system">
-<title>video_system_t</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;
-</programlisting>
-</section>
-
-<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:
-</para>
-<programlisting>
- typedef
- struct video_highlight {
- boolean active; /&#x22C6; 1=show highlight, 0=hide highlight &#x22C6;/
- uint8_t contrast1; /&#x22C6; 7- 4 Pattern pixel contrast &#x22C6;/
- /&#x22C6; 3- 0 Background pixel contrast &#x22C6;/
- uint8_t contrast2; /&#x22C6; 7- 4 Emphasis pixel-2 contrast &#x22C6;/
- /&#x22C6; 3- 0 Emphasis pixel-1 contrast &#x22C6;/
- uint8_t color1; /&#x22C6; 7- 4 Pattern pixel color &#x22C6;/
- /&#x22C6; 3- 0 Background pixel color &#x22C6;/
- uint8_t color2; /&#x22C6; 7- 4 Emphasis pixel-2 color &#x22C6;/
- /&#x22C6; 3- 0 Emphasis pixel-1 color &#x22C6;/
- uint32_t ypos; /&#x22C6; 23-22 auto action mode &#x22C6;/
- /&#x22C6; 21-12 start y &#x22C6;/
- /&#x22C6; 9- 0 end y &#x22C6;/
- uint32_t xpos; /&#x22C6; 23-22 button color number &#x22C6;/
- /&#x22C6; 21-12 start x &#x22C6;/
- /&#x22C6; 9- 0 end x &#x22C6;/
- } video_highlight_t;
-</programlisting>
-
-</section>
-<section id="video-spu">
-<title>struct video_spu</title>
-<para>Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the
-following format:
-</para>
-<programlisting>
- typedef
- struct video_spu {
- boolean active;
- int stream_id;
- } video_spu_t;
-</programlisting>
-
-</section>
-<section id="video-spu-palette">
-<title>struct video_spu_palette</title>
-<para>The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE:
-</para>
-<programlisting>
- typedef
- struct video_spu_palette {
- int length;
- uint8_t &#x22C6;palette;
- } video_spu_palette_t;
-</programlisting>
-
-</section>
-<section id="video-navi-pack">
-<title>struct 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:
-</para>
-<programlisting>
- typedef
- struct video_navi_pack {
- int length; /&#x22C6; 0 ... 1024 &#x22C6;/
- uint8_t data[1024];
- } video_navi_pack_t;
-</programlisting>
-</section>
-
-
-<section id="video-attributes-t">
-<title>video_attributes_t</title>
-<para>The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES:
-</para>
-<programlisting>
- typedef uint16_t video_attributes_t;
- /&#x22C6; bits: descr. &#x22C6;/
- /&#x22C6; 15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) &#x22C6;/
- /&#x22C6; 13-12 TV system (0=525/60, 1=625/50) &#x22C6;/
- /&#x22C6; 11-10 Aspect ratio (0=4:3, 3=16:9) &#x22C6;/
- /&#x22C6; 9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca &#x22C6;/
- /&#x22C6; 7 line 21-1 data present in GOP (1=yes, 0=no) &#x22C6;/
- /&#x22C6; 6 line 21-2 data present in GOP (1=yes, 0=no) &#x22C6;/
- /&#x22C6; 5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 &#x22C6;/
- /&#x22C6; 2 source letterboxed (1=yes, 0=no) &#x22C6;/
- /&#x22C6; 0 film/camera mode (0=camera, 1=film (625/50 only)) &#x22C6;/
-</programlisting>
-</section></section>
-
-
-<section id="video_function_calls">
-<title>Video Function Calls</title>
-
-
-<section id="video_fopen">
-<title>open()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call opens a named video device (e.g. /dev/dvb/adapter0/video0)
- for subsequent use.</para>
-<para>When an open() call has succeeded, the device will be ready for use.
- The significance of blocking or non-blocking mode is described in the
- documentation for functions where there is a difference. It does not affect the
- semantics of the open() call itself. A device opened in blocking mode can later
- be put into non-blocking mode (and vice versa) using the F_SETFL command
- of the fcntl system call. This is a standard system call, documented in the Linux
- manual page for fcntl. Only one user can open the Video Device in O_RDWR
- mode. All other attempts to open the device in this mode will fail, and an
- error-code will be returned. If the Video Device is opened in O_RDONLY
- mode, the only ioctl call that can be used is VIDEO_GET_STATUS. All other
- call will return an error code.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int open(const char &#x22C6;deviceName, int flags);</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>PARAMETERS
-</para>
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>const char
- *deviceName</para>
-</entry><entry
- align="char">
-<para>Name of specific video device.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int flags</para>
-</entry><entry
- align="char">
-<para>A bit-wise OR of the following flags:</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDONLY read-only access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_RDWR read/write access</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>O_NONBLOCK open in non-blocking mode</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>(blocking mode is the default)</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<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">
-<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></tbody></tgroup></informaltable>
-
-</section>
-<section id="video_fclose">
-<title>close()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call closes a previously opened video device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int close(int fd);</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></tbody></tgroup></informaltable>
-<para>RETURN VALUE</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>
-
-</section>
-<section id="video_fwrite">
-<title>write()</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This system call can only be used if VIDEO_SOURCE_MEMORY is selected
- in the ioctl call VIDEO_SELECT_SOURCE. The data provided shall be in
- PES format, unless the capability allows other formats. If O_NONBLOCK is
- not specified the function will block until buffer space is available. The amount
- of data to be transferred is implied by count.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>size_t write(int fd, const void &#x22C6;buf, size_t count);</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>void *buf</para>
-</entry><entry
- align="char">
-<para>Pointer to the buffer containing the PES data.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>size_t count</para>
-</entry><entry
- align="char">
-<para>Size of buf.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>RETURN VALUE</para>
-<informaltable><tgroup cols="2"><tbody><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>ENOMEM</para>
-</entry><entry
- align="char">
-<para>Attempted to write more data than the internal buffer can
- hold.</para>
-</entry>
- </row><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>
-
-</section><section id="VIDEO_STOP"
-role="subsection"><title>VIDEO_STOP</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-&VIDIOC-DECODER-CMD; instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to stop playing the current stream.
- Depending on the input parameter, the screen can be blanked out or displaying
- the last decoded frame.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_STOP, boolean
- mode);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_STOP for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>Boolean mode</para>
-</entry><entry
- align="char">
-<para>Indicates how the screen shall be handled.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>TRUE: Blank screen when stop.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>FALSE: Show last decoded frame.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_PLAY"
-role="subsection"><title>VIDEO_PLAY</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-&VIDIOC-DECODER-CMD; instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to start playing a video stream from the
- selected source.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_PLAY);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_PLAY for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_FREEZE"
-role="subsection"><title>VIDEO_FREEZE</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-&VIDIOC-DECODER-CMD; instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call suspends the live video stream being played. Decoding
- and playing are frozen. It is then possible to restart the decoding
- and playing process of the video stream using the VIDEO_CONTINUE
- command. If VIDEO_SOURCE_MEMORY is selected in the ioctl call
- VIDEO_SELECT_SOURCE, the DVB subsystem will not decode any more
- data until the ioctl call VIDEO_CONTINUE or VIDEO_PLAY is performed.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_FREEZE);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_FREEZE for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_CONTINUE"
-role="subsection"><title>VIDEO_CONTINUE</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
-&VIDIOC-DECODER-CMD; instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call restarts decoding and playing processes of the video stream
- which was played before a call to VIDEO_FREEZE was made.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_CONTINUE);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_CONTINUE for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SELECT_SOURCE"
-role="subsection"><title>VIDEO_SELECT_SOURCE</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. This ioctl was also supported by the
-V4L2 ivtv driver, but that has been replaced by the ivtv-specific
-<constant>IVTV_IOC_PASSTHROUGH_MODE</constant> ioctl.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call informs the video device which source shall be used for the input
- data. The possible sources are demux or memory. If memory is selected, the
- data is fed to the video device through the write command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_SELECT_SOURCE,
- video_stream_source_t source);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SELECT_SOURCE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_stream_source_t
- source</para>
-</entry><entry
- align="char">
-<para>Indicates which source shall be used for the Video stream.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_BLANK"
-role="subsection"><title>VIDEO_SET_BLANK</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to blank out the picture.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_SET_BLANK, boolean
- mode);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_BLANK for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>boolean mode</para>
-</entry><entry
- align="char">
-<para>TRUE: Blank screen when stop.</para>
-</entry>
- </row><row><entry
- align="char">
-</entry><entry
- align="char">
-<para>FALSE: Show last decoded frame.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_STATUS"
-role="subsection"><title>VIDEO_GET_STATUS</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to return the current status of the device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_GET_STATUS, struct
- video_status &#x22C6;status);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_STATUS for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct video_status
- *status</para>
-</entry><entry
- align="char">
-<para>Returns the current status of the Video Device.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_FRAME_COUNT"
-role="subsection"><title>VIDEO_GET_FRAME_COUNT</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
-ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_FRAME</constant> control.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to return the number of displayed frames
-since the decoder was started.</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 =
- VIDEO_GET_FRAME_COUNT, __u64 *pts);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_FRAME_COUNT for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u64 *pts
-</para>
-</entry><entry
- align="char">
-<para>Returns the number of frames displayed since the decoder was started.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_PTS"
-role="subsection"><title>VIDEO_GET_PTS</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
-ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_PTS</constant> control.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to return the current PTS timestamp.</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 =
- VIDEO_GET_PTS, __u64 *pts);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_PTS for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>__u64 *pts
-</para>
-</entry><entry
- align="char">
-<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
-</para>
-<para>
-The PTS should belong to the currently played
-frame if possible, but may also be a value close to it
-like the PTS of the last decoded frame or the last PTS
-extracted by the PES parser.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_FRAME_RATE"
-role="subsection"><title>VIDEO_GET_FRAME_RATE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to return the current framerate.</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 =
- VIDEO_GET_FRAME_RATE, unsigned int *rate);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_FRAME_RATE for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>unsigned int *rate
-</para>
-</entry><entry
- align="char">
-<para>Returns the framerate in number of frames per 1000 seconds.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_EVENT"
-role="subsection"><title>VIDEO_GET_EVENT</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is for DVB devices only. To get events from a V4L2 decoder use the V4L2
-&VIDIOC-DQEVENT; ioctl instead.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call returns an event of type video_event if available. If an event is
- not available, the behavior depends on whether the device is in blocking or
- non-blocking mode. In the latter case, the call fails immediately with errno
- set to EWOULDBLOCK. In the former case, the call blocks until an event
- becomes available. The standard Linux poll() and/or select() system calls can
- be used with the device file descriptor to watch for new events. For select(),
- the file descriptor should be included in the exceptfds argument, and for
- poll(), POLLPRI should be specified as the wake-up condition. Read-only
- permissions are sufficient for this ioctl call.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_GET_EVENT, struct
- video_event &#x22C6;ev);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_EVENT for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct video_event
- *ev</para>
-</entry><entry
- align="char">
-<para>Points to the location where the event, if any, is to be
- stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EWOULDBLOCK</para>
-</entry><entry
- align="char">
-<para>There is no event pending, and the device is in
- non-blocking mode.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>EOVERFLOW</para>
-</entry><entry
- align="char">
-<para>Overflow in event queue - one or more events were lost.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_COMMAND"
-role="subsection"><title>VIDEO_COMMAND</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
-ioctl has been replaced by the &VIDIOC-DECODER-CMD; ioctl.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl commands the decoder. The <constant>video_command</constant> struct
-is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
-&VIDIOC-DECODER-CMD; documentation for more information.</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 =
- VIDEO_COMMAND, struct video_command *cmd);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_COMMAND for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct video_command *cmd
-</para>
-</entry><entry
- align="char">
-<para>Commands the decoder.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_TRY_COMMAND"
-role="subsection"><title>VIDEO_TRY_COMMAND</title>
-<para>DESCRIPTION
-</para>
-<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
-ioctl has been replaced by the &VIDIOC-TRY-DECODER-CMD; ioctl.</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl tries a decoder command. The <constant>video_command</constant> struct
-is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
-&VIDIOC-TRY-DECODER-CMD; documentation for more information.</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 =
- VIDEO_TRY_COMMAND, struct video_command *cmd);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_TRY_COMMAND for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct video_command *cmd
-</para>
-</entry><entry
- align="char">
-<para>Try a decoder command.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_GET_SIZE"
-role="subsection"><title>VIDEO_GET_SIZE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl returns the size and aspect ratio.</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 =
- VIDEO_GET_SIZE, video_size_t *size);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_SIZE for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_size_t *size
-</para>
-</entry><entry
- align="char">
-<para>Returns the size and aspect ratio.
-</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_DISPLAY_FORMAT"
-role="subsection"><title>VIDEO_SET_DISPLAY_FORMAT</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to select the video format to be applied
- by the MPEG chip on the video.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request =
- VIDEO_SET_DISPLAY_FORMAT, video_display_format_t
- format);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_DISPLAY_FORMAT for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_display_format_t
- format</para>
-</entry><entry
- align="char">
-<para>Selects the video format to be used.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_STILLPICTURE"
-role="subsection"><title>VIDEO_STILLPICTURE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to display a still picture (I-frame). The
- input data shall contain an I-frame. If the pointer is NULL, then the current
- displayed still picture is blanked.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_STILLPICTURE,
- struct video_still_picture &#x22C6;sp);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_STILLPICTURE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>struct
- video_still_picture
- *sp</para>
-</entry><entry
- align="char">
-<para>Pointer to a location where an I-frame and size is stored.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_FAST_FORWARD"
-role="subsection"><title>VIDEO_FAST_FORWARD</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the Video Device to skip decoding of N number of I-frames.
- This call can only be used if VIDEO_SOURCE_MEMORY is selected.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_FAST_FORWARD, int
- nFrames);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_FAST_FORWARD for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int nFrames</para>
-</entry><entry
- align="char">
-<para>The number of frames to skip.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Mode VIDEO_SOURCE_MEMORY not selected.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_SLOWMOTION"
-role="subsection"><title>VIDEO_SLOWMOTION</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the video device to repeat decoding frames N number of
- times. This call can only be used if VIDEO_SOURCE_MEMORY is selected.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_SLOWMOTION, int
- nFrames);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SLOWMOTION for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int nFrames</para>
-</entry><entry
- align="char">
-<para>The number of times to repeat each frame.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EPERM</para>
-</entry><entry
- align="char">
-<para>Mode VIDEO_SOURCE_MEMORY not selected.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_GET_CAPABILITIES"
-role="subsection"><title>VIDEO_GET_CAPABILITIES</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call asks the video device about its decoding capabilities. On success
- it returns and integer which has bits set according to the defines in section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_GET_CAPABILITIES,
- unsigned int &#x22C6;cap);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_CAPABILITIES for this
- command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>unsigned int *cap</para>
-</entry><entry
- align="char">
-<para>Pointer to a location where to store the capability
- information.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_ID"
-role="subsection"><title>VIDEO_SET_ID</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl selects which sub-stream is to be decoded if a program or system
- stream is sent to the video 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 = VIDEO_SET_ID, int
- id);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_ID for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int id</para>
-</entry><entry
- align="char">
-<para>video sub-stream id</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>Invalid sub-stream id.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_CLEAR_BUFFER"
-role="subsection"><title>VIDEO_CLEAR_BUFFER</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl call clears all video buffers in the driver and in the decoder hardware.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_CLEAR_BUFFER);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_CLEAR_BUFFER for this command.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_STREAMTYPE"
-role="subsection"><title>VIDEO_SET_STREAMTYPE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl tells the driver which kind of stream to expect being written to it. If
- this call is not used the default of video PES is used. Some drivers might not
- support this call and always expect PES.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>int ioctl(fd, int request = VIDEO_SET_STREAMTYPE,
- int type);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_STREAMTYPE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>int type</para>
-</entry><entry
- align="char">
-<para>stream type</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_FORMAT"
-role="subsection"><title>VIDEO_SET_FORMAT</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl sets the screen format (aspect ratio) of the connected output device
- (TV) so that the output of the decoder can be adjusted accordingly.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_FORMAT,
- video_format_t format);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_FORMAT for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_format_t
- format</para>
-</entry><entry
- align="char">
-<para>video format of TV as defined in section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>format is not a valid video format.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_SET_SYSTEM"
-role="subsection"><title>VIDEO_SET_SYSTEM</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl sets the television output format. The format (see section ??) may
- vary from the color format of the displayed MPEG stream. If the hardware is
- not able to display the requested format the call will return an error.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_SYSTEM ,
- video_system_t system);</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_FORMAT for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_system_t
- system</para>
-</entry><entry
- align="char">
-<para>video system of TV output.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>system is not a valid or supported video system.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_SET_HIGHLIGHT"
-role="subsection"><title>VIDEO_SET_HIGHLIGHT</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl sets the SPU highlight information for the menu access of a DVD.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_HIGHLIGHT
- ,video_highlight_t &#x22C6;vhilite)</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_HIGHLIGHT for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_highlight_t
- *vhilite</para>
-</entry><entry
- align="char">
-<para>SPU Highlight information according to section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-
-</section><section id="VIDEO_SET_SPU"
-role="subsection"><title>VIDEO_SET_SPU</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl activates or deactivates SPU decoding in a DVD input stream. It can
- only be used, if the driver is able to handle a DVD stream.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_SPU ,
- video_spu_t &#x22C6;spu)</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_SPU for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_spu_t *spu</para>
-</entry><entry
- align="char">
-<para>SPU decoding (de)activation and subid setting according
- to section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>input is not a valid spu setting or driver cannot handle
- SPU.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_SET_SPU_PALETTE"
-role="subsection"><title>VIDEO_SET_SPU_PALETTE</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl sets the SPU color palette.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_SPU_PALETTE
- ,video_spu_palette_t &#x22C6;palette )</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_SPU_PALETTE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_spu_palette_t
- *palette</para>
-</entry><entry
- align="char">
-<para>SPU palette according to section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>input is not a valid palette or driver doesn&#8217;t handle SPU.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_GET_NAVI"
-role="subsection"><title>VIDEO_GET_NAVI</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl returns navigational information from the DVD stream. This is
- especially needed if an encoded stream has to be decoded by the hardware.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_GET_NAVI ,
- video_navi_pack_t &#x22C6;navipack)</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_GET_NAVI for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_navi_pack_t
- *navipack</para>
-</entry><entry
- align="char">
-<para>PCI or DSI pack (private stream 2) according to section
- ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EFAULT</para>
-</entry><entry
- align="char">
-<para>driver is not able to return navigational information</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-
-</section><section id="VIDEO_SET_ATTRIBUTES"
-role="subsection"><title>VIDEO_SET_ATTRIBUTES</title>
-<para>DESCRIPTION
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para>This ioctl is intended for DVD playback and allows you to set certain
- information about the stream. Some hardware may not need this information,
- but the call also tells the hardware to prepare for DVD playback.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-<para>SYNOPSIS
-</para>
-<informaltable><tgroup cols="1"><tbody><row><entry
- align="char">
-<para> int ioctl(fd, int request = VIDEO_SET_ATTRIBUTE
- ,video_attributes_t vattr)</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 request</para>
-</entry><entry
- align="char">
-<para>Equals VIDEO_SET_ATTRIBUTE for this command.</para>
-</entry>
- </row><row><entry
- align="char">
-<para>video_attributes_t
- vattr</para>
-</entry><entry
- align="char">
-<para>video attributes according to section ??.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
-&return-value-dvb;
-<informaltable><tgroup cols="2"><tbody><row><entry
- align="char">
-<para>EINVAL</para>
-</entry><entry
- align="char">
-<para>input is not a valid attribute setting.</para>
-</entry>
- </row></tbody></tgroup></informaltable>
- </section></section>
diff --git a/Documentation/DocBook/media/dvbstb.png.b64 b/Documentation/DocBook/media/dvbstb.png.b64
deleted file mode 100644
index e8b52fde3d11..000000000000
--- a/Documentation/DocBook/media/dvbstb.png.b64
+++ /dev/null
@@ -1,398 +0,0 @@
-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
deleted file mode 100644
index b5b557b88158..000000000000
--- a/Documentation/DocBook/media/fieldseq_bt.gif.b64
+++ /dev/null
@@ -1,447 +0,0 @@
-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
deleted file mode 100644
index 7b4c1766b407..000000000000
--- a/Documentation/DocBook/media/fieldseq_tb.gif.b64
+++ /dev/null
@@ -1,445 +0,0 @@
-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
deleted file mode 100644
index 083a7c85d107..000000000000
--- a/Documentation/DocBook/media/nv12mt.gif.b64
+++ /dev/null
@@ -1,37 +0,0 @@
-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
deleted file mode 100644
index a512078c7f24..000000000000
--- a/Documentation/DocBook/media/nv12mt_example.gif.b64
+++ /dev/null
@@ -1,121 +0,0 @@
-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
deleted file mode 100644
index 97d9ac007473..000000000000
--- a/Documentation/DocBook/media/pipeline.png.b64
+++ /dev/null
@@ -1,213 +0,0 @@
-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==
diff --git a/Documentation/DocBook/media/selection.png.b64 b/Documentation/DocBook/media/selection.png.b64
deleted file mode 100644
index 416186558cb2..000000000000
--- a/Documentation/DocBook/media/selection.png.b64
+++ /dev/null
@@ -1,206 +0,0 @@
-iVBORw0KGgoAAAANSUhEUgAABIsAAAHpCAYAAAACi7yYAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A
-/wD/oL2nkwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sLCBAiCLMGMtAAACAASURBVHja
-7d3rkds4FgZQaMohTBY7ObRCV+fgyWJy4P6wJavVIgmSAIjHOVWu3bElPkBSAj5dgpdpmqYAAAAA
-ACGEvzQBAAAAAHfCIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMDDD00A
-21wul9XXTNN0aHnP749Z39o2rK0jRzssLX/pvVve9+61S69Jdey2bn/sMTx6TAAA/cIW+oVb+2tb
-3p+izwioLIJsHYe9X+a979vae89ut6Pb1+txBwD0C3vZN0ERrFNZBAct/ZJxuVx2Vdg8v+/oLyEx
-69j7xbq2/1u2e0u75Th2Mevf8ytVzDkDAOgXjtYv3LquVP0nQRHEUVkEBTsJve/r0hfu2hdz7e0W
-27HQ4QAA9Avr7BcJiiCesAhO+GKK/YIt8SV+RscoNmippUPl1jIAQL/w3PUc7Y8JimAbYRGc9KVY
-Yu6b3OsYNUTRuQAA9AvL9AtT9LsERbCdOYsAX74ZOiVbO1M6LQCAfmH7/TzohcoiqOhLK+eXV4p1
-xP4y1krF0X1bn7dXBwIA0C+ss19oagAoR1gEJ4j9osv5iPq965imKUk59eidwNc/AIB+oX7h/HpK
-tzeMzm1oQJIv7Ra/eO/7sOWxtgAAtN0v1N+DdcIiyPQFlPP1JbZpTyehl19q1joQOhgAgH7hOf3C
-Pct9tz36c7DMbWhQwPMXUYkOQ6517P3Sj/216axJEdfWoyMBAOgXpukX5uqv7Xm/W9JgnsoiSGxr
-4FHiiyvlOu7v21pu/PqLzuuvOTHtlmIZW/bz+f1r6177ewBAv1C/8FwqjCCesAgSdwK2dAh63e+5
-fX8XuBxtt1SdkZhy6djt37vNOioAoF84Sr8wV39tzzIERvCd29Agg7knQ8T+unTk15mc64j5El17
-KsbRW75inrqR6glj79rELWsAgH5hmn7hmcckpt8HI7tMRjYAAAAA/KayCAAAAIAHYREAAAAAD8Ii
-AAAAAB6ERQAAAAA8CIsAAAAAeBAWAQAAAPAgLAIAAADgQVgEAAAAwIOwCAAAAIAHYREAAAAADz80
-AQAAqVwuF40AABWbpmn1NbvDIh0BAKDGzg3n0T8EgD7sCot0BAAAmDNNUwj6iwBQlS3fzIduQ7vd
-blobAMjuer1qhKZ6o4IiAGiZOYsAAMji0w+LAHC6jx0/unkaGgAAAAAPwiIAAAAAHoRFAAAAADwI
-iwAAAAB4EBYBAAAA8OBpaAAAFDf3ZJa5J6htef3za5eeyDb3urWnxsQuM/V7jmxX7Dr3HIMUbfj6
-+qXjurZ977Zja1vuaVOAnqgsAgCgqKWB+rt/2/r6s7Z/z3aesf0x+1fjdgFQjsoiALpyfRng3J5+
-Fb7/2+3NL8Xv/m1pWa/veX7t/XXXN4OtuWXs+fe59c/t45H2erd/Mdu/9XX0b63q5zWkWHr9/d8+
-rtfFapOY9byz9L7X5e7ZzqVKmT2VP3ts2cc966+1MmfuGKkkAvhFZREA3XgON94FNnMhzlJQNLes
-1/ffX/f62ue/fw1d3r3m9d/nlhu7/rX22rv8LW20d/voT8ztYbEBzNJrS4YMubbzzNCidLs+BzX3
-datsAjiXsAiALrwLfPYGE1uXtaVK5l2YNLes2OXurdI5svwtbaSKiFdbg5Cl18f821y1UupAZu92
-1njblwobgLG5DQ0AZqSofjkSnOSuvsmxf2fsB5SUMtT5vN2+LC82xNoziXaJNthyO11MBdHS7YUA
-5CUsAmAo91u97rdGLc1jdKQi5t08QiH8uSVrTcwcSkekWv7avuTeD1hzD2TuwcOWqqIS8wa9C01G
-nD/neV9fQzQAyhMWAUAma5NVA23KEeLMhUZHJ5g+e/9jXyscAqiLOYsA6MK7+XLW5gWK/fdnsYHP
-2uvWJtveu969ti5/bxsJzNgTDOx5JP2z1yAmNsC4T7j8+ifXdj6vs7VjlGsdQiSAc6gsAqAbz7eY
-Pf9dqmVtWd7cbWivE0LPbe/rv80tL1Vb7Vl+TBvl3g/a8nx70dIj7e9/v/b6mKer1bBfc9tZ65w8
-pdt1bh1zQdFaGwNw3GWapmnzmy6XQx1wAIAt7gHTjm4LJTuWv/uI084QYC482Pv6LfMSvXtc/Nag
-pNR+xb7+yLYeXX9MG669ZunYpN7mEeeJAsZx/4y7/P7vmP6U29AAAChq6yPm9z6S3n7t34/c648J
-Z97N49TKuQDQOpVFAED1VBY10rGMrCwCAMpRWQQAAADAIcIiAAAAAB48DQ0AADqSciJsAMYkLAIA
-gI4IgwA4SlgEAADAZh9/X9/+/ed/t8Ovf37t3PKWXje3rq3LTP2eI9sVs961969t59r2LbX16zJi
-t+Xzv1vyduE4YVHpD9SZsuDnX4COlA7HLD/Ferase2lZW7Zh6/a+vn6pDda27912rK0vVbsCAEB1
-45qFwf3H39dNIcm715fY/rWQKsV7Wj5me93Dn6VlxgZKnEdYVPLiXAgTPq7X6BBh7rWpln/kPWv7
-LigBAIDGxzUrVT+vocTS6+//thYs7A1plt73utw927kUeixt3xnhWEybzO13qe0VHtVDWFTq4nwK
-cmKDni2B0NLy7/82F/4srWdPYLRneVvWUWvgNNfuAjIAALoZ10TcHhYbwNz/LiYwStpvf3PbU47t
-zL0v727/WqvqijlmEEIIf2mCAh+oK0HR0UBhbflbbuVKsT1ry4vdhhRt/nm7PdZdYr0AADCCreHC
-0utj/m0u3EkdcuzdzntQ09MxS7Gud23iFrQ2qCwqeXFmrjBZWv7n7XZ6WFLDNgAAAGNLGeq8Vilt
-ndz53fKO7sMZc0DlPjaCpfKERTVfKBsmqy617hr2de21qeduAgAAzvM6YfKWypQS8wa9q6IpVT3z
-vPyYp4pBLGERu55i1sSXytO2q2oCAAAe44MMIc5caDQ3B1KSsVzF4dC7p6KthWgqiOohLKr5A2zj
-RNW511/LurY8NQ4AAEhv661OMY9RXxwDPAUP9/+OGjtsDB+ObufzOnMFOTHLnZvoWhhDLBNcl/xA
-PRherIUka7dfLS333Z/a9j/VOoRIAACwc0wy86SzL/3tmadvLU12/Pra2vZryz6V3OZ3f44eMwhB
-ZVGZi/jpFqi5qqAj1UJry495Gltupbdhbh1zQdFauwEAAL/72i+PkU/x+hoeRb93O/fMi1R6Iuet
-xyz1emNDQRNc10NYVOoieQl0jnoNN2KWXyoo2jMH0lnbfKTdzm5nAAA4bXyzMJnyXHVLC0FA7fsV
-cxveu7mCWjoG1EFYVPKDZ2GS5diAYW0ZtQYYJZ/gtrSuexs9h201txsAAFQ7vtkYMGx5/dHXHgk/
-atmvI+9PNYF0ioqvGqrG2O4yTdO0+U2XSwghhJuBNABQwPV3qL+j20LJjuXvPuL9KPnRBWCbtVvE
-hCrsOq9+96Muv/87pj+lsggAAKDFAeBLsCBIaJ9jSC2ERQAAAB0QHgGpCIuI++JZmZRbmTkAAFTW
-h98QHn1cPzQYFPR5+6x6+4RFRJ7IN40AAAA19dGfwp+Yx6HHPr4cQFgEAADQuNfwZy08inkEOzAu
-YREAAECjYiqKdvl50bg04Ujg+Xr7Ze5bw1q63VNYlPzgXzUCAP13zNyeDJB/bJErCAKKB0WtERYB
-AACcNWA9IRBy6xnDX3eColXCoowUbgLQk0kTAMQPRguFQItPOHuzDXuCoss/jieV9Ul+Hrg2TwqK
-WnvioLAIAABgy6CvgiBoz/apKGL4a1dQFE1YBAAA8DywK3hrWOoAJ1U1EXR3XQuKNhEWAQAAYwwW
-Gw6B9u6foAgERXsIiwAAgLYHgoUnia4tgBESwcL1UUlQ9Hn7bCo8EhYBAAB1DvJOenR860GLoAh+
-f4ZUFBS1RlgEAACUH8R5ZLx9hJyfMYKiQ4RFAABAuoGSEMj+w9mfQ4Kiw4RFAADA+iBICAS08Fkl
-KEpCWAQAACMPrMwLBPTyeSYoSkZYBAAAPQ6ahEDASJ95gqKkhEUAANDaoMgtYQB/PhMFRckJiwAA
-oJYBjxAIYNvnpqAoC2ERAADkHlQIgQDyf+4JipIRFgEAwN4Bg3mBAKogKEpLWAQAAK+DASEQQDME
-RekJiwAAGIpbwgD6ISjKQ1gEAEAXhEAAZPl+GSwoCkFYBABA7Z10IRAAZ30HDRgUhSAsAgDgrA64
-eYEAqPl7atCgKARhEQAAR/17CSGEMP186WSHa9HNEAIB70zTNMy+Xi4XBzyRkYOiEIRFAAAs+ff8
-gYcQCICSRg+KQhAWAQCMSQgE0J25KioVR/EERb8IiwAAenJGCPS/6ctgZHp0sG+OB0AFXkMk4dF7
-gqI/hEUAAC04qxLof5O2B6B7gqKvhEUAAGcSAgFQ2HOlkSojQdE7wiIAgFxOvCUMAFgnKHpPWAQA
-sJUQCIBOjFxlJCiaJywCALgTAgHAEARFy4RFAED/zAsEAKvuVUa9VxgJitYJi6DmD+uf7//+8s/6
-a969ds/yU6xn636uLWttu9e2dakdX5cRuy2Xf/K2ETBDCAQAbHBWUPS63toJi6BSS8HD9DM+eJh7
-barlH3nPme2y5h7+LC0zNlACdnaq/r5+v/Zzh0NCIADotsJIUBRPWAQ1fjg/BSKxQc+WQGhp+fd/
-mwtJltaTOzCKbZe5fSoV6giPYKXD9BQCFSMEAoCx+x+Cok2ERVCZtUBk6e9TLP/5dqrY8CfmFqy1
-7Xm+/evdenO3C5CgMyQEAoC+xibT1EV1kaBoO2ERVCp38LG0/CPhT+vt8q4dlsIrARVDdBTffB58
-hGv29X7+d3v8/+v1+ui0AgDEqiUo+rx9NhUeCYug48FcCOfPI7T3faXmQOrtWECJa/eo5xAIAKi8
-v9Dw/EU1BUWtERYByQaXe8OQ5/fVXNUEvVyruQiBAIBaCIqOERZBJ7ZOVJ17/bUParfs1+utaGu3
-oKkgIqczrpfHuf+l43NzMABgpD5IQ/MXCYqOExZBxQPCI6HDWoVOzCPhlwaNJQa8c3MFCWPo9Zov
-zbUEAPRGUJSGsAgqE/M0siOBydryY546VmKw+jpwzt0ukMtZlXOuBQAgeb+m8uoiQVE6wiKo0Gsw
-kmKwOjcvUEuTMadul63rjQ3STHA9SGdJCAQAUA1BUVrCIqjU0m1ksYPFtWWcFWrEPHZ+7rH1Z243
-43BLGADATD+pwuoiQVF6wiKoWMzgce01a4HMGQPZLWFXim3J3Y4G+w11boRAAABdERTlISwCoHlC
-IACAgn2v6dczUmurMBIUpSMsAqDejoh5gQAAiCAoSktYBBQf4BuIIwQCACAVQVF6wiLAgJyk3BIG
-AEApgqI8hEUARBECAQDwpX9Y4ZPRchgtKApBWATgS14IBAAAb40YFIUgLALolnmBAADI3ufsuLpo
-1KAoBGERQHtfyEIgAADIauSgKARhEUBV3BIGAEBzfdjOqotGD4pCEBYBlPkCFQIBAED1BEW/CIsA
-DhACAQCMpbYKmmmaqtmO1quLBEV/CIsA3n3ZmRcIAACGISj6SlgEDEUIBABAT16reWqpNGqJoOg7
-YRHQDbeEAQAAWwiK3hMWAdUTAgEAQGQ/9qnSqHSVUWvzFgmK5gmLgNMIgQAAgDMIipYJi4DkzAsE
-AADnu1f5mMfoK0HROmEREE0IBAAAtOysoOh1vbUTFgEhBLeEAQBAr0pWGNU8b5GgKJ6wCDonBAIA
-AEYnKNpGWASNEgIBAACb+vODzmEkKNpOWASVMS8QAABAGrUERZ+3z6bCI2ERFCIEAgAAanC5XLJW
-F9Uyb1FNQVFrhEWQ+oOxUCgkBAIAAHaPJzIHRmcTFB0jLILaPrSFQAAAALsJio4TFkEhQiAAAKCq
-MUqH1UWCojSERZD6A1coBAAAUJygKJ2/nE4AAABASqUrlgRFaaksghQfhD+1Af1QHQcAQEsERemp
-LAIAAIBB1fCI+yMERXkIiwAAAIDmCYrScRsaJOYWHlrkVkoAgIHHMB08FU1QlJbKIgAAAKBZgqL0
-hEUAAABAkwRFeQiLAAAAAGaMFhSFICwCAAAAeGvEoCgEYREAAADAN6MGRSEIiwAAAGB4l8sl+TJb
-fsLayEFRCCH8cEkAQJkOTo5OGAAAaY0eFIUgLAJgcCV/8VpalyAJAOB8gqJfhEUADKPmUuh32yZA
-AgAoR1D0h7CIrgduBlp9DqqdM4xyHj9vv3MTACAfQdFXwiKAmcH5K4P19o9hT/vlfAQASENQ9J2w
-iO4HjQZUGKyPeXxG2V/nIQCQyuVyGa5PJSh6T1iEgR0kOIcN2H2OOA8BANoiKJonLAIwYG+6vfne
-Ls5BAIBlgqJlf2kCeh/oGVRyxvntvNO22gkAoE6ConUqiwAyDthDUOWRsi1xDgIAHHFWUPS63tqp
-LAIoMGAXdhxrP5yDAABHCYriCYsYYuBnkIQBu/ZCmwIA4xIUbSMsAjhhwI42Ort9tTEAMApB0XbC
-IoYZABoY4Vpoo120jfMQACCVWoKi1ibRFhYBGKhrD+0OANAdQdF+wiKAkwfqBusCCwAA0hIUHSMs
-YqjBoAEp1Pe54LoEACAlQdFxP5xGAOebpilcLpfh9rkVKY6NUAwAID9BURrCIoBKjBQY1Rqc5Gz/
-uWULkQAA0hAUpSMsYriB4YgVHLR1rfR+ftb0eVBDW79ug/AIAGA7QVFawiJgqIH5O7UNznsOjGpo
-69rb9nn7BEcAAOsERekJixhuIN77YJxjg3OD9D4/C1q93gVHAADLBEV5CIsAKhyk9xZonhV09NSG
-giMAgGWConSERQCRg3QD9PaOmXMSAGAMgqJkHc0Qpin85ZQip5oHMgZZ7BmglwwhejlHS+/HSLeY
-lj4nAQBqJChK2nkPIQRhEW0NisAAvbXvmslxse8AgDFcNoKiPIRFGMhCxV9+LZ+jpYMitAMAQA6j
-BUUhCItoZKB4HwAZCGFwPt71v9b+joE2AQDa6sO1ZMSgKARhEUCSwTnaXfsAAPRl1KAoBGERmbSU
-SEvPcY62t72CkPh20lYAANuNHBSFICyikcGOQSKtnaejEhQ5PwEAWjd6UBSCsAjAgFwbD9N22g8A
-YJmg6BdhEcnlmNi6pW0G134egg7tCACQk6DoD2ERBjuAa157AgAMTVD0lbCIpFqu0FFdRM2D8NrP
-z5zbJ9jQrgBAe/25lvoagqLvhEU0O5Ax0IE+OxbU8zkLANA7QdF7wiIAqiXM0MYAALkIiuYJi0im
-xYmtc+4DBt+ue+0IAECdBEXLhEUYlAMAAAxstB/NBUXrhEUAVNepEAQDAJDDWUHR63prJyyiukHj
-1kFi6kGlW9HgXIIiAAD9uRwERfGERQAAAEDXBEXbCIs4rMdKHNVFcM41oqoIAMDYJzVB0XbCIqqy
-d6BogAkAAMCrWoKi1ibRFhYBsImqIgAA/boW+nSCov2ERVTz4VLbQNGtaAAAAG0SFB0jLKIbqhLA
-9QsAQJyefxwXFB0nLIJBP0BpSy1himsCAICaCYrSEBZRxaAx1UBYdQK9XRsAANBKf/Xs8ZigKB1h
-EQCnEvICAHCUoCgtYRG79Dyxdc59Bdc9AABn9ud67NMJitITFtEdVQoAAABjEBTl8cOpBZBOjl9q
-eg5AhbsAAG32UWvs1wmK0lFZxKkfNLk+UFIv1+03AAAA9RIUpaWyCCCRnkNFgSkAgD7cnLOrigRF
-6akswoDRvlMxt2kBAMA8QVEeKovodhB8uVwEPBTjXKvvMwAAQL9Uny6F0YKiEFQWAVT7hSxMAQCA
-c40YFIWgsoiTBsSlBsGpq4umaTKAJ9t1AQAALfVHex8bjRoUhaCyCKDKL+aavngFYgAAjGbkoCgE
-lUUAmwlPjlOhBwDoC+rP1Wr0oCgElUWc8IFY+kMl9fp8OYx9HZQ4/oIUAAA4h6DoF5VFACtKBoSC
-IgAAatdrn1VQ9IewiKID5V4+VEx07bz3pQsAAP0QFH0lLGIIqZ+KRl9qODcERQAAtDK26o2g6Dth
-EVCMwG6cL1wAAGiBoOg9E1xTbHB/9oDYRNfUSFAEAEAr/dbe+q6ConnCIoATv3BrJxQFAKBHgqJl
-bkMDKGz0aiLVVAAA+m5nEhStU1nErB6fguZWNM4+/wQlAABwnrOCotf11k5lEUBmAiIAAPRjzyco
-iqeyiLd6rCrKtT2qi5g7z1QSAQBAHQRF26gsAjhIIAQAgL5tvQRF26ksAjhomqYvfwAAgDrUEhS1
-Nom2yiLeDnxTqTWVvlwuBvUUuYZUHQEAUKve+6qCov2ERQAZCY4AAGihr9pbf1VQdIzb0Fj8sDjC
-wBi+X18q2gAAIC9B0XHCIoYlzOIsQiMAAGrup7bcVxUUpSEsAjjxyxgAAEhDUJSOsIgsA9dWqnZU
-F1HDdSc0AgBAP/UYQVFawiKASr6MAQCA7QRF6QmLACohMAIAoMY+as39VEFRHj+c+qQepLZ2a9fl
-ckm6/9M0ub2t4XPj7C9C5w8AAOwjKEpHWATw5F1QUzpAEhgBAFCbe5+41n6qoCgtt6ExdFVRru12
-O1FfLpfL40+L1yUAAPRMUJSesAhgg5LBkcAIAIDa1NZHFRTlISwC2KlEaCQwAgCAc40WFIUgLBqe
-W9Dybb9B/jgERgAAjDaOHKWPOmJQFIKwCCCJ0nMaAQAAeY0aFIUgLCLhQBnIdy2oLgIAoDY991FH
-DopCEBa5sMk60NfGzqPWz6cc++K6AACgZqMHRSEIiwCyUG0HAMAIevshUFD0i7DIBW1QnHl/VFHg
-fAIAgPoJiv744XQAyONyuQh3AIDmTdOkavqlj1fzsXKO7CMo+kplEUBjnQkBFAAApCMo+k5YNCC3
-oJXfL4N7AACgxDjm+U+r48ySBEXvCYsACnxp+zIGAIC6CIrmCYsGo6rovP0zuAfXAwD47qb0mKZk
-lVFL54mgaJkJrvGFAax2MlzvAAD0QlC0TmURQAGeIAIAwNn90RJVRrX/yHhWUPS63toJiwaiMsAx
-wPkEAACjEhTFExYBcAphFwDAOXJXGNXYzxMUbSMsAgAAALolKNpOWDQIv+A7Fpyv5XmLzLkEAOjH
-6p+2eL7UEhS1Nom2sAgAAADojqBoP2HRAPwC4JjgXLL9AAC8U+IJaWcQFB0jLAIAAAC6ISg6TlgE
-QBTzFgEA6OttcUYVuaAoDWFR59zi4diAawEAgBEIitIRFgEAABDFjzx9a7m6SFCUlrAIgFM7EAAA
-cISgKD1hUcek/o4RuBYAANiitR8HBUV5CIsAAACA5gmK0hEWdcqv9I4V5JLr1ybXAgDov+Kc2UtQ
-lJawCAAAAGiWoCi9H04rYpjU9iu/puAz4ZLlOpimyecNAECnfb0cBEV5qCzqkCDDMcNxBgAA0hgt
-KApBWEQEv/IDJQnVAACMA2sxYlAUgrDIIItqPjgdO1wHrgcAMO6AeowaFIUgLAJoml98AAAgvZGD
-ohCERRiIahuK6PXXN9VFAAD01rcbPSgKQVjk4sMxBNeENgYAIIQgKLoTFjFL5Qzgs6JvgiIAfI/A
-H4KiP4RFYJCMjpT2064AAEMTFH0lLNLpx7GkUTWFlbm3xXWhPQEAchEUfScsovpBKBiU+9wYrS21
-IwBAGYKi94RFOv5UOEB2TF2baNMcbaf9AICzxzo1ERTNExYB+OJuarsEHtoMAOAoQdEyYRHNDELB
-4NxniPbVVgD4nsH5cpSgaJ2wyMWGY4tjp507bR9tBADw1VlB0et6aycsAkg8QM+theq/UtsoENEm
-AACxBEXxhEU0NwgFA3SfJ+/aH+0AADBHULSNsMigAMeYho5Ta4Fu6cBo1GtGWAkAME9QtJ2wiGYH
-oWCA7rNl7rg4BwEACKGeoKi1SbSFRQ0PEHCsOW9wfsZxEehuP072DwD0Vxm3Dyoo2u+HUx+g/g5Q
-60HR5XI5pR3v6+whaNMRBwCIJyg6RlhENwMpMCCv/3PmrPZ9Xm9rn3fOSQCAbQRFxwmLDGZpYEA8
-TZPKiMHPKddHnvOwxrZ1nQAA7CcoSkNYBFCxHqv+agiM7l6344z2Fg4B0INeftyk7XNFUJSOsAgf
-6uDaPGXfagxJ5rYpxbEQCgEA5CMoSktY1BiDjXEHwn6tGe8ccp347AUAYJ2gKL2/nFYGpIDr8sx9
-9TkEAMBegqI8hEUN8cu2Ab9zwHljv9H2AADvCYrSERYBGLTbf20OANA0QVFa5iwySABci1W1hQo6
-5xwAwBaCovRUFjXC4MmAzLngHBmpTbSLcw4AIIagKA+VRQAG7FW3kYDUOQcAcKbRgqIQVBY1IcdA
-yaDBOcF5A3bXn88r5xwAQBtGDIpCUFkERQZqwh0M1tO0n2vJOQcAUMqoQVEIwiIAA/YG21No5JwD
-AMhp5KAoBLehVc8taAZvJc8N0h1vt/6UaWO0CQB9j13gDKMHRSGoLAJINlDn3HYfsYPqvAMASEtQ
-9IuwyMACcB11dVxGCI2cgwAA6QmK/hAWVUwZZ3+Du9THdJomg0aDcRaOXS+fo85HAIC8BEVfCYsM
-DnBMnX8Mc821FB65BgFokR8zaZGg6DthEaT+gvypDaBW7zqvNQRIOtUAAOcQFL0nLAJgaEtBTcog
-SSAEAFAXQdE8YREAzBDwAAD0SVC0TFgEKQaU//z637lb0O7/DgAAwLkEReuERVBAzDxGAiUAAIC8
-zgqKXtdbO2ERVGItUBImAQDQRL/WE9G6O569EBTFExZBQnOBToonpKlOAgAA2EdQtI2wCAqICXEE
-SgAAAOkJirYTFkEl1kKcFGFS7HIESgAAHOpzuhWNStQSFH3ePpsKj4RF0IhS1UkxyxEmAQAAtasp
-KGqNsAg64nY3AACg6jFLoYozQdExwiIY7cPZ7W4AAEDHBEXHCYuAL2q63S12ewAAgPSmaWpumwVF
-aQiLgM3MnwQAANRGUJSOsAjIwvxJAABj80Q0ShIUpSUsAk5j/iQA8i3Z/QAADThJREFUAOAoQVF6
-wiKgWm53AwAAlgiK8hAWAU1zuxsAABCCoCglYRHQPYESAAD0TVCUlrAIIJg/CQAAWiUoSk9YBBDB
-/EkAADv6NZ6IxnM/NsO5ICjKQ1gEkOrLz+1uAADQndGCohCERQBFCZQAAGjBNE0aIYwZFIUgLAKo
-jvmTAADgfKMGRSEIiwCaY/4kAKAl5i1q85iNbuSgKARhEUCX3O4GAAD7jB4UhSAsAhiW290AACjW
-92ykukxQ9IuwCID3X+gV3e4Wuz0AALCXoOgPYREAu5k/CQCgL6POVyQo+kpYBEBW5k8CAKBmgqLv
-hEUAnM78SQDQN09Ea+c4jUZQ9J6wCIDqmT8JAIDUBEXzhEUAdMH8SQAAB/o3g1UVCYqWCYsAGIb5
-kwAAEBStExYBwBPzJwEAI1FR9HnKemsnLAKADdzuBgDQJkFRPGERACTmdjcAePO95YloVR6TIn2j
-Co67oGgbYREAnECgBABQhqBoO2ERAFTK/EkAQA4jzVNUS1D0eftsKjwSFgFAo86cP+kjXL92gP67
-OSAAQFVqCopaIywCgI6VCpQ+/r6uvkagBIB5i85t+1P6Iicdb0HRMcIiABhcqdvdBEoAQAmCouOE
-RQDAonuYNH3p/Ny+do4igqCoTtbMch6B1b+XEP43OSgAEOHsuYnOqCoSFKUhLAIADoupCEoVKIV/
-VzqewiQAGJKgKB1hEQBQRLFA6d+IXzEFSgB0aKSnnH3rQwiKkhIWAQDVmAuUrtfrr05wovmTBEoA
-0A9BUXrCIgCgHTEBzr+J5kcQKAGEEH7NO5OyYqX1J6KNXL2z9bwpQVCUh7AIAOhLTYGSMAkAihEU
-pSMsAgDGUypQUp0EwIDOqBwTFKUlLAIAeGctxHG7GwBUQVCUnrAIAGAPt7sBwDelq4oERXkIiwAA
-cnG7G9BRAGCSa2LOkx6NFhSFICwCADiXQAkAqjViUBSCsAgAoH7mTwKgcj1WFY0aFIUgLAIAaF8l
-8ydNP0O4/ONwANC+kYOiEIRFAABjKBQoTT+fOtrhGvWez/9ujg80wLxFLJ0bPRk9KApBWAQAwF2p
-291eO+V/X1dfI1ACoARB0S/CIgAA4qyESZfL5UtlUdLOu0AJoEo9VRUJiv4QFgEAkG7Q8E8I06OT
-fYvrnEcEQSmWI0wCYPY7RFD0hbAIAIBTxYQ4KQIl1UkA6ago6puwCACA6q2FOKWqk2K2BYB2CIre
-ExYBANC8UtVJscsRKNErT0Tjfh70QFA0T1gEAMAQagqUhEkA5xIULRMWAQDAfbBg/iSAWSqKxiEs
-AgCADcyfBNCus4Ki1/XWTlgEAAAJud0NtjFvUf1UFKVdbwuERQAAUJjb3QDKEhRtIywCAIAKCZSo
-VeonolH3se6BoGg7YREAADTK/EkAK59flQRFn7fPpsIjYREAAHTK/EnAXj1UFdUUFLVGWAQAAANz
-uxvQI0HRMcIiAABgkUCJV6nnLfJEtHqOaw8ERccJiwAAgMPMnwTUQFCUhrAIAADIzvxJUKeeKroE
-RekIiwAAgCq43S3xAPZpPwVk9E5QlJawCAAAaEYNt7u1GLx8/H0VGNHtvFCCovSERQAAQDdKVCe1
-WpkkMKJHgqI8hEUAAMBQSlQn1TBv0ud/t2/bkTIw8kS0Oo3choKidIRFAAAAzwO/CsKkmO2I3Zec
-gRFUc90KipISFgEAAGwZlJ44b9KekCdnYNRCFYtqpQGuSUFRcsIiAACAlAPXjPMm7b29TYUR3V5v
-gqIshEUAAAClB7iZAqWt74kJjKafjhdjGy0oCkFYBAAAUKV3IU6qW9y+L3PS4PDu+hgwKApBWAQA
-ANCMUvMlAeMGRSEIiwAAALqR6va2PXMZnTWwtl7r7Wm9tRAWAQAADCBn1ZEgwXqtty/Coozc9QsA
-AJwt5glqHwb01mu9p663NsIiAACAzsQERAb01mu9day3RsIiAACATpQKiUYc0Fuv9Y5EWJTY5+2m
-EQAAgHrGKAkDolEH9NZrvaMRFgEAAHQoR0g04oDeeq13RMIiAACATuQKiEYd0Fuv9Y7qL00AAACA
-Ab31Wi93wiIAAAAM6K3XenkQFgEAAGBAb73WW3C9tRMWAQAAYEBvvdZbaL0tEBYBAABgQG+91ltg
-va0QFgEAAGBAb73Wm3m9LREWAQAAMEuQYL3W2856UxEWAQAA8JYBvfVabzvrTekyTdO0+U2XSwgh
-hNvt5tMTAMjuer2GEELY0W2hZMfydx9xenSO9RWhFS3fLgMtKhkgffzuR11+/3dMf0plEQAAAAAP
-wiIAAAAAHn5oAgAAgLG1OKcKkI/KIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwYIJrAAAAivq4
-frz9+7mJtre8/vm1SxN3z71ubl1bl5n6PUe2K3adW4/DWvsfPb5737PlmJrc/T2VRQAAABSzNHB/
-929bX3/W9u/ZzjO2/+gxOrrcrcve856alt8qlUUAAAAUsVb18zpoX3r9/d8+rh+L1Sdbq19itu91
-uXu28/73qapz9tiyjyWWneo9Z+xvb1QWAQAAkF3M7WGxAczSa3Pac9vbnu08M7RYu+3r8/b5eM3W
-dj/aFjmO8xnnUQuERQAAABSzNQhZen3Mv81VK6UOZPZu52i3Qe1p99zhmYqi79yGBgAAABFShjqf
-t88vy4sNsfZMon10H9fmYzozbMndHqMSFgEAANCleyBzDzS2VBWVmDfoXfVTrsqnFPv4/HevYRd9
-ERYBAABApBwhzlxodHRC59T7WGM4pIIoD2ERAAAAxWy9bWntaWdrnquL7v8dY2sIcXQ7n9d55oTd
-e7Z9yzHds2+520OF1HcmuAYAACC7mKdOzT1ZbG0enVqeHrZlO1sLKO5PQXv9s8WeY5b7ONdyHtVG
-ZREAAABFPM9zs6UqaOn1MQP8Ek/T2rOde+ZFamVC55T7lqo9SsxD1QuVRQAAABSz9RHzex9Jb7+O
-i7l1b8utc3uqkfa8p6blt+oyTdO0+U2XSwghhNvtpgUBgOyu12sIIYQd3RZKdix/9xGnRwdcXxEA
-zvbxux91+f3fMf0plUUAAAAAPJizCACA09yrxl7NVbBvef3za5cq4udeN7eurctM/Z4j2xW7ztT7
-eH/t2nGda//YZS7tz1q77DlmAL1SWQQAwCmWBvbv/m3r68/a/j3becb2x+5jDccixTLn9qXm9oc9
-Pq4fi38gRrHKopikvvQvG3vWs+fLxS8yfpEBAOb7DDH9taXX3//ter0u9pP29AvXtu91uXu2c6mP
-d6RftsWWdR89FiXsOWZ7zw+ojcmaSaFIZVGqXx5S/nqzd3v37r9fZAAA1sOGd3+/9votPz6msue2
-tz3bWWvgcsaxOLq81tof4EzZK4u2/mq05XVry1/7ZWPLLw4pvlBTbXcNHQS/yAAAOfoae19/u90W
-K5zvP3jN9V9S9lf2budaFXlpe6uacrRnquW11P4AZ8paWbT1V6PUy6/h1wO/yPjCBQD6kzNcWqrk
-fve61z9792duOTX05e7bkONHyL3tD9CzIreh5f6CWftlo9aORMntzn1Puy9XAKBmr2HDliqSEkHK
-7XYTWpx8fmh/gD9+1LhRZ06SfOQLodQEhEe+BN+VYKdc9mtbqCoCAHqVo5/zroJmy5QKqfclV9+x
-tr7snvYH6NmPkXe+9nCn1Q6T0AgAiO2LbekjrD3tLKav8lwtErvuPU/KPbKdc/2qVo5diW0+crtd
-D+0PkNtfNW7UvQz0tRz0zKdb7Nnu5+2v5YumxPbMlfECALz2tbY+DGTtCbO1PBxky3a21E86eiy2
-PiE4VT+9l/YHKKVIZdHR0s21JyDs/WWjhvmM/CIDAIzouX+3pSpo6fUxfbsSc2nu2c49fdaUUzds
-DWy27mOq45dif1K1P0DPslYWbf3VKPXya3uKQ6rt9osMANCDrQ/7qPmhJr3u17uK8b3bnGo/j94F
-0Op5BVDSZZqmafObLpdNH55rQcJrBcrWx83HLv/19ak+/Pc+Qn7rdqfc19flbA1+UuwLAGz9rt3R
-baFkx/J3H/F+lD59/wPA6T5+96Muv/87pj9VZM6iFGn93mXU8uQGv8gAAAAALShSWQQAcITKokY6
-liqLAKA6eyqLfmg2AADoj2kCANhLWAQAAB0SBgGwl7BohV9kAAAAgJEIi1YIgwAAAICRCIsAAMji
-Y6VCGwCo01+aAAAAAIA7lUUAACR10QQA0PZ3+TRN0+Y3XXQBAIDydnRbKNmx1EcEgC76UyqLAAAo
-1vkEAOq3KyzSEQAAAADokwmuAQAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
-AA/CIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
-AA/CIgAAAAAehEUAAAAAPAiLAAAAAHgQFgEAAADwICwCAAAA4EFYBAAAAMCDsAgAAACAB2ERAAAA
-AA/CIgAAAAAe/g/10lQlA3JSSwAAAABJRU5ErkJggg==
diff --git a/Documentation/DocBook/media/typical_media_device.svg b/Documentation/DocBook/media/typical_media_device.svg
deleted file mode 100644
index f0c82f72c4b6..000000000000
--- a/Documentation/DocBook/media/typical_media_device.svg
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg stroke-linejoin="round" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" clip-path="url(#a)" xml:space="preserve" fill-rule="evenodd" height="178.78mm" viewBox="0 0 24285.662 17877.829" width="251.99mm" version="1.2" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" preserveAspectRatio="xMidYMid" stroke-width="28.222"><defs><clipPath id="a" clipPathUnits="userSpaceOnUse"><rect y="0" x="0" width="28000" height="21000"/></clipPath></defs><g transform="matrix(1.004 0 0 1 -2185.6 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#fcf" d="m12231 4800c-516 0-1031 515-1031 1031v4124c0 516 515 1032 1031 1032h8538c516 0 1032-516 1032-1032v-4124c0-516-516-1031-1032-1031h-8538z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ffc" d="m3595 15607c-293 0-585 292-585 585v2340c0 293 292 586 585 586h3275c293 0 586-293 586-586v-2340c0-293-293-585-586-585h-3275z"/></g><g transform="translate(-2197.3 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#e6e6e6" d="m2663 2186c-461 0-922 461-922 922v11169c0 461 461 923 922 923h3692c461 0 922-462 922-923v-11169c0-461-461-922-922-922h-3692z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4461 8602h-2260v-1086h4520v1086h-2260z"/><path fill="none" d="m4461 8602h-2260v-1086h4520v1086h-2260z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="8275" x="2579" class="TextPosition"><tspan fill="#000000">Audio decoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4461 11772h-2260v-1270h4520v1270h-2260z"/><path fill="none" d="m4461 11772h-2260v-1270h4520v1270h-2260z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="11353" x="2617" class="TextPosition"><tspan fill="#000000">Video decoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4453 10217h-2269v-1224h4537v1224h-2268z"/><path fill="none" d="m4453 10217h-2269v-1224h4537v1224h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="9821" x="2571" class="TextPosition"><tspan fill="#000000">Audio encoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.RectangleShape"><path fill="#cfc" d="m15711 12832h-3810v-1281h7620v1281h-3810z"/><path fill="none" d="m15711 12832h-3810v-1281h7620v1281h-3810z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="12407" x="12377" class="TextPosition"><tspan fill="#000000">Button Key/IR input logic</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2411.8)" class="com.sun.star.drawing.RectangleShape"><path fill="#cfe7f5" d="m14169 14572h-2268v-1412h4536v1412h-2268z"/><path fill="none" d="m14169 14572h-2268v-1412h4536v1412h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14082" x="12882" class="TextPosition"><tspan fill="#000000">EEPROM</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#fc9" d="m5140 17662h-1563v-1715h3126v1715h-1563z"/><path fill="none" d="m5140 17662h-1563v-1715h3126v1715h-1563z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="17020" x="4276" class="TextPosition"><tspan fill="#000000">Sensor</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 8030 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 8030 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 9612 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 9612 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6721 11100 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m6721 11100 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2411.8)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 13854 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 13854 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 12163 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 12163 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 17158 670-353v176h2028v-176l671 353-671 354v-177h-2028v177l-670-354z"/><path fill="none" d="m9962 17158 670-353v176h2028v-176l671 353-671 354v-177h-2028v177l-670-354z" stroke="#3465af"/></g><g transform="matrix(0 .83339 -1.0005 0 30268 -5276.3)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m23229 12779 1009-978 1009 978h-505v2959h505l-1009 979-1009-979h504v-2959h-504z"/><path fill="none" d="m23229 12779 1009-978 1009 978h-505v2959h505l-1009 979-1009-979h504v-2959h-504z" stroke="#3465af"/></g><g transform="translate(-9973.6 -666.6)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="706px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15832" x="24341" class="TextPosition" transform="matrix(0,-1,1,0,8509,40173)"><tspan fill="#000000">System Bus</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m13151 9262h-1250v-875h2499v875h-1249z"/><path fill="none" d="m13151 9262h-1250v-875h2499v875h-1249z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="9040" x="12215" class="TextPosition"><tspan fill="#000000">Demux</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9996 8765 373-357v178h1130v-178l374 357-374 358v-179h-1130v179l-373-358z"/><path fill="none" d="m9996 8765 373-357v178h1130v-178l374 357-374 358v-179h-1130v179l-373-358z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9996 7378 373-358v179h1130v-179l374 358-374 358v-179h-1130v179l-373-358z"/><path fill="none" d="m9996 7378 373-358v179h1130v-179l374 358-374 358v-179h-1130v179l-373-358z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m16322 7992h-4421v-1270h8841v1270h-4420z"/><path fill="none" d="m16322 7992h-4421v-1270h8841v1270h-4420z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="7573" x="12786" class="TextPosition"><tspan fill="#000000">Conditional Access Module</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4445 13287h-2269v-1224h4537v1224h-2268z"/><path fill="none" d="m4445 13287h-2269v-1224h4537v1224h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="12891" x="2601" class="TextPosition"><tspan fill="#000000">Video encoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6721 12634 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m6721 12634 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m20791 7545 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m20791 7545 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2028 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14478" x="1990" class="TextPosition"><tspan fill="#000000">Radio / Analog TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="700" class="TextParagraph"><tspan y="10724" x="14956" class="TextPosition"><tspan fill="#000000">Digital TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-8970.5 -1395.8)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="494px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="19167" x="14724" class="TextPosition"><tspan fill="#000000">PS.: picture is not complete: other blocks may be present</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="18561" x="4199" class="TextPosition"><tspan fill="#000000">Webcam</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.RectangleShape"><path fill="#f90" d="m14552 16372h-2650v-1412h5299v1412h-2649z"/><path fill="none" d="m14552 16372h-2650v-1412h5299v1412h-2649z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15882" x="12265" class="TextPosition"><tspan fill="#000000">Processing blocks</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 15654 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 15654 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6702 16954 397-353v176h1201v-176l398 353-398 354v-177h-1201v177l-397-354z"/><path fill="none" d="m6702 16954 397-353v176h1201v-176l398 353-398 354v-177h-1201v177l-397-354z" stroke="#3465af"/></g><g transform="translate(-2479.5 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="8792" x="22850" class="TextPosition"><tspan fill="#000000">Smartcard</tspan></tspan></tspan></text>
-</g><g transform="matrix(1.0048 0 0 1 -2207.4 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#fcf" d="m2766 2600c-333 0-666 333-666 666v2668c0 333 333 666 666 666h18368c333 0 667-333 667-666v-2668c0-333-334-666-667-666h-18368z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m5121 5155h-1614v-1816h3227v1816h-1613z"/><path fill="none" d="m5121 5155h-1614v-1816h3227v1816h-1613z" stroke="#3465af"/><text font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextShape"><tspan class="TextParagraph"><tspan y="4111" x="4374" class="TextPosition"><tspan fill="#000000">Tuner</tspan></tspan></tspan><tspan class="TextParagraph"><tspan y="4814" x="4151" class="TextPosition"><tspan fill="#000000">FM/TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ff8080" d="m2902 3702c0 111 40 202 88 202h530c48 0 89-91 89-202 0-110-41-202-89-202h-530c-48 0-88 92-88 202z"/><path fill="none" d="m2902 3702c0 111 40 202 88 202h530c48 0 89-91 89-202 0-110-41-202-89-202h-530c-48 0-88 92-88 202z" stroke="#3465af"/><path fill="#ffb3b3" d="m2902 3702c0 111 40 202 88 202s88-91 88-202c0-110-40-202-88-202s-88 92-88 202z"/><path fill="none" d="m2902 3702c0 111 40 202 88 202s88-91 88-202c0-110-40-202-88-202s-88 92-88 202z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ff8080" d="m2903 4267c0 110 40 202 88 202h530c48 0 89-92 89-202s-41-203-89-203h-530c-48 0-88 93-88 203z"/><path fill="none" d="m2903 4267c0 110 40 202 88 202h530c48 0 89-92 89-202s-41-203-89-203h-530c-48 0-88 93-88 203z" stroke="#3465af"/><path fill="#ffb3b3" d="m2903 4267c0 110 40 202 88 202s88-92 88-202-40-203-88-203-88 93-88 203z"/><path fill="none" d="m2903 4267c0 110 40 202 88 202s88-92 88-202-40-203-88-203-88 93-88 203z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 4196 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 4196 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9979 4150 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z"/><path fill="none" d="m9979 4150 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m16500 6189h-4500v-1389h9e3v1389h-4500z"/><path fill="none" d="m16500 6189h-4500v-1389h9e3v1389h-4500z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="5710" x="12051" class="TextPosition"><tspan fill="#000000">Satellite Equipment Control (SEC)</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#cff" d="m13400 4600h-1400v-1e3h2800v1e3h-1400z"/><path fill="none" d="m13400 4600h-1400v-1e3h2800v1e3h-1400z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="4316" x="12465" class="TextPosition"><tspan fill="#000000">Demod</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9979 5451 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z"/><path fill="none" d="m9979 5451 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z" stroke="#3465af"/></g><path fill="#ff9" d="m7855.1 9099v7302h-1270v-14605h1270v7303z"/><path fill="none" d="m7855.1 9099v7302h-1270v-14605h1270v7303z" stroke="#3465af"/><text y="-6640.4663" x="-20770.572" transform="rotate(-90)" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="7409.5396" x="-11193.634" class="TextPosition" transform="matrix(0,-1,1,0,-4473,23627)"><tspan fill="#000000">I2C Bus (control bus)</tspan></tspan></tspan></text>
-<g transform="translate(-2197.3 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="3278" x="9391" class="TextPosition"><tspan fill="#000000">Digital TV Frontend</tspan></tspan></tspan></text>
-</g><g transform="matrix(1.015 0 0 .99994 -2233.3 -2185.7)" class="com.sun.star.drawing.CustomShape"><g stroke="#3465af" fill="none"><path d="m3e3 2800c-18 0-35 1-53 3"/><path d="m2915 2808c-17 3-35 7-52 12"/><path d="m2832 2830c-16 6-33 12-49 20"/><path d="m2754 2864c-15 8-31 17-46 27"/><path d="m2681 2909c-14 10-28 21-42 32"/><path d="m2614 2962c-13 12-26 24-38 37"/><path d="m2554 3023c-11 13-22 27-33 41"/><path d="m2502 3091c-10 14-19 29-28 45"/><path d="m2459 3164c-8 16-15 32-22 49"/><path d="m2426 3243c-5 17-10 34-14 51"/><path d="m2406 3326c-3 18-5 35-6 53"/><path d="m2400 3411v53"/><path d="m2400 3497v53"/><path d="m2400 3582v53"/><path d="m2400 3668v53"/><path d="m2400 3753v53"/><path d="m2400 3839v53"/><path d="m2400 3924v53"/><path d="m2400 4009v54"/><path d="m2400 4095v53"/><path d="m2400 4180v53"/><path d="m2400 4266v53"/><path d="m2400 4351v53"/><path d="m2400 4437v53"/><path d="m2400 4522v53"/><path d="m2400 4607v54"/><path d="m2400 4693v53"/><path d="m2400 4778v53"/><path d="m2400 4864v53"/><path d="m2400 4949v53"/><path d="m2400 5035v53"/><path d="m2400 5120v53"/><path d="m2400 5205v54"/><path d="m2400 5291v53"/><path d="m2400 5376v53"/><path d="m2400 5462v53"/><path d="m2400 5547v53"/><path d="m2400 5633v53"/><path d="m2400 5718v53"/><path d="m2400 5803c0 18 1 36 3 53"/><path d="m2408 5888c4 18 8 35 13 52"/><path d="m2431 5971c6 16 13 33 20 49"/><path d="m2466 6049c8 15 17 31 27 46"/><path d="m2511 6122c10 14 21 28 32 42"/><path d="m2564 6188c12 13 25 26 38 38"/><path d="m2626 6248c13 11 27 23 41 33"/><path d="m2694 6300c14 10 29 19 45 27"/><path d="m2768 6343c15 7 32 15 48 21"/><path d="m2847 6375c17 5 34 10 51 14"/><path d="m2930 6395c17 2 35 4 53 5"/><path d="m3015 6400h53"/><path d="m3100 6400h53"/><path d="m3186 6400h53"/><path d="m3271 6400h53"/><path d="m3357 6400h53"/><path d="m3442 6400h53"/><path d="m3527 6400h54"/><path d="m3613 6400h53"/><path d="m3698 6400h53"/><path d="m3784 6400h53"/><path d="m3869 6400h53"/><path d="m3955 6400h53"/><path d="m4040 6400h53"/><path d="m4125 6400h54"/><path d="m4211 6400h53"/><path d="m4296 6400h53"/><path d="m4382 6400h53"/><path d="m4467 6400h53"/><path d="m4553 6400h53"/><path d="m4638 6400h53"/><path d="m4723 6400h54"/><path d="m4809 6400h53"/><path d="m4894 6400h53"/><path d="m4980 6400h53"/><path d="m5065 6400h53"/><path d="m5151 6400h53"/><path d="m5236 6400h53"/><path d="m5322 6400h53"/><path d="m5407 6400h53"/><path d="m5492 6400h53"/><path d="m5578 6400h53"/><path d="m5663 6400h53"/><path d="m5749 6400h53"/><path d="m5834 6400h53"/><path d="m5920 6400h53"/><path d="m6005 6400h53"/><path d="m6090 6400h53"/><path d="m6176 6400h53"/><path d="m6261 6400h53"/><path d="m6347 6400h53"/><path d="m6432 6400h53"/><path d="m6518 6400h53"/><path d="m6603 6400h53"/><path d="m6688 6400h54"/><path d="m6774 6400h53"/><path d="m6859 6400h53"/><path d="m6945 6400h53"/><path d="m7030 6400h53"/><path d="m7116 6400h53"/><path d="m7201 6400h53"/><path d="m7286 6400h54"/><path d="m7372 6400h53"/><path d="m7457 6400h53"/><path d="m7543 6400h53"/><path d="m7628 6400h53"/><path d="m7714 6400h53"/><path d="m7799 6400h53"/><path d="m7884 6400h54"/><path d="m7970 6400h53"/><path d="m8055 6400h53"/><path d="m8141 6400h53"/><path d="m8226 6400h53"/><path d="m8312 6400h53"/><path d="m8397 6400h53"/><path d="m8482 6400h54"/><path d="m8568 6400h53"/><path d="m8653 6400h53"/><path d="m8739 6400h53"/><path d="m8824 6400h53"/><path d="m8910 6400h53"/><path d="m8995 6400h53"/><path d="m9081 6400h53"/><path d="m9166 6400h53"/><path d="m9251 6400h53"/><path d="m9337 6400h53"/><path d="m9422 6400h53"/><path d="m9508 6400h53"/><path d="m9593 6400h53"/><path d="m9679 6400h53"/><path d="m9764 6400h53"/><path d="m9849 6400h53"/><path d="m9935 6400h53"/><path d="m10020 6400h53"/><path d="m10106 6400h53"/><path d="m10191 6400h53"/><path d="m10277 6400h53"/><path d="m10362 6400h53"/><path d="m10447 6400h53"/><path d="m10533 6400h53"/><path d="m10618 6400h53"/><path d="m10704 6400h53"/><path d="m10789 6400h53"/><path d="m10875 6400h53"/><path d="m10960 6400h53"/><path d="m11045 6400h54"/><path d="m11131 6400h53"/><path d="m11216 6400h53"/><path d="m11302 6400h53"/><path d="m11387 6400h53"/><path d="m11473 6400h53"/><path d="m11558 6400h53"/><path d="m11643 6400h54"/><path d="m11729 6400h53"/><path d="m11814 6400h53"/><path d="m11900 6400h53"/><path d="m11985 6400h53"/><path d="m12071 6400h53"/><path d="m12156 6400h53"/><path d="m12241 6400h54"/><path d="m12327 6400h53"/><path d="m12412 6400h53"/><path d="m12498 6400h53"/><path d="m12583 6400h53"/><path d="m12669 6400h53"/><path d="m12754 6400h53"/><path d="m12839 6400h54"/><path d="m12925 6400h53"/><path d="m13010 6400h53"/><path d="m13096 6400h53"/><path d="m13181 6400h53"/><path d="m13267 6400h53"/><path d="m13352 6400h53"/><path d="m13438 6400h53"/><path d="m13523 6400h53"/><path d="m13608 6400h53"/><path d="m13694 6400h53"/><path d="m13779 6400h53"/><path d="m13865 6400h53"/><path d="m13950 6400h53"/><path d="m14036 6400h53"/><path d="m14121 6400h53"/><path d="m14206 6400h53"/><path d="m14292 6400h53"/><path d="m14377 6400h53"/><path d="m14463 6400h53"/><path d="m14548 6400h53"/><path d="m14634 6400h53"/><path d="m14719 6400h53"/><path d="m14804 6400h54"/><path d="m14890 6400h53"/><path d="m14975 6400h53"/><path d="m15061 6400h53"/><path d="m15146 6400h53"/><path d="m15232 6400h53"/><path d="m15317 6400h53"/><path d="m15402 6400h54"/><path d="m15488 6400h53"/><path d="m15573 6400h53"/><path d="m15659 6400h53"/><path d="m15744 6400h53"/><path d="m15830 6400h53"/><path d="m15915 6400h53"/><path d="m16000 6400h54"/><path d="m16086 6400h53"/><path d="m16171 6400h53"/><path d="m16257 6400h53"/><path d="m16342 6400h53"/><path d="m16428 6400h53"/><path d="m16513 6400h53"/><path d="m16598 6400h54"/><path d="m16684 6400h53"/><path d="m16769 6400h53"/><path d="m16855 6400h53"/><path d="m16940 6400h53"/><path d="m17026 6400h53"/><path d="m17111 6400h53"/><path d="m17196 6400h54"/><path d="m17282 6400h53"/><path d="m17367 6400h53"/><path d="m17453 6400h53"/><path d="m17538 6400h53"/><path d="m17624 6400h53"/><path d="m17709 6400h53"/><path d="m17795 6400h53"/><path d="m17880 6400h53"/><path d="m17965 6400h53"/><path d="m18051 6400h53"/><path d="m18136 6400h53"/><path d="m18222 6400h53"/><path d="m18307 6400h53"/><path d="m18393 6400h53"/><path d="m18478 6400h53"/><path d="m18563 6400h53"/><path d="m18649 6400h53"/><path d="m18734 6400h53"/><path d="m18820 6400h53"/><path d="m18905 6400h53"/><path d="m18991 6400h53"/><path d="m19076 6400h53"/><path d="m19161 6400h54"/><path d="m19247 6400h53"/><path d="m19332 6400h53"/><path d="m19418 6400h53"/><path d="m19503 6400h53"/><path d="m19589 6400h53"/><path d="m19674 6400h53"/><path d="m19759 6400h54"/><path d="m19845 6400h53"/><path d="m19930 6400h53"/><path d="m20016 6400h53"/><path d="m20101 6400h53"/><path d="m20187 6400h53"/><path d="m20272 6400h53"/><path d="m20357 6400h54"/><path d="m20443 6400h53"/><path d="m20528 6400h53"/><path d="m20614 6400c17-1 35-2 53-5"/><path d="m20699 6390c17-4 34-9 51-14"/><path d="m20781 6365c16-6 32-13 48-21"/><path d="m20858 6329c15-8 31-17 45-27"/><path d="m20930 6283c14-10 28-21 42-32"/><path d="m20996 6229c13-12 25-25 37-38"/><path d="m21055 6167c11-14 22-28 33-42"/><path d="m21106 6098c10-15 19-30 27-45"/><path d="m21148 6024c7-16 14-33 20-49"/><path d="m21179 5944c5-17 9-34 13-51"/><path d="m21197 5861c2-18 4-35 4-53"/><path d="m21201 5776v-54"/><path d="m21201 5690v-53"/><path d="m21201 5605v-53"/><path d="m21201 5519v-53"/><path d="m21201 5434v-53"/><path d="m21201 5348v-53"/><path d="m21201 5263v-53"/><path d="m21201 5178v-54"/><path d="m21201 5092v-53"/><path d="m21201 5007v-53"/><path d="m21201 4921v-53"/><path d="m21201 4836v-53"/><path d="m21201 4750v-53"/><path d="m21201 4665v-53"/><path d="m21201 4579v-53"/><path d="m21201 4494v-53"/><path d="m21201 4409v-53"/><path d="m21201 4323v-53"/><path d="m21201 4238v-53"/><path d="m21201 4152v-53"/><path d="m21201 4067v-53"/><path d="m21201 3981v-53"/><path d="m21201 3896v-53"/><path d="m21201 3811v-53"/><path d="m21201 3725v-53"/><path d="m21201 3640v-53"/><path d="m21201 3554v-53"/><path d="m21201 3469v-53"/><path d="m21201 3383c-1-17-3-35-5-52"/><path d="m21190 3299c-4-17-8-35-14-51"/><path d="m21165 3217c-6-16-13-33-21-49"/><path d="m21129 3140c-9-16-18-31-28-46"/><path d="m21082 3068c-10-14-21-28-33-42"/><path d="m21027 3002c-12-13-24-25-37-37"/><path d="m20965 2944c-14-12-28-22-42-33"/><path d="m20896 2893c-15-9-30-18-46-27"/><path d="m20821 2852c-16-8-32-14-49-20"/><path d="m20741 2821c-17-5-34-9-51-12"/><path d="m20658 2804c-18-3-35-4-53-4"/><path d="m20573 2800h-53"/><path d="m20487 2800h-53"/><path d="m20402 2800h-53"/><path d="m20316 2800h-53"/><path d="m20231 2800h-53"/><path d="m20146 2800h-54"/><path d="m20060 2800h-53"/><path d="m19975 2800h-53"/><path d="m19889 2800h-53"/><path d="m19804 2800h-53"/><path d="m19718 2800h-53"/><path d="m19633 2800h-53"/><path d="m19548 2800h-54"/><path d="m19462 2800h-53"/><path d="m19377 2800h-53"/><path d="m19291 2800h-53"/><path d="m19206 2800h-53"/><path d="m19120 2800h-53"/><path d="m19035 2800h-53"/><path d="m18950 2800h-54"/><path d="m18864 2800h-53"/><path d="m18779 2800h-53"/><path d="m18693 2800h-53"/><path d="m18608 2800h-53"/><path d="m18522 2800h-53"/><path d="m18437 2800h-53"/><path d="m18352 2800h-54"/><path d="m18266 2800h-53"/><path d="m18181 2800h-53"/><path d="m18095 2800h-53"/><path d="m18010 2800h-53"/><path d="m17924 2800h-53"/><path d="m17839 2800h-53"/><path d="m17753 2800h-53"/><path d="m17668 2800h-53"/><path d="m17583 2800h-53"/><path d="m17497 2800h-53"/><path d="m17412 2800h-53"/><path d="m17326 2800h-53"/><path d="m17241 2800h-53"/><path d="m17155 2800h-53"/><path d="m17070 2800h-53"/><path d="m16985 2800h-53"/><path d="m16899 2800h-53"/><path d="m16814 2800h-53"/><path d="m16728 2800h-53"/><path d="m16643 2800h-53"/><path d="m16557 2800h-53"/><path d="m16472 2800h-53"/><path d="m16387 2800h-54"/><path d="m16301 2800h-53"/><path d="m16216 2800h-53"/><path d="m16130 2800h-53"/><path d="m16045 2800h-53"/><path d="m15959 2800h-53"/><path d="m15874 2800h-53"/><path d="m15789 2800h-54"/><path d="m15703 2800h-53"/><path d="m15618 2800h-53"/><path d="m15532 2800h-53"/><path d="m15447 2800h-53"/><path d="m15361 2800h-53"/><path d="m15276 2800h-53"/><path d="m15191 2800h-54"/><path d="m15105 2800h-53"/><path d="m15020 2800h-53"/><path d="m14934 2800h-53"/><path d="m14849 2800h-53"/><path d="m14763 2800h-53"/><path d="m14678 2800h-53"/><path d="m14593 2800h-54"/><path d="m14507 2800h-53"/><path d="m14422 2800h-53"/><path d="m14336 2800h-53"/><path d="m14251 2800h-53"/><path d="m14165 2800h-53"/><path d="m14080 2800h-53"/><path d="m13994 2800h-53"/><path d="m13909 2800h-53"/><path d="m13824 2800h-53"/><path d="m13738 2800h-53"/><path d="m13653 2800h-53"/><path d="m13567 2800h-53"/><path d="m13482 2800h-53"/><path d="m13396 2800h-53"/><path d="m13311 2800h-53"/><path d="m13226 2800h-53"/><path d="m13140 2800h-53"/><path d="m13055 2800h-53"/><path d="m12969 2800h-53"/><path d="m12884 2800h-53"/><path d="m12798 2800h-53"/><path d="m12713 2800h-53"/><path d="m12628 2800h-53"/><path d="m12542 2800h-53"/><path d="m12457 2800h-53"/><path d="m12371 2800h-53"/><path d="m12286 2800h-53"/><path d="m12200 2800h-53"/><path d="m12115 2800h-53"/><path d="m12030 2800h-54"/><path d="m11944 2800h-53"/><path d="m11859 2800h-53"/><path d="m11773 2800h-53"/><path d="m11688 2800h-53"/><path d="m11602 2800h-53"/><path d="m11517 2800h-53"/><path d="m11432 2800h-54"/><path d="m11346 2800h-53"/><path d="m11261 2800h-53"/><path d="m11175 2800h-53"/><path d="m11090 2800h-53"/><path d="m11004 2800h-53"/><path d="m10919 2800h-53"/><path d="m10834 2800h-54"/><path d="m10748 2800h-53"/><path d="m10663 2800h-53"/><path d="m10577 2800h-53"/><path d="m10492 2800h-53"/><path d="m10406 2800h-53"/><path d="m10321 2800h-53"/><path d="m10236 2800h-54"/><path d="m10150 2800h-53"/><path d="m10065 2800h-53"/><path d="m9979 2800h-53"/><path d="m9894 2800h-53"/><path d="m9808 2800h-53"/><path d="m9723 2800h-53"/><path d="m9637 2800h-53"/><path d="m9552 2800h-53"/><path d="m9467 2800h-53"/><path d="m9381 2800h-53"/><path d="m9296 2800h-53"/><path d="m9210 2800h-53"/><path d="m9125 2800h-53"/><path d="m9039 2800h-53"/><path d="m8954 2800h-53"/><path d="m8869 2800h-53"/><path d="m8783 2800h-53"/><path d="m8698 2800h-53"/><path d="m8612 2800h-53"/><path d="m8527 2800h-53"/><path d="m8441 2800h-53"/><path d="m8356 2800h-53"/><path d="m8271 2800h-54"/><path d="m8185 2800h-53"/><path d="m8100 2800h-53"/><path d="m8014 2800h-53"/><path d="m7929 2800h-53"/><path d="m7843 2800h-53"/><path d="m7758 2800h-53"/><path d="m7673 2800h-54"/><path d="m7587 2800h-53"/><path d="m7502 2800h-53"/><path d="m7416 2800h-53"/><path d="m7331 2800h-53"/><path d="m7245 2800h-53"/><path d="m7160 2800h-53"/><path d="m7075 2800h-54"/><path d="m6989 2800h-53"/><path d="m6904 2800h-53"/><path d="m6818 2800h-53"/><path d="m6733 2800h-53"/><path d="m6647 2800h-53"/><path d="m6562 2800h-53"/><path d="m6477 2800h-54"/><path d="m6391 2800h-53"/><path d="m6306 2800h-53"/><path d="m6220 2800h-53"/><path d="m6135 2800h-53"/><path d="m6049 2800h-53"/><path d="m5964 2800h-53"/><path d="m5879 2800h-54"/><path d="m5793 2800h-53"/><path d="m5708 2800h-53"/><path d="m5622 2800h-53"/><path d="m5537 2800h-53"/><path d="m5451 2800h-53"/><path d="m5366 2800h-53"/><path d="m5280 2800h-53"/><path d="m5195 2800h-53"/><path d="m5110 2800h-53"/><path d="m5024 2800h-53"/><path d="m4939 2800h-53"/><path d="m4853 2800h-53"/><path d="m4768 2800h-53"/><path d="m4682 2800h-53"/><path d="m4597 2800h-53"/><path d="m4512 2800h-53"/><path d="m4426 2800h-53"/><path d="m4341 2800h-53"/><path d="m4255 2800h-53"/><path d="m4170 2800h-53"/><path d="m4084 2800h-53"/><path d="m3999 2800h-53"/><path d="m3914 2800h-54"/><path d="m3828 2800h-53"/><path d="m3743 2800h-53"/><path d="m3657 2800h-53"/><path d="m3572 2800h-53"/><path d="m3486 2800h-53"/><path d="m3401 2800h-53"/><path d="m3316 2800h-54"/><path d="m3230 2800h-53"/><path d="m3145 2800h-53"/><path d="m3059 2800h-53"/></g></g><g transform="translate(-2197.3 -2186)"><rect height="1100.7" width="1213.6" y="6917.1" x="23255" fill="#f3e777"/><path fill="#ca4677" d="m22802 7700.4v-405.46l150.7-169.16c82.886-93.039 170.53-186.62 194.77-207.96l44.069-38.798 783.23-0.086 783.23-0.086v613.5 613.5h-978-978v-405.46zm1027.7 136.98v-78.372l-169.91 4.925-169.91 4.9249-5.09 45.854c-8.249 74.303 46.711 101.04 207.69 101.04h137.21v-78.372zm235.86-262.94 4.495-341.31 207.2-8.6408 207.2-8.6408 5.144-46.443c9.596-86.615-41.863-102.05-322.02-96.607l-246.71 4.7956-4.438 419.08-4.439 419.08h74.537 74.538l4.494-341.31zm391.3 313.72c26.41-19.286 36.255-41.399 32.697-73.447l-5.09-45.854h-174.05-174.05l-5.38 48.984c-9.97 90.771 0.993 97.91 150.36 97.91 99.305 0 148.27-7.6982 175.52-27.594zm-627.16-274.84v-77.768h-174.05-174.05v66.246c0 36.436 4.973 71.431 11.051 77.768 6.078 6.3366 84.401 11.521 174.05 11.521h163v-77.768zm659.89-4.9154 5.125-74.042-179.18 4.9155-179.18 4.9155-5.38 48.984c-10.473 95.348-2.259 99.57 183.28 94.197l170.2-4.9284 5.125-74.042zm-659.89-237.63v-78.372l-169.91 4.925-169.91 4.925-5.097 73.447-5.097 73.447h175 175v-78.372zm659.86 4.925-5.097-73.447h-174.05-174.05l-5.38 48.984c-10.289 93.673-2.146 97.91 188.15 97.91h175.52l-5.097-73.447zm-659.86-228.98v-77.768h-137.21c-97.358 0-147.91 7.8138-174.05 26.902-34.952 25.523-49.645 92.242-25.79 117.11 6.078 6.3366 84.401 11.521 174.05 11.521h163v-77.768z"/></g><g transform="matrix(.84874 0 0 .76147 2408.1 3615.3)"><rect height="3076.2" width="2734.3" y="13264" x="19249" fill="#6076b3"/><g stroke-linejoin="round" fill-rule="evenodd" stroke-width="28.222" fill="#e0ee2c"><rect y="13369" width="356.65" x="18937" height="180.95"/><rect y="13708" width="356.65" x="18937" height="180.95"/><rect y="14048" width="356.65" x="18937" height="180.95"/><rect y="14387" width="356.65" x="18937" height="180.95"/><rect y="14726" width="356.65" x="18937" height="180.95"/><rect y="15066" width="356.65" x="18937" height="180.95"/><rect y="15405" width="356.65" x="18937" height="180.95"/><rect y="15744" width="356.65" x="18937" height="180.95"/><rect y="16083" width="356.65" x="18937" height="180.95"/><rect y="13324" width="356.65" x="21939" height="180.95"/><rect y="13663" width="356.65" x="21939" height="180.95"/><rect y="14002" width="356.65" x="21939" height="180.95"/><rect y="14342" width="356.65" x="21939" height="180.95"/><rect y="14681" width="356.65" x="21939" height="180.95"/><rect y="15020" width="356.65" x="21939" height="180.95"/><rect y="15360" width="356.65" x="21939" height="180.95"/><rect y="15699" width="356.65" x="21939" height="180.95"/><rect y="16038" width="356.65" x="21939" height="180.95"/></g><g stroke-linejoin="round" fill-rule="evenodd" transform="matrix(.98702 0 0 .90336 -2675 7020.8)" class="com.sun.star.drawing.TextShape" stroke-width="28.222"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"/></text>
-<text style="word-spacing:0px;letter-spacing:0px" xml:space="preserve" font-size="1128.9px" y="9042.0264" x="22439.668" font-family="Sans" line-height="125%" fill="#000000"><tspan y="9042.0264" x="22439.668">CPU</tspan></text>
-</g></g><g stroke-linejoin="round" fill-rule="evenodd" transform="translate(-11752 543.6)" class="com.sun.star.drawing.TextShape" stroke-width="28.222"><text class="TextShape"><tspan font-size="706px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15832" x="24341" class="TextPosition" transform="matrix(0,-1,1,0,8509,40173)"><tspan fill="#000000">PCI, USB, SPI, I2C, ...</tspan></tspan></tspan></text>
-</g><g stroke-linejoin="round" fill-rule="evenodd" transform="translate(-655.31 963.83)" class="com.sun.star.drawing.RectangleShape" stroke-width="28.222"><g transform="matrix(.49166 0 0 1.0059 6045.6 -82.24)"><path fill="#cfe7f5" d="m14169 14572h-2268v-1412h4536v1412h-2268z"/><path fill="none" d="m14169 14572h-2268v-1412h4536v1412h-2268z" stroke="#3465af"/></g><text y="-395.11282" x="-790.22229" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="13686.9" x="12091.779" class="TextPosition"><tspan fill="#000000">Bridge</tspan></tspan></tspan></text>
-<text y="338.66486" x="-846.66675" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14420.677" x="12035.335" class="TextPosition"><tspan fill="#000000"> DMA</tspan></tspan></tspan></text>
-</g></svg>
diff --git a/Documentation/DocBook/media/v4l/.gitignore b/Documentation/DocBook/media/v4l/.gitignore
deleted file mode 100644
index d7ec32eafac9..000000000000
--- a/Documentation/DocBook/media/v4l/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-!*.xml
diff --git a/Documentation/DocBook/media/v4l/biblio.xml b/Documentation/DocBook/media/v4l/biblio.xml
deleted file mode 100644
index 87f1d24958aa..000000000000
--- a/Documentation/DocBook/media/v4l/biblio.xml
+++ /dev/null
@@ -1,381 +0,0 @@
- <bibliography>
- <title>References</title>
-
- <biblioentry id="cea608">
- <abbrev>CEA&nbsp;608-E</abbrev>
- <authorgroup>
- <corpauthor>Consumer Electronics Association (<ulink
-url="http://www.ce.org">http://www.ce.org</ulink>)</corpauthor>
- </authorgroup>
- <title>CEA-608-E R-2014 "Line 21 Data Services"</title>
- </biblioentry>
-
- <biblioentry id="en300294">
- <abbrev>EN&nbsp;300&nbsp;294</abbrev>
- <authorgroup>
- <corpauthor>European Telecommunication Standards Institute
-(<ulink url="http://www.etsi.org">http://www.etsi.org</ulink>)</corpauthor>
- </authorgroup>
- <title>EN 300 294 "625-line television Wide Screen Signalling
-(WSS)"</title>
- </biblioentry>
-
- <biblioentry id="ets300231">
- <abbrev>ETS&nbsp;300&nbsp;231</abbrev>
- <authorgroup>
- <corpauthor>European Telecommunication Standards Institute
-(<ulink
-url="http://www.etsi.org">http://www.etsi.org</ulink>)</corpauthor>
- </authorgroup>
- <title>ETS 300 231 "Specification of the domestic video
-Programme Delivery Control system (PDC)"</title>
- </biblioentry>
-
- <biblioentry id="ets300706">
- <abbrev>ETS&nbsp;300&nbsp;706</abbrev>
- <authorgroup>
- <corpauthor>European Telecommunication Standards Institute
-(<ulink url="http://www.etsi.org">http://www.etsi.org</ulink>)</corpauthor>
- </authorgroup>
- <title>ETS 300 706 "Enhanced Teletext specification"</title>
- </biblioentry>
-
- <biblioentry id="mpeg2part1">
- <abbrev>ISO&nbsp;13818-1</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>), International
-Organisation for Standardisation (<ulink
-url="http://www.iso.ch">http://www.iso.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-T Rec. H.222.0 | ISO/IEC 13818-1 "Information
-technology &mdash; Generic coding of moving pictures and associated
-audio information: Systems"</title>
- </biblioentry>
-
- <biblioentry id="mpeg2part2">
- <abbrev>ISO&nbsp;13818-2</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>), International
-Organisation for Standardisation (<ulink
-url="http://www.iso.ch">http://www.iso.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-T Rec. H.262 | ISO/IEC 13818-2 "Information
-technology &mdash; Generic coding of moving pictures and associated
-audio information: Video"</title>
- </biblioentry>
-
- <biblioentry id="itu470">
- <abbrev>ITU&nbsp;BT.470</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.470-6 "Conventional Television
-Systems"</title>
- </biblioentry>
-
- <biblioentry id="itu601">
- <abbrev>ITU&nbsp;BT.601</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.601-5 "Studio Encoding Parameters
-of Digital Television for Standard 4:3 and Wide-Screen 16:9 Aspect
-Ratios"</title>
- </biblioentry>
-
- <biblioentry id="itu653">
- <abbrev>ITU&nbsp;BT.653</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.653-3 "Teletext systems"</title>
- </biblioentry>
-
- <biblioentry id="itu709">
- <abbrev>ITU&nbsp;BT.709</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.709-5 "Parameter values for the
-HDTV standards for production and international programme
-exchange"</title>
- </biblioentry>
-
- <biblioentry id="itu1119">
- <abbrev>ITU&nbsp;BT.1119</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.1119 "625-line
-television Wide Screen Signalling (WSS)"</title>
- </biblioentry>
-
- <biblioentry id="jfif">
- <abbrev>JFIF</abbrev>
- <authorgroup>
- <corpauthor>Independent JPEG Group (<ulink
-url="http://www.ijg.org">http://www.ijg.org</ulink>)</corpauthor>
- </authorgroup>
- <title>JPEG File Interchange Format</title>
- <subtitle>Version 1.02</subtitle>
- </biblioentry>
-
- <biblioentry id="itu-t81">
- <abbrev>ITU-T.81</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union
-(<ulink url="http://www.itu.int">http://www.itu.int</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-T Recommendation T.81
-"Information Technology &mdash; Digital Compression and Coding of Continous-Tone
-Still Images &mdash; Requirements and Guidelines"</title>
- </biblioentry>
-
- <biblioentry id="w3c-jpeg-jfif">
- <abbrev>W3C JPEG JFIF</abbrev>
- <authorgroup>
- <corpauthor>The World Wide Web Consortium (<ulink
-url="http://www.w3.org/Graphics/JPEG">http://www.w3.org</ulink>)</corpauthor>
- </authorgroup>
- <title>JPEG JFIF</title>
- </biblioentry>
-
- <biblioentry id="smpte12m">
- <abbrev>SMPTE&nbsp;12M</abbrev>
- <authorgroup>
- <corpauthor>Society of Motion Picture and Television Engineers
-(<ulink url="http://www.smpte.org">http://www.smpte.org</ulink>)</corpauthor>
- </authorgroup>
- <title>SMPTE 12M-1999 "Television, Audio and Film - Time and
-Control Code"</title>
- </biblioentry>
-
- <biblioentry id="smpte170m">
- <abbrev>SMPTE&nbsp;170M</abbrev>
- <authorgroup>
- <corpauthor>Society of Motion Picture and Television Engineers
-(<ulink url="http://www.smpte.org">http://www.smpte.org</ulink>)</corpauthor>
- </authorgroup>
- <title>SMPTE 170M-1999 "Television - Composite Analog Video
-Signal - NTSC for Studio Applications"</title>
- </biblioentry>
-
- <biblioentry id="smpte240m">
- <abbrev>SMPTE&nbsp;240M</abbrev>
- <authorgroup>
- <corpauthor>Society of Motion Picture and Television Engineers
-(<ulink url="http://www.smpte.org">http://www.smpte.org</ulink>)</corpauthor>
- </authorgroup>
- <title>SMPTE 240M-1999 "Television - Signal Parameters -
-1125-Line High-Definition Production"</title>
- </biblioentry>
-
- <biblioentry id="smpte431">
- <abbrev>SMPTE&nbsp;RP&nbsp;431-2</abbrev>
- <authorgroup>
- <corpauthor>Society of Motion Picture and Television Engineers
-(<ulink url="http://www.smpte.org">http://www.smpte.org</ulink>)</corpauthor>
- </authorgroup>
- <title>SMPTE RP 431-2:2011 "D-Cinema Quality - Reference Projector and Environment"</title>
- </biblioentry>
-
- <biblioentry id="smpte2084">
- <abbrev>SMPTE&nbsp;ST&nbsp;2084</abbrev>
- <authorgroup>
- <corpauthor>Society of Motion Picture and Television Engineers
-(<ulink url="http://www.smpte.org">http://www.smpte.org</ulink>)</corpauthor>
- </authorgroup>
- <title>SMPTE ST 2084:2014 "High Dynamic Range Electro-Optical Transfer Function of Master Reference Displays"</title>
- </biblioentry>
-
- <biblioentry id="srgb">
- <abbrev>sRGB</abbrev>
- <authorgroup>
- <corpauthor>International Electrotechnical Commission
-(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>IEC 61966-2-1 ed1.0 "Multimedia systems and equipment - Colour measurement
-and management - Part 2-1: Colour management - Default RGB colour space - sRGB"</title>
- </biblioentry>
-
- <biblioentry id="sycc">
- <abbrev>sYCC</abbrev>
- <authorgroup>
- <corpauthor>International Electrotechnical Commission
-(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>IEC 61966-2-1-am1 ed1.0 "Amendment 1 - Multimedia systems and equipment - Colour measurement
-and management - Part 2-1: Colour management - Default RGB colour space - sRGB"</title>
- </biblioentry>
-
- <biblioentry id="xvycc">
- <abbrev>xvYCC</abbrev>
- <authorgroup>
- <corpauthor>International Electrotechnical Commission
-(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>IEC 61966-2-4 ed1.0 "Multimedia systems and equipment - Colour measurement
-and management - Part 2-4: Colour management - Extended-gamut YCC colour space for video
-applications - xvYCC"</title>
- </biblioentry>
-
- <biblioentry id="adobergb">
- <abbrev>AdobeRGB</abbrev>
- <authorgroup>
- <corpauthor>Adobe Systems Incorporated (<ulink url="http://www.adobe.com">http://www.adobe.com</ulink>)</corpauthor>
- </authorgroup>
- <title>Adobe&copy; RGB (1998) Color Image Encoding Version 2005-05</title>
- </biblioentry>
-
- <biblioentry id="oprgb">
- <abbrev>opRGB</abbrev>
- <authorgroup>
- <corpauthor>International Electrotechnical Commission
-(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>IEC 61966-2-5 "Multimedia systems and equipment - Colour measurement
-and management - Part 2-5: Colour management - Optional RGB colour space - opRGB"</title>
- </biblioentry>
-
- <biblioentry id="itu2020">
- <abbrev>ITU&nbsp;BT.2020</abbrev>
- <authorgroup>
- <corpauthor>International Telecommunication Union (<ulink
-url="http://www.itu.ch">http://www.itu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>ITU-R Recommendation BT.2020 (08/2012) "Parameter values for ultra-high
-definition television systems for production and international programme exchange"
-</title>
- </biblioentry>
-
- <biblioentry id="tech3213">
- <abbrev>EBU&nbsp;Tech&nbsp;3213</abbrev>
- <authorgroup>
- <corpauthor>European Broadcast Union (<ulink
-url="http://www.ebu.ch">http://www.ebu.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>E.B.U. Standard for Chromaticity Tolerances for Studio Monitors"</title>
- </biblioentry>
-
- <biblioentry id="iec62106">
- <abbrev>IEC&nbsp;62106</abbrev>
- <authorgroup>
- <corpauthor>International Electrotechnical Commission
-(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
- </authorgroup>
- <title>Specification of the radio data system (RDS) for VHF/FM sound broadcasting
-in the frequency range from 87,5 to 108,0 MHz</title>
- </biblioentry>
-
- <biblioentry id="nrsc4">
- <abbrev>NRSC-4-B</abbrev>
- <authorgroup>
- <corpauthor>National Radio Systems Committee
-(<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
- </authorgroup>
- <title>NRSC-4-B: United States RBDS Standard</title>
- </biblioentry>
-
- <biblioentry id="iso12232">
- <abbrev>ISO&nbsp;12232:2006</abbrev>
- <authorgroup>
- <corpauthor>International Organization for Standardization
-(<ulink url="http://www.iso.org">http://www.iso.org</ulink>)</corpauthor>
- </authorgroup>
- <title>Photography &mdash; Digital still cameras &mdash; Determination
- of exposure index, ISO speed ratings, standard output sensitivity, and
- recommended exposure index</title>
- </biblioentry>
-
- <biblioentry id="cea861">
- <abbrev>CEA-861-E</abbrev>
- <authorgroup>
- <corpauthor>Consumer Electronics Association
-(<ulink url="http://www.ce.org">http://www.ce.org</ulink>)</corpauthor>
- </authorgroup>
- <title>A DTV Profile for Uncompressed High Speed Digital Interfaces</title>
- </biblioentry>
-
- <biblioentry id="vesadmt">
- <abbrev>VESA&nbsp;DMT</abbrev>
- <authorgroup>
- <corpauthor>Video Electronics Standards Association
-(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
- </authorgroup>
- <title>VESA and Industry Standards and Guidelines for Computer Display Monitor Timing (DMT)</title>
- </biblioentry>
-
- <biblioentry id="vesaedid">
- <abbrev>EDID</abbrev>
- <authorgroup>
- <corpauthor>Video Electronics Standards Association
-(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
- </authorgroup>
- <title>VESA Enhanced Extended Display Identification Data Standard</title>
- <subtitle>Release A, Revision 2</subtitle>
- </biblioentry>
-
- <biblioentry id="hdcp">
- <abbrev>HDCP</abbrev>
- <authorgroup>
- <corpauthor>Digital Content Protection LLC
-(<ulink url="http://www.digital-cp.com">http://www.digital-cp.com</ulink>)</corpauthor>
- </authorgroup>
- <title>High-bandwidth Digital Content Protection System</title>
- <subtitle>Revision 1.3</subtitle>
- </biblioentry>
-
- <biblioentry id="hdmi">
- <abbrev>HDMI</abbrev>
- <authorgroup>
- <corpauthor>HDMI Licensing LLC
-(<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor>
- </authorgroup>
- <title>High-Definition Multimedia Interface</title>
- <subtitle>Specification Version 1.4a</subtitle>
- </biblioentry>
-
- <biblioentry id="hdmi2">
- <abbrev>HDMI2</abbrev>
- <authorgroup>
- <corpauthor>HDMI Licensing LLC
-(<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor>
- </authorgroup>
- <title>High-Definition Multimedia Interface</title>
- <subtitle>Specification Version 2.0</subtitle>
- </biblioentry>
-
- <biblioentry id="dp">
- <abbrev>DP</abbrev>
- <authorgroup>
- <corpauthor>Video Electronics Standards Association
-(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
- </authorgroup>
- <title>VESA DisplayPort Standard</title>
- <subtitle>Version 1, Revision 2</subtitle>
- </biblioentry>
-
- <biblioentry id="poynton">
- <abbrev>poynton</abbrev>
- <authorgroup>
- <corpauthor>Charles Poynton</corpauthor>
- </authorgroup>
- <title>Digital Video and HDTV, Algorithms and Interfaces</title>
- </biblioentry>
-
- <biblioentry id="colimg">
- <abbrev>colimg</abbrev>
- <authorgroup>
- <corpauthor>Erik Reinhard et al.</corpauthor>
- </authorgroup>
- <title>Color Imaging: Fundamentals and Applications</title>
- </biblioentry>
-
- </bibliography>
diff --git a/Documentation/DocBook/media/v4l/capture.c.xml b/Documentation/DocBook/media/v4l/capture.c.xml
deleted file mode 100644
index 22126a991b34..000000000000
--- a/Documentation/DocBook/media/v4l/capture.c.xml
+++ /dev/null
@@ -1,659 +0,0 @@
-<programlisting>
-/*
- * V4L2 video capture example
- *
- * This program can be used and distributed without restrictions.
- *
- * This program is provided with the V4L2 API
- * see https://linuxtv.org/docs.php for more information
- */
-
-#include &lt;stdio.h&gt;
-#include &lt;stdlib.h&gt;
-#include &lt;string.h&gt;
-#include &lt;assert.h&gt;
-
-#include &lt;getopt.h&gt; /* getopt_long() */
-
-#include &lt;fcntl.h&gt; /* low-level i/o */
-#include &lt;unistd.h&gt;
-#include &lt;errno.h&gt;
-#include &lt;sys/stat.h&gt;
-#include &lt;sys/types.h&gt;
-#include &lt;sys/time.h&gt;
-#include &lt;sys/mman.h&gt;
-#include &lt;sys/ioctl.h&gt;
-
-#include &lt;linux/videodev2.h&gt;
-
-#define CLEAR(x) memset(&amp;(x), 0, sizeof(x))
-
-enum io_method {
- IO_METHOD_READ,
- IO_METHOD_MMAP,
- IO_METHOD_USERPTR,
-};
-
-struct buffer {
- void *start;
- size_t length;
-};
-
-static char *dev_name;
-static enum io_method io = IO_METHOD_MMAP;
-static int fd = -1;
-struct buffer *buffers;
-static unsigned int n_buffers;
-static int out_buf;
-static int force_format;
-static int frame_count = 70;
-
-static void errno_exit(const char *s)
-{
- fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
- exit(EXIT_FAILURE);
-}
-
-static int xioctl(int fh, int request, void *arg)
-{
- int r;
-
- do {
- r = ioctl(fh, request, arg);
- } while (-1 == r &amp;&amp; EINTR == errno);
-
- return r;
-}
-
-static void process_image(const void *p, int size)
-{
- if (out_buf)
- fwrite(p, size, 1, stdout);
-
- fflush(stderr);
- fprintf(stderr, ".");
- fflush(stdout);
-}
-
-static int read_frame(void)
-{
- struct <link linkend="v4l2-buffer">v4l2_buffer</link> buf;
- unsigned int i;
-
- switch (io) {
- case IO_METHOD_READ:
- if (-1 == read(fd, buffers[0].start, buffers[0].length)) {
- switch (errno) {
- case EAGAIN:
- return 0;
-
- case EIO:
- /* Could ignore EIO, see spec. */
-
- /* fall through */
-
- default:
- errno_exit("read");
- }
- }
-
- process_image(buffers[0].start, buffers[0].length);
- break;
-
- case IO_METHOD_MMAP:
- CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
-
- if (-1 == xioctl(fd, VIDIOC_DQBUF, &amp;buf)) {
- switch (errno) {
- case EAGAIN:
- return 0;
-
- case EIO:
- /* Could ignore EIO, see spec. */
-
- /* fall through */
-
- default:
- errno_exit("VIDIOC_DQBUF");
- }
- }
-
- assert(buf.index &lt; n_buffers);
-
- process_image(buffers[buf.index].start, buf.bytesused);
-
- if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))
- errno_exit("VIDIOC_QBUF");
- break;
-
- case IO_METHOD_USERPTR:
- CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_USERPTR;
-
- if (-1 == xioctl(fd, VIDIOC_DQBUF, &amp;buf)) {
- switch (errno) {
- case EAGAIN:
- return 0;
-
- case EIO:
- /* Could ignore EIO, see spec. */
-
- /* fall through */
-
- default:
- errno_exit("VIDIOC_DQBUF");
- }
- }
-
- for (i = 0; i &lt; n_buffers; ++i)
- if (buf.m.userptr == (unsigned long)buffers[i].start
- &amp;&amp; buf.length == buffers[i].length)
- break;
-
- assert(i &lt; n_buffers);
-
- process_image((void *)buf.m.userptr, buf.bytesused);
-
- if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))
- errno_exit("VIDIOC_QBUF");
- break;
- }
-
- return 1;
-}
-
-static void mainloop(void)
-{
- unsigned int count;
-
- count = frame_count;
-
- while (count-- &gt; 0) {
- for (;;) {
- fd_set fds;
- struct timeval tv;
- int r;
-
- FD_ZERO(&amp;fds);
- FD_SET(fd, &amp;fds);
-
- /* Timeout. */
- tv.tv_sec = 2;
- tv.tv_usec = 0;
-
- r = select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);
-
- if (-1 == r) {
- if (EINTR == errno)
- continue;
- errno_exit("select");
- }
-
- if (0 == r) {
- fprintf(stderr, "select timeout\n");
- exit(EXIT_FAILURE);
- }
-
- if (read_frame())
- break;
- /* EAGAIN - continue select loop. */
- }
- }
-}
-
-static void stop_capturing(void)
-{
- enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-
- switch (io) {
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
-
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &amp;type))
- errno_exit("VIDIOC_STREAMOFF");
- break;
- }
-}
-
-static void start_capturing(void)
-{
- unsigned int i;
- enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-
- switch (io) {
- case IO_METHOD_READ:
- /* Nothing to do. */
- break;
-
- case IO_METHOD_MMAP:
- for (i = 0; i &lt; n_buffers; ++i) {
- struct <link linkend="v4l2-buffer">v4l2_buffer</link> buf;
-
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
-
- if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))
- errno_exit("VIDIOC_QBUF");
- }
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;type))
- errno_exit("VIDIOC_STREAMON");
- break;
-
- case IO_METHOD_USERPTR:
- for (i = 0; i &lt; n_buffers; ++i) {
- struct <link linkend="v4l2-buffer">v4l2_buffer</link> buf;
-
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_USERPTR;
- buf.index = i;
- buf.m.userptr = (unsigned long)buffers[i].start;
- buf.length = buffers[i].length;
-
- if (-1 == xioctl(fd, VIDIOC_QBUF, &amp;buf))
- errno_exit("VIDIOC_QBUF");
- }
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (-1 == xioctl(fd, VIDIOC_STREAMON, &amp;type))
- errno_exit("VIDIOC_STREAMON");
- break;
- }
-}
-
-static void uninit_device(void)
-{
- unsigned int i;
-
- switch (io) {
- case IO_METHOD_READ:
- free(buffers[0].start);
- break;
-
- case IO_METHOD_MMAP:
- for (i = 0; i &lt; n_buffers; ++i)
- if (-1 == munmap(buffers[i].start, buffers[i].length))
- errno_exit("munmap");
- break;
-
- case IO_METHOD_USERPTR:
- for (i = 0; i &lt; n_buffers; ++i)
- free(buffers[i].start);
- break;
- }
-
- free(buffers);
-}
-
-static void init_read(unsigned int buffer_size)
-{
- buffers = calloc(1, sizeof(*buffers));
-
- if (!buffers) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
-
- buffers[0].length = buffer_size;
- buffers[0].start = malloc(buffer_size);
-
- if (!buffers[0].start) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
-}
-
-static void init_mmap(void)
-{
- struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> req;
-
- CLEAR(req);
-
- req.count = 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
-
- if (-1 == xioctl(fd, VIDIOC_REQBUFS, &amp;req)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s does not support "
- "memory mapping\n", dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
-
- if (req.count &lt; 2) {
- fprintf(stderr, "Insufficient buffer memory on %s\n",
- dev_name);
- exit(EXIT_FAILURE);
- }
-
- buffers = calloc(req.count, sizeof(*buffers));
-
- if (!buffers) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
-
- for (n_buffers = 0; n_buffers &lt; req.count; ++n_buffers) {
- struct <link linkend="v4l2-buffer">v4l2_buffer</link> buf;
-
- CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = n_buffers;
-
- if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &amp;buf))
- errno_exit("VIDIOC_QUERYBUF");
-
- buffers[n_buffers].length = buf.length;
- buffers[n_buffers].start =
- mmap(NULL /* start anywhere */,
- buf.length,
- PROT_READ | PROT_WRITE /* required */,
- MAP_SHARED /* recommended */,
- fd, buf.m.offset);
-
- if (MAP_FAILED == buffers[n_buffers].start)
- errno_exit("mmap");
- }
-}
-
-static void init_userp(unsigned int buffer_size)
-{
- struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> req;
-
- CLEAR(req);
-
- req.count = 4;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_USERPTR;
-
- if (-1 == xioctl(fd, VIDIOC_REQBUFS, &amp;req)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s does not support "
- "user pointer i/o\n", dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_REQBUFS");
- }
- }
-
- buffers = calloc(4, sizeof(*buffers));
-
- if (!buffers) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
-
- for (n_buffers = 0; n_buffers &lt; 4; ++n_buffers) {
- buffers[n_buffers].length = buffer_size;
- buffers[n_buffers].start = malloc(buffer_size);
-
- if (!buffers[n_buffers].start) {
- fprintf(stderr, "Out of memory\n");
- exit(EXIT_FAILURE);
- }
- }
-}
-
-static void init_device(void)
-{
- struct <link linkend="v4l2-capability">v4l2_capability</link> cap;
- struct <link linkend="v4l2-cropcap">v4l2_cropcap</link> cropcap;
- struct <link linkend="v4l2-crop">v4l2_crop</link> crop;
- struct <link linkend="v4l2-format">v4l2_format</link> fmt;
- unsigned int min;
-
- if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &amp;cap)) {
- if (EINVAL == errno) {
- fprintf(stderr, "%s is no V4L2 device\n",
- dev_name);
- exit(EXIT_FAILURE);
- } else {
- errno_exit("VIDIOC_QUERYCAP");
- }
- }
-
- if (!(cap.capabilities &amp; V4L2_CAP_VIDEO_CAPTURE)) {
- fprintf(stderr, "%s is no video capture device\n",
- dev_name);
- exit(EXIT_FAILURE);
- }
-
- switch (io) {
- case IO_METHOD_READ:
- if (!(cap.capabilities &amp; V4L2_CAP_READWRITE)) {
- fprintf(stderr, "%s does not support read i/o\n",
- dev_name);
- exit(EXIT_FAILURE);
- }
- break;
-
- case IO_METHOD_MMAP:
- case IO_METHOD_USERPTR:
- if (!(cap.capabilities &amp; V4L2_CAP_STREAMING)) {
- fprintf(stderr, "%s does not support streaming i/o\n",
- dev_name);
- exit(EXIT_FAILURE);
- }
- break;
- }
-
-
- /* Select video input, video standard and tune here. */
-
-
- CLEAR(cropcap);
-
- cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- if (0 == xioctl(fd, VIDIOC_CROPCAP, &amp;cropcap)) {
- crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- crop.c = cropcap.defrect; /* reset to default */
-
- if (-1 == xioctl(fd, VIDIOC_S_CROP, &amp;crop)) {
- switch (errno) {
- case EINVAL:
- /* Cropping not supported. */
- break;
- default:
- /* Errors ignored. */
- break;
- }
- }
- } else {
- /* Errors ignored. */
- }
-
-
- CLEAR(fmt);
-
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (force_format) {
- fmt.fmt.pix.width = 640;
- fmt.fmt.pix.height = 480;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
-
- if (-1 == xioctl(fd, VIDIOC_S_FMT, &amp;fmt))
- errno_exit("VIDIOC_S_FMT");
-
- /* Note VIDIOC_S_FMT may change width and height. */
- } else {
- /* Preserve original settings as set by v4l2-ctl for example */
- if (-1 == xioctl(fd, VIDIOC_G_FMT, &amp;fmt))
- errno_exit("VIDIOC_G_FMT");
- }
-
- /* Buggy driver paranoia. */
- min = fmt.fmt.pix.width * 2;
- if (fmt.fmt.pix.bytesperline &lt; min)
- fmt.fmt.pix.bytesperline = min;
- min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
- if (fmt.fmt.pix.sizeimage &lt; min)
- fmt.fmt.pix.sizeimage = min;
-
- switch (io) {
- case IO_METHOD_READ:
- init_read(fmt.fmt.pix.sizeimage);
- break;
-
- case IO_METHOD_MMAP:
- init_mmap();
- break;
-
- case IO_METHOD_USERPTR:
- init_userp(fmt.fmt.pix.sizeimage);
- break;
- }
-}
-
-static void close_device(void)
-{
- if (-1 == close(fd))
- errno_exit("close");
-
- fd = -1;
-}
-
-static void open_device(void)
-{
- struct stat st;
-
- if (-1 == stat(dev_name, &amp;st)) {
- fprintf(stderr, "Cannot identify '%s': %d, %s\n",
- dev_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- if (!S_ISCHR(st.st_mode)) {
- fprintf(stderr, "%s is no device\n", dev_name);
- exit(EXIT_FAILURE);
- }
-
- fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
-
- if (-1 == fd) {
- fprintf(stderr, "Cannot open '%s': %d, %s\n",
- dev_name, errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-}
-
-static void usage(FILE *fp, int argc, char **argv)
-{
- fprintf(fp,
- "Usage: %s [options]\n\n"
- "Version 1.3\n"
- "Options:\n"
- "-d | --device name Video device name [%s]\n"
- "-h | --help Print this message\n"
- "-m | --mmap Use memory mapped buffers [default]\n"
- "-r | --read Use read() calls\n"
- "-u | --userp Use application allocated buffers\n"
- "-o | --output Outputs stream to stdout\n"
- "-f | --format Force format to 640x480 YUYV\n"
- "-c | --count Number of frames to grab [%i]\n"
- "",
- argv[0], dev_name, frame_count);
-}
-
-static const char short_options[] = "d:hmruofc:";
-
-static const struct option
-long_options[] = {
- { "device", required_argument, NULL, 'd' },
- { "help", no_argument, NULL, 'h' },
- { "mmap", no_argument, NULL, 'm' },
- { "read", no_argument, NULL, 'r' },
- { "userp", no_argument, NULL, 'u' },
- { "output", no_argument, NULL, 'o' },
- { "format", no_argument, NULL, 'f' },
- { "count", required_argument, NULL, 'c' },
- { 0, 0, 0, 0 }
-};
-
-int main(int argc, char **argv)
-{
- dev_name = "/dev/video0";
-
- for (;;) {
- int idx;
- int c;
-
- c = getopt_long(argc, argv,
- short_options, long_options, &amp;idx);
-
- if (-1 == c)
- break;
-
- switch (c) {
- case 0: /* getopt_long() flag */
- break;
-
- case 'd':
- dev_name = optarg;
- break;
-
- case 'h':
- usage(stdout, argc, argv);
- exit(EXIT_SUCCESS);
-
- case 'm':
- io = IO_METHOD_MMAP;
- break;
-
- case 'r':
- io = IO_METHOD_READ;
- break;
-
- case 'u':
- io = IO_METHOD_USERPTR;
- break;
-
- case 'o':
- out_buf++;
- break;
-
- case 'f':
- force_format++;
- break;
-
- case 'c':
- errno = 0;
- frame_count = strtol(optarg, NULL, 0);
- if (errno)
- errno_exit(optarg);
- break;
-
- default:
- usage(stderr, argc, argv);
- exit(EXIT_FAILURE);
- }
- }
-
- open_device();
- init_device();
- start_capturing();
- mainloop();
- stop_capturing();
- uninit_device();
- close_device();
- fprintf(stderr, "\n");
- return 0;
-}
-</programlisting>
diff --git a/Documentation/DocBook/media/v4l/cec-api.xml b/Documentation/DocBook/media/v4l/cec-api.xml
deleted file mode 100644
index 7062c1fa4904..000000000000
--- a/Documentation/DocBook/media/v4l/cec-api.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<partinfo>
- <authorgroup>
- <author>
- <firstname>Hans</firstname>
- <surname>Verkuil</surname>
- <affiliation><address><email>hans.verkuil@cisco.com</email></address></affiliation>
- <contrib>Initial version.</contrib>
- </author>
- </authorgroup>
- <copyright>
- <year>2016</year>
- <holder>Hans Verkuil</holder>
- </copyright>
-
- <revhistory>
- <!-- Put document revisions here, newest first. -->
- <revision>
- <revnumber>1.0.0</revnumber>
- <date>2016-03-17</date>
- <authorinitials>hv</authorinitials>
- <revremark>Initial revision</revremark>
- </revision>
- </revhistory>
-</partinfo>
-
-<title>CEC API</title>
-
-<chapter id="cec-api">
- <title>CEC: Consumer Electronics Control</title>
-
- <section id="cec-intro">
- <title>Introduction</title>
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
- <para>HDMI connectors provide a single pin for use by the Consumer Electronics
- Control protocol. This protocol allows different devices connected by an HDMI cable
- to communicate. The protocol for CEC version 1.4 is defined in supplements 1 (CEC)
- and 2 (HEAC or HDMI Ethernet and Audio Return Channel) of the HDMI 1.4a
- (<xref linkend="hdmi" />) specification and the extensions added to CEC version 2.0
- are defined in chapter 11 of the HDMI 2.0 (<xref linkend="hdmi2" />) specification.
- </para>
-
- <para>The bitrate is very slow (effectively no more than 36 bytes per second) and
- is based on the ancient AV.link protocol used in old SCART connectors. The protocol
- closely resembles a crazy Rube Goldberg contraption and is an unholy mix of low and
- high level messages. Some messages, especially those part of the HEAC protocol layered
- on top of CEC, need to be handled by the kernel, others can be handled either by the
- kernel or by userspace.</para>
-
- <para>In addition, CEC can be implemented in HDMI receivers, transmitters and in USB
- devices that have an HDMI input and an HDMI output and that control just the CEC pin.</para>
-
- <para>Drivers that support CEC will create a CEC device node (/dev/cecX)
- to give userspace access to the CEC adapter. The &CEC-ADAP-G-CAPS; ioctl will tell userspace
- what it is allowed to do.</para>
- </section>
-</chapter>
-
-<appendix id="cec-user-func">
- <title>Function Reference</title>
- <!-- Keep this alphabetically sorted. -->
- &sub-cec-func-open;
- &sub-cec-func-close;
- &sub-cec-func-ioctl;
- &sub-cec-func-poll;
- <!-- All ioctls go here. -->
- &sub-cec-ioc-adap-g-caps;
- &sub-cec-ioc-adap-g-log-addrs;
- &sub-cec-ioc-adap-g-phys-addr;
- &sub-cec-ioc-dqevent;
- &sub-cec-ioc-g-mode;
- &sub-cec-ioc-receive;
-</appendix>
diff --git a/Documentation/DocBook/media/v4l/cec-func-close.xml b/Documentation/DocBook/media/v4l/cec-func-close.xml
deleted file mode 100644
index 0812c8cd9634..000000000000
--- a/Documentation/DocBook/media/v4l/cec-func-close.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<refentry id="cec-func-close">
- <refmeta>
- <refentrytitle>cec close()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>cec-close</refname>
- <refpurpose>Close a cec device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>close</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>Closes the cec device. Resources associated with the file descriptor
- are freed. The device configuration remain unchanged.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para><function>close</function> returns 0 on success. On error, -1 is
- returned, and <varname>errno</varname> is set appropriately. Possible error
- codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid open file descriptor.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-func-ioctl.xml b/Documentation/DocBook/media/v4l/cec-func-ioctl.xml
deleted file mode 100644
index f92817a2dc80..000000000000
--- a/Documentation/DocBook/media/v4l/cec-func-ioctl.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<refentry id="cec-func-ioctl">
- <refmeta>
- <refentrytitle>cec ioctl()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>cec-ioctl</refname>
- <refpurpose>Control a cec 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>CEC ioctl request code as defined in the cec.h header file,
- for example CEC_ADAP_G_CAPS.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>Pointer to a request-specific structure.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>The <function>ioctl()</function> function manipulates cec device
- parameters. The argument <parameter>fd</parameter> must be an open file
- descriptor.</para>
- <para>The ioctl <parameter>request</parameter> code specifies the cec
- function to be called. It 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.</para>
- <para>Macros and structures definitions specifying cec ioctl requests and
- their parameters are located in the cec.h header file. All cec ioctl
- requests, their respective function and parameters are specified in
- <xref linkend="cec-user-func" />.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <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>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-func-open.xml b/Documentation/DocBook/media/v4l/cec-func-open.xml
deleted file mode 100644
index 2edc5555b81a..000000000000
--- a/Documentation/DocBook/media/v4l/cec-func-open.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<refentry id="cec-func-open">
- <refmeta>
- <refentrytitle>cec open()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>cec-open</refname>
- <refpurpose>Open a cec device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>open</function></funcdef>
- <paramdef>const char *<parameter>device_name</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>device_name</parameter></term>
- <listitem>
- <para>Device to be opened.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>Open flags. Access mode must be <constant>O_RDWR</constant>.
- </para>
- <para>When the <constant>O_NONBLOCK</constant> flag is
-given, the &CEC-RECEIVE; ioctl will return &EAGAIN; when no message is
-available, and the &CEC-TRANSMIT;, &CEC-ADAP-S-PHYS-ADDR; and
-&CEC-ADAP-S-LOG-ADDRS; ioctls all act in non-blocking mode.</para>
- <para>Other flags have no effect.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Description</title>
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>To open a cec device applications call <function>open()</function>
- with the desired device name. The function has no side effects; the device
- configuration remain unchanged.</para>
- <para>When the device is opened in read-only mode, attempts to modify its
- configuration will result in an error, and <varname>errno</varname> will be
- set to <errorcode>EBADF</errorcode>.</para>
- </refsect1>
- <refsect1>
- <title>Return Value</title>
-
- <para><function>open</function> returns the new file descriptor on success.
- On error, -1 is returned, and <varname>errno</varname> is set appropriately.
- Possible error codes include:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para>The requested access to the file is not allowed.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EMFILE</errorcode></term>
- <listitem>
- <para>The process already has the maximum number of files open.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENFILE</errorcode></term>
- <listitem>
- <para>The system limit on the total number of open files has been
- reached.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOMEM</errorcode></term>
- <listitem>
- <para>Insufficient kernel memory was available.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENXIO</errorcode></term>
- <listitem>
- <para>No device corresponding to this device special file exists.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-func-poll.xml b/Documentation/DocBook/media/v4l/cec-func-poll.xml
deleted file mode 100644
index 1bddbde0142d..000000000000
--- a/Documentation/DocBook/media/v4l/cec-func-poll.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<refentry id="cec-func-poll">
- <refmeta>
- <refentrytitle>cec poll()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>cec-poll</refname>
- <refpurpose>Wait for some event on a file descriptor</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;sys/poll.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>poll</function></funcdef>
- <paramdef>struct pollfd *<parameter>ufds</parameter></paramdef>
- <paramdef>unsigned int <parameter>nfds</parameter></paramdef>
- <paramdef>int <parameter>timeout</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>With the <function>poll()</function> function applications
-can wait for CEC events.</para>
-
- <para>On success <function>poll()</function> returns the number of
-file descriptors that have been selected (that is, file descriptors
-for which the <structfield>revents</structfield> field of the
-respective <structname>pollfd</structname> structure is non-zero).
-CEC devices set the <constant>POLLIN</constant> and
-<constant>POLLRDNORM</constant> flags in the
-<structfield>revents</structfield> field if there are messages in the
-receive queue. If the transmit queue has room for new messages, the
-<constant>POLLOUT</constant> and <constant>POLLWRNORM</constant>
-flags are set. If there are events in the event queue, then the
-<constant>POLLPRI</constant> flag is set.
-When the function timed out it returns a value of zero, on
-failure it returns <returnvalue>-1</returnvalue> and the
-<varname>errno</varname> variable is set appropriately.
-</para>
-
- <para>For more details see the
-<function>poll()</function> manual page.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, <function>poll()</function> returns the number
-structures which have non-zero <structfield>revents</structfield>
-fields, or zero if the call timed out. On error
-<returnvalue>-1</returnvalue> is returned, and the
-<varname>errno</varname> variable is set appropriately:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para>One or more of the <parameter>ufds</parameter> members
-specify an invalid file descriptor.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EFAULT</errorcode></term>
- <listitem>
- <para><parameter>ufds</parameter> references an inaccessible
-memory area.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINTR</errorcode></term>
- <listitem>
- <para>The call was interrupted by a signal.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <parameter>nfds</parameter> argument is greater
-than <constant>OPEN_MAX</constant>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml b/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
deleted file mode 100644
index 3523ef2259b1..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-caps.xml
+++ /dev/null
@@ -1,151 +0,0 @@
-<refentry id="cec-ioc-adap-g-caps">
- <refmeta>
- <refentrytitle>ioctl CEC_ADAP_G_CAPS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_ADAP_G_CAPS</refname>
- <refpurpose>Query device capabilities</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 cec_caps *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_ADAP_G_CAPS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>All cec devices must support the <constant>CEC_ADAP_G_CAPS</constant>
- ioctl. To query device information, applications call the ioctl with a
- pointer to a &cec-caps;. The driver fills the structure and returns
- the information to the application.
- The ioctl never fails.</para>
-
- <table pgwide="1" frame="none" id="cec-caps">
- <title>struct <structname>cec_caps</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>char</entry>
- <entry><structfield>driver[32]</structfield></entry>
- <entry>The name of the cec adapter driver.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>name[32]</structfield></entry>
- <entry>The name of this CEC adapter. The combination <structfield>driver</structfield>
- and <structfield>name</structfield> must be unique.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capabilities</structfield></entry>
- <entry>The capabilities of the CEC adapter, see <xref
- linkend="cec-capabilities" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>version</structfield></entry>
- <entry>CEC Framework API version, formatted with the
- <constant>KERNEL_VERSION()</constant> macro.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-capabilities">
- <title>CEC Capabilities Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_CAP_PHYS_ADDR</constant></entry>
- <entry>0x00000001</entry>
- <entry>Userspace has to configure the physical address by
- calling &CEC-ADAP-S-PHYS-ADDR;. If this capability isn't set,
- then setting the physical address is handled by the kernel
- whenever the EDID is set (for an HDMI receiver) or read (for
- an HDMI transmitter).</entry>
- </row>
- <row>
- <entry><constant>CEC_CAP_LOG_ADDRS</constant></entry>
- <entry>0x00000002</entry>
- <entry>Userspace has to configure the logical addresses by
- calling &CEC-ADAP-S-LOG-ADDRS;. If this capability isn't set,
- then the kernel will have configured this.</entry>
- </row>
- <row>
- <entry><constant>CEC_CAP_TRANSMIT</constant></entry>
- <entry>0x00000004</entry>
- <entry>Userspace can transmit CEC messages by calling &CEC-TRANSMIT;. This
- implies that userspace can be a follower as well, since being able to
- transmit messages is a prerequisite of becoming a follower. If this
- capability isn't set, then the kernel will handle all CEC transmits
- and process all CEC messages it receives.
- </entry>
- </row>
- <row>
- <entry><constant>CEC_CAP_PASSTHROUGH</constant></entry>
- <entry>0x00000008</entry>
- <entry>Userspace can use the passthrough mode by
- calling &CEC-S-MODE;.</entry>
- </row>
- <row>
- <entry><constant>CEC_CAP_RC</constant></entry>
- <entry>0x00000010</entry>
- <entry>This adapter supports the remote control protocol.</entry>
- </row>
- <row>
- <entry><constant>CEC_CAP_MONITOR_ALL</constant></entry>
- <entry>0x00000020</entry>
- <entry>The CEC hardware can monitor all messages, not just directed and
- broadcast messages.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml b/Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml
deleted file mode 100644
index 302b8294f7fc..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-log-addrs.xml
+++ /dev/null
@@ -1,329 +0,0 @@
-<refentry id="cec-ioc-adap-g-log-addrs">
- <refmeta>
- <refentrytitle>ioctl CEC_ADAP_G_LOG_ADDRS, CEC_ADAP_S_LOG_ADDRS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_ADAP_G_LOG_ADDRS</refname>
- <refname>CEC_ADAP_S_LOG_ADDRS</refname>
- <refpurpose>Get or set the logical addresses</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 cec_log_addrs *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_ADAP_G_LOG_ADDRS, CEC_ADAP_S_LOG_ADDRS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>To query the current CEC logical addresses, applications call the
-<constant>CEC_ADAP_G_LOG_ADDRS</constant> ioctl with a pointer to a
-<structname>cec_log_addrs</structname> structure where the drivers stores the
-logical addresses.</para>
-
- <para>To set new logical addresses, applications fill in struct <structname>cec_log_addrs</structname>
-and call the <constant>CEC_ADAP_S_LOG_ADDRS</constant> ioctl with a pointer to this struct.
-The <constant>CEC_ADAP_S_LOG_ADDRS</constant> ioctl is only available if
-<constant>CEC_CAP_LOG_ADDRS</constant> is set (&ENOTTY; is returned otherwise). This ioctl will block until all
-requested logical addresses have been claimed. <constant>CEC_ADAP_S_LOG_ADDRS</constant>
-can only be called by a file handle in initiator mode (see &CEC-S-MODE;).</para>
-
- <table pgwide="1" frame="none" id="cec-log-addrs">
- <title>struct <structname>cec_log_addrs</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>log_addr</structfield>[CEC_MAX_LOG_ADDRS]</entry>
- <entry>The actual logical addresses that were claimed. This is set by the
- driver. If no logical address could be claimed, then it is set to
- <constant>CEC_LOG_ADDR_INVALID</constant>. If this adapter is Unregistered,
- then <structfield>log_addr[0]</structfield> is set to 0xf and all others to
- <constant>CEC_LOG_ADDR_INVALID</constant>.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>log_addr_mask</structfield></entry>
- <entry>The bitmask of all logical addresses this adapter has claimed.
- If this adapter is Unregistered then <structfield>log_addr_mask</structfield>
- sets bit 15 and clears all other bits. If this adapter is not configured at all, then
- <structfield>log_addr_mask</structfield> is set to 0. Set by the driver.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>cec_version</structfield></entry>
- <entry>The CEC version that this adapter shall use. See
- <xref linkend="cec-versions" />.
- Used to implement the <constant>CEC_MSG_CEC_VERSION</constant> and
- <constant>CEC_MSG_REPORT_FEATURES</constant> messages. Note that
- <constant>CEC_OP_CEC_VERSION_1_3A</constant> is not allowed
- by the CEC framework.
- </entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>num_log_addrs</structfield></entry>
- <entry>Number of logical addresses to set up. Must be &le;
- <structfield>available_log_addrs</structfield> as returned by
- &CEC-ADAP-G-CAPS;. All arrays in this structure are only filled up to
- index <structfield>available_log_addrs</structfield>-1. The remaining
- array elements will be ignored. Note that the CEC 2.0 standard allows
- for a maximum of 2 logical addresses, although some hardware has support
- for more. <constant>CEC_MAX_LOG_ADDRS</constant> is 4. The driver will
- return the actual number of logical addresses it could claim, which may
- be less than what was requested. If this field is set to 0, then the
- CEC adapter shall clear all claimed logical addresses and all other
- fields will be ignored.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>vendor_id</structfield></entry>
- <entry>The vendor ID is a 24-bit number that identifies the specific
- vendor or entity. Based on this ID vendor specific commands may be
- defined. If you do not want a vendor ID then set it to
- <constant>CEC_VENDOR_ID_NONE</constant>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags. No flags are defined yet, so set this to 0.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>osd_name</structfield>[15]</entry>
- <entry>The On-Screen Display name as is returned by the
- <constant>CEC_MSG_SET_OSD_NAME</constant> message.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>primary_device_type</structfield>[CEC_MAX_LOG_ADDRS]</entry>
- <entry>Primary device type for each logical address. See
- <xref linkend="cec-prim-dev-types" /> for possible types.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>log_addr_type</structfield>[CEC_MAX_LOG_ADDRS]</entry>
- <entry>Logical address types. See <xref linkend="cec-log-addr-types" /> for
- possible types. The driver will update this with the actual logical address
- type that it claimed (e.g. it may have to fallback to
- <constant>CEC_LOG_ADDR_TYPE_UNREGISTERED</constant>).</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>all_device_types</structfield>[CEC_MAX_LOG_ADDRS]</entry>
- <entry>CEC 2.0 specific: all device types. See <xref linkend="cec-all-dev-types-flags" />.
- Used to implement the <constant>CEC_MSG_REPORT_FEATURES</constant> message.
- This field is ignored if <structfield>cec_version</structfield> &lt;
- <constant>CEC_OP_CEC_VERSION_2_0</constant>.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>features</structfield>[CEC_MAX_LOG_ADDRS][12]</entry>
- <entry>Features for each logical address. Used to implement the
- <constant>CEC_MSG_REPORT_FEATURES</constant> message. The 12 bytes include
- both the RC Profile and the Device Features.
- This field is ignored if <structfield>cec_version</structfield> &lt;
- <constant>CEC_OP_CEC_VERSION_2_0</constant>.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-versions">
- <title>CEC Versions</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_OP_CEC_VERSION_1_3A</constant></entry>
- <entry>4</entry>
- <entry>CEC version according to the HDMI 1.3a standard.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_CEC_VERSION_1_4B</constant></entry>
- <entry>5</entry>
- <entry>CEC version according to the HDMI 1.4b standard.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_CEC_VERSION_2_0</constant></entry>
- <entry>6</entry>
- <entry>CEC version according to the HDMI 2.0 standard.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-prim-dev-types">
- <title>CEC Primary Device Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_TV</constant></entry>
- <entry>0</entry>
- <entry>Use for a TV.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_RECORD</constant></entry>
- <entry>1</entry>
- <entry>Use for a recording device.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_TUNER</constant></entry>
- <entry>3</entry>
- <entry>Use for a device with a tuner.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_PLAYBACK</constant></entry>
- <entry>4</entry>
- <entry>Use for a playback device.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM</constant></entry>
- <entry>5</entry>
- <entry>Use for an audio system (e.g. an audio/video receiver).</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_SWITCH</constant></entry>
- <entry>6</entry>
- <entry>Use for a CEC switch.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_PRIM_DEVTYPE_VIDEOPROC</constant></entry>
- <entry>7</entry>
- <entry>Use for a video processor device.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-log-addr-types">
- <title>CEC Logical Address Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_TV</constant></entry>
- <entry>0</entry>
- <entry>Use for a TV.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_RECORD</constant></entry>
- <entry>1</entry>
- <entry>Use for a recording device.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_TUNER</constant></entry>
- <entry>2</entry>
- <entry>Use for a tuner device.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_PLAYBACK</constant></entry>
- <entry>3</entry>
- <entry>Use for a playback device.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_AUDIOSYSTEM</constant></entry>
- <entry>4</entry>
- <entry>Use for an audio system device.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_SPECIFIC</constant></entry>
- <entry>5</entry>
- <entry>Use for a second TV or for a video processor device.</entry>
- </row>
- <row>
- <entry><constant>CEC_LOG_ADDR_TYPE_UNREGISTERED</constant></entry>
- <entry>6</entry>
- <entry>Use this if you just want to remain unregistered.
- Used for pure CEC switches or CDC-only devices (CDC:
- Capability Discovery and Control).</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-all-dev-types-flags">
- <title>CEC All Device Types Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_TV</constant></entry>
- <entry>0x80</entry>
- <entry>This supports the TV type.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_RECORD</constant></entry>
- <entry>0x40</entry>
- <entry>This supports the Recording type.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_TUNER</constant></entry>
- <entry>0x20</entry>
- <entry>This supports the Tuner type.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_PLAYBACK</constant></entry>
- <entry>0x10</entry>
- <entry>This supports the Playback type.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM</constant></entry>
- <entry>0x08</entry>
- <entry>This supports the Audio System type.</entry>
- </row>
- <row>
- <entry><constant>CEC_OP_ALL_DEVTYPE_SWITCH</constant></entry>
- <entry>0x04</entry>
- <entry>This supports the CEC Switch or Video Processing type.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml b/Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml
deleted file mode 100644
index d95f1785080c..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-adap-g-phys-addr.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-<refentry id="cec-ioc-adap-g-phys-addr">
- <refmeta>
- <refentrytitle>ioctl CEC_ADAP_G_PHYS_ADDR, CEC_ADAP_S_PHYS_ADDR</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_ADAP_G_PHYS_ADDR</refname>
- <refname>CEC_ADAP_S_PHYS_ADDR</refname>
- <refpurpose>Get or set the physical address</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>__u16 *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_ADAP_G_PHYS_ADDR, CEC_ADAP_S_PHYS_ADDR</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>To query the current physical address applications call the
-<constant>CEC_ADAP_G_PHYS_ADDR</constant> ioctl with a pointer to an __u16
-where the driver stores the physical address.</para>
-
- <para>To set a new physical address applications store the physical address in
-an __u16 and call the <constant>CEC_ADAP_S_PHYS_ADDR</constant> ioctl with a
-pointer to this integer. <constant>CEC_ADAP_S_PHYS_ADDR</constant> is only
-available if <constant>CEC_CAP_PHYS_ADDR</constant> is set (&ENOTTY; will be returned
-otherwise). <constant>CEC_ADAP_S_PHYS_ADDR</constant>
-can only be called by a file handle in initiator mode (see &CEC-S-MODE;), if not
-&EBUSY; will be returned.</para>
-
- <para>The physical address is a 16-bit number where each group of 4 bits
-represent a digit of the physical address a.b.c.d where the most significant
-4 bits represent 'a'. The CEC root device (usually the TV) has address 0.0.0.0.
-Every device that is hooked up to an input of the TV has address a.0.0.0 (where
-'a' is &ge; 1), devices hooked up to those in turn have addresses a.b.0.0, etc.
-So a topology of up to 5 devices deep is supported. The physical address a
-device shall use is stored in the EDID of the sink.</para>
-
-<para>For example, the EDID for each HDMI input of the TV will have a different
-physical address of the form a.0.0.0 that the sources will read out and use as
-their physical address.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml b/Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml
deleted file mode 100644
index 697dde575cd4..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-dqevent.xml
+++ /dev/null
@@ -1,202 +0,0 @@
-<refentry id="cec-ioc-g-event">
- <refmeta>
- <refentrytitle>ioctl CEC_DQEVENT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_DQEVENT</refname>
- <refpurpose>Dequeue a CEC 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 cec_event *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_DQEVENT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>CEC devices can send asynchronous events. These can be retrieved by calling
- the <constant>CEC_DQEVENT</constant> ioctl. If the file descriptor is in non-blocking
- mode and no event is pending, then it will return -1 and set errno to the &EAGAIN;.</para>
-
- <para>The internal event queues are per-filehandle and per-event type. If there is
- no more room in a queue then the last event is overwritten with the new one. This
- means that intermediate results can be thrown away but that the latest event is always
- available. This also means that is it possible to read two successive events that have
- the same value (e.g. two CEC_EVENT_STATE_CHANGE events with the same state). In that
- case the intermediate state changes were lost but it is guaranteed that the state
- did change in between the two events.</para>
-
- <table pgwide="1" frame="none" id="cec-event-state-change">
- <title>struct <structname>cec_event_state_change</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u16</entry>
- <entry><structfield>phys_addr</structfield></entry>
- <entry>The current physical address.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>log_addr_mask</structfield></entry>
- <entry>The current set of claimed logical addresses.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-event-lost-msgs">
- <title>struct <structname>cec_event_lost_msgs</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>lost_msgs</structfield></entry>
- <entry>Set to the number of lost messages since the filehandle
- was opened or since the last time this event was dequeued for
- this filehandle. The messages lost are the oldest messages. So
- when a new message arrives and there is no more room, then the
- oldest message is discarded to make room for the new one. The
- internal size of the message queue guarantees that all messages
- received in the last two seconds will be stored. Since messages
- should be replied to within a second according to the CEC
- specification, this is more than enough.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-event">
- <title>struct <structname>cec_event</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u64</entry>
- <entry><structfield>ts</structfield></entry>
- <entry>Timestamp of the event in ns.</entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>event</structfield></entry>
- <entry>The CEC event type, see <xref linkend="cec-events" />.</entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Event flags, see <xref linkend="cec-event-flags" />.</entry>
- <entry></entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct cec_event_state_change</entry>
- <entry><structfield>state_change</structfield></entry>
- <entry>The new adapter state as sent by the <constant>CEC_EVENT_STATE_CHANGE</constant>
- event.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct cec_event_lost_msgs</entry>
- <entry><structfield>lost_msgs</structfield></entry>
- <entry>The number of lost messages as sent by the <constant>CEC_EVENT_LOST_MSGS</constant>
- event.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-events">
- <title>CEC Events Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_EVENT_STATE_CHANGE</constant></entry>
- <entry>1</entry>
- <entry>Generated when the CEC Adapter's state changes. When open() is
- called an initial event will be generated for that filehandle with the
- CEC Adapter's state at that time.
- </entry>
- </row>
- <row>
- <entry><constant>CEC_EVENT_LOST_MSGS</constant></entry>
- <entry>2</entry>
- <entry>Generated if one or more CEC messages were lost because the
- application didn't dequeue CEC messages fast enough.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-event-flags">
- <title>CEC Event Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_EVENT_FL_INITIAL_VALUE</constant></entry>
- <entry>1</entry>
- <entry>Set for the initial events that are generated when the device is
- opened. See the table above for which events do this. This allows
- applications to learn the initial state of the CEC adapter at open()
- time.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml b/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
deleted file mode 100644
index 26b4282ad134..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-g-mode.xml
+++ /dev/null
@@ -1,255 +0,0 @@
-<refentry id="cec-ioc-g-mode">
- <refmeta>
- <refentrytitle>ioctl CEC_G_MODE, CEC_S_MODE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_G_MODE</refname>
- <refname>CEC_S_MODE</refname>
- <refpurpose>Get or set exclusive use of the CEC adapter</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>__u32 *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_G_MODE, CEC_S_MODE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>By default any filehandle can use &CEC-TRANSMIT; and &CEC-RECEIVE;, but
-in order to prevent applications from stepping on each others toes it must be possible
-to obtain exclusive access to the CEC adapter. This ioctl sets the filehandle
-to initiator and/or follower mode which can be exclusive depending on the chosen
-mode. The initiator is the filehandle that is used
-to initiate messages, i.e. it commands other CEC devices. The follower is the filehandle
-that receives messages sent to the CEC adapter and processes them. The same filehandle
-can be both initiator and follower, or this role can be taken by two different
-filehandles.</para>
-
- <para>When a CEC message is received, then the CEC framework will decide how
-it will be processed. If the message is a reply to an earlier transmitted message,
-then the reply is sent back to the filehandle that is waiting for it. In addition
-the CEC framework will process it.</para>
-
- <para>If the message is not a reply, then the CEC framework will process it
-first. If there is no follower, then the message is just discarded and a feature
-abort is sent back to the initiator if the framework couldn't process it. If there
-is a follower, then the message is passed on to the follower who will use
-&CEC-RECEIVE; to dequeue the new message. The framework expects the follower to
-make the right decisions.</para>
-
- <para>The CEC framework will process core messages unless requested otherwise
-by the follower. The follower can enable the passthrough mode. In that case, the
-CEC framework will pass on most core messages without processing them and
-the follower will have to implement those messages. There are some messages
-that the core will always process, regardless of the passthrough mode. See
-<xref linkend="cec-core-processing" /> for details.</para>
-
- <para>If there is no initiator, then any CEC filehandle can use &CEC-TRANSMIT;.
-If there is an exclusive initiator then only that initiator can call &CEC-TRANSMIT;.
-The follower can of course always call &CEC-TRANSMIT;.</para>
-
- <para>Available initiator modes are:</para>
-
- <table pgwide="1" frame="none" id="cec-mode-initiator">
- <title>Initiator Modes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_MODE_NO_INITIATOR</constant></entry>
- <entry>0x0</entry>
- <entry>This is not an initiator, i.e. it cannot transmit CEC messages
- or make any other changes to the CEC adapter.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_INITIATOR</constant></entry>
- <entry>0x1</entry>
- <entry>This is an initiator (the default when the device is opened) and it
- can transmit CEC messages and make changes to the CEC adapter, unless there
- is an exclusive initiator.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_EXCL_INITIATOR</constant></entry>
- <entry>0x2</entry>
- <entry>This is an exclusive initiator and this file descriptor is the only one
- that can transmit CEC messages and make changes to the CEC adapter. If someone
- else is already the exclusive initiator then an attempt to become one will return
- the &EBUSY; error.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Available follower modes are:</para>
-
- <table pgwide="1" frame="none" id="cec-mode-follower">
- <title>Follower Modes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_MODE_NO_FOLLOWER</constant></entry>
- <entry>0x00</entry>
- <entry>This is not a follower (the default when the device is opened).</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_FOLLOWER</constant></entry>
- <entry>0x10</entry>
- <entry>This is a follower and it will receive CEC messages unless there is
- an exclusive follower. You cannot become a follower if <constant>CEC_CAP_TRANSMIT</constant>
- is not set or if <constant>CEC_MODE_NO_INITIATOR</constant> was specified,
- &EINVAL; is returned in that case.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_EXCL_FOLLOWER</constant></entry>
- <entry>0x20</entry>
- <entry>This is an exclusive follower and only this file descriptor will receive
- CEC messages for processing. If someone else is already the exclusive follower
- then an attempt to become one will return the &EBUSY; error. You cannot become
- a follower if <constant>CEC_CAP_TRANSMIT</constant> is not set or if
- <constant>CEC_MODE_NO_INITIATOR</constant> was specified, &EINVAL; is returned
- in that case.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_EXCL_FOLLOWER_PASSTHRU</constant></entry>
- <entry>0x30</entry>
- <entry>This is an exclusive follower and only this file descriptor will receive
- CEC messages for processing. In addition it will put the CEC device into
- passthrough mode, allowing the exclusive follower to handle most core messages
- instead of relying on the CEC framework for that. If someone else is already the
- exclusive follower then an attempt to become one will return the &EBUSY; error.
- You cannot become a follower if <constant>CEC_CAP_TRANSMIT</constant>
- is not set or if <constant>CEC_MODE_NO_INITIATOR</constant> was specified,
- &EINVAL; is returned in that case.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_MONITOR</constant></entry>
- <entry>0xe0</entry>
- <entry>Put the file descriptor into monitor mode. Can only be used in combination
- with <constant>CEC_MODE_NO_INITIATOR</constant>, otherwise &EINVAL; will be
- returned. In monitor mode all messages this CEC device transmits and all messages
- it receives (both broadcast messages and directed messages for one its logical
- addresses) will be reported. This is very useful for debugging. This is only
- allowed if the process has the <constant>CAP_NET_ADMIN</constant>
- capability. If that is not set, then &EPERM; is returned.</entry>
- </row>
- <row>
- <entry><constant>CEC_MODE_MONITOR_ALL</constant></entry>
- <entry>0xf0</entry>
- <entry>Put the file descriptor into 'monitor all' mode. Can only be used in combination
- with <constant>CEC_MODE_NO_INITIATOR</constant>, otherwise &EINVAL; will be
- returned. In 'monitor all' mode all messages this CEC device transmits and all messages
- it receives, including directed messages for other CEC devices will be reported. This
- is very useful for debugging, but not all devices support this. This mode requires that
- the <constant>CEC_CAP_MONITOR_ALL</constant> capability is set, otherwise &EINVAL; is
- returned. This is only allowed if the process has the <constant>CAP_NET_ADMIN</constant>
- capability. If that is not set, then &EPERM; is returned.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Core message processing details:</para>
-
- <table pgwide="1" frame="none" id="cec-core-processing">
- <title>Core Message Processing</title>
- <tgroup cols="2">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_MSG_GET_CEC_VERSION</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will return the CEC version that was set with &CEC-ADAP-S-LOG-ADDRS;.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_GIVE_DEVICE_VENDOR_ID</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will return the vendor ID that was set with &CEC-ADAP-S-LOG-ADDRS;.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_ABORT</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will return a feature refused message as per the specification.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_GIVE_PHYSICAL_ADDR</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will report the current physical address.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_GIVE_OSD_NAME</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will report the current OSD name as was set with
- &CEC-ADAP-S-LOG-ADDRS;.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_GIVE_FEATURES</constant></entry>
- <entry>When in passthrough mode this message has to be handled by userspace,
- otherwise the core will report the current features as was set with
- &CEC-ADAP-S-LOG-ADDRS; or the message is ignore if the CEC version was
- older than 2.0.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_USER_CONTROL_PRESSED</constant></entry>
- <entry>If <constant>CEC_CAP_RC</constant> is set, then generate a remote control
- key press. This message is always passed on to userspace.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_USER_CONTROL_RELEASED</constant></entry>
- <entry>If <constant>CEC_CAP_RC</constant> is set, then generate a remote control
- key release. This message is always passed on to userspace.</entry>
- </row>
- <row>
- <entry><constant>CEC_MSG_REPORT_PHYSICAL_ADDR</constant></entry>
- <entry>The CEC framework will make note of the reported physical address
- and then just pass the message on to userspace.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/cec-ioc-receive.xml b/Documentation/DocBook/media/v4l/cec-ioc-receive.xml
deleted file mode 100644
index fde9f8678e67..000000000000
--- a/Documentation/DocBook/media/v4l/cec-ioc-receive.xml
+++ /dev/null
@@ -1,274 +0,0 @@
-<refentry id="cec-ioc-receive">
- <refmeta>
- <refentrytitle>ioctl CEC_RECEIVE, CEC_TRANSMIT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>CEC_RECEIVE</refname>
- <refname>CEC_TRANSMIT</refname>
- <refpurpose>Receive or transmit a CEC message</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 cec_msg *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='cec-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>CEC_RECEIVE, CEC_TRANSMIT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Note: this documents the proposed CEC API. This API is not yet finalized and
- is currently only available as a staging kernel module.
- </para>
-
- <para>To receive a CEC message the application has to fill in the
- <structname>cec_msg</structname> structure and pass it to the
- <constant>CEC_RECEIVE</constant> ioctl. <constant>CEC_RECEIVE</constant> is
- only available if <constant>CEC_CAP_RECEIVE</constant> is set. If the
- file descriptor is in non-blocking mode and there are no received
- messages pending, then it will return -1 and set errno to the &EAGAIN;.
- If the file descriptor is in blocking mode and <structfield>timeout</structfield>
- is non-zero and no message arrived within <structfield>timeout</structfield>
- milliseconds, then it will return -1 and set errno to the &ETIMEDOUT;.</para>
-
- <para>To send a CEC message the application has to fill in the
- <structname>cec_msg</structname> structure and pass it to the
- <constant>CEC_TRANSMIT</constant> ioctl. <constant>CEC_TRANSMIT</constant> is
- only available if <constant>CEC_CAP_TRANSMIT</constant> is set.
- If there is no more room in the transmit queue, then it will return
- -1 and set errno to the &EBUSY;.</para>
-
- <table pgwide="1" frame="none" id="cec-msg">
- <title>struct <structname>cec_msg</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u64</entry>
- <entry><structfield>ts</structfield></entry>
- <entry>Timestamp of when the message was transmitted in ns in the case
- of <constant>CEC_TRANSMIT</constant> with <structfield>reply</structfield>
- set to 0, or the timestamp of the received message in all other cases.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>len</structfield></entry>
- <entry>The length of the message. For <constant>CEC_TRANSMIT</constant> this
- is filled in by the application. The driver will fill this in for
- <constant>CEC_RECEIVE</constant> and for <constant>CEC_TRANSMIT</constant>
- it will be filled in with the length of the reply message if
- <structfield>reply</structfield> was set.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>timeout</structfield></entry>
- <entry>The timeout in milliseconds. This is the time the device will wait for a message to
- be received before timing out. If it is set to 0, then it will wait indefinitely when it
- is called by <constant>CEC_RECEIVE</constant>. If it is 0 and it is called by
- <constant>CEC_TRANSMIT</constant>, then it will be replaced by 1000 if the
- <structfield>reply</structfield> is non-zero or ignored if <structfield>reply</structfield>
- is 0.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sequence</structfield></entry>
- <entry>The sequence number is automatically assigned by the CEC
- framework for all transmitted messages. It can be later used by the
- framework to generate an event if a reply for a message was
- requested and the message was transmitted in a non-blocking mode.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags. No flags are defined yet, so set this to 0.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>rx_status</structfield></entry>
- <entry>The status bits of the received message. See <xref linkend="cec-rx-status" />
- for the possible status values. It is 0 if this message was transmitted, not
- received, unless this is the reply to a transmitted message. In that case both
- <structfield>rx_status</structfield> and <structfield>tx_status</structfield>
- are set.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>tx_status</structfield></entry>
- <entry>The status bits of the transmitted message. See <xref linkend="cec-tx-status" />
- for the possible status values. It is 0 if this messages was received, not
- transmitted.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>msg</structfield>[16]</entry>
- <entry>The message payload. For <constant>CEC_TRANSMIT</constant> this
- is filled in by the application. The driver will fill this in for
- <constant>CEC_RECEIVE</constant> and for <constant>CEC_TRANSMIT</constant>
- it will be filled in with the payload of the reply message if
- <structfield>reply</structfield> was set.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>reply</structfield></entry>
- <entry>Wait until this message is replied. If <structfield>reply</structfield>
- is 0 and the <structfield>timeout</structfield> is 0, then don't wait for a reply but
- return after transmitting the message. If there was an error as indicated by a non-zero
- <structfield>tx_status</structfield> field, then <structfield>reply</structfield> and
- <structfield>timeout</structfield> are both set to 0 by the driver. Ignored by
- <constant>CEC_RECEIVE</constant>. The case where <structfield>reply</structfield> is 0
- (this is the opcode for the Feature Abort message) and <structfield>timeout</structfield>
- is non-zero is specifically allowed to send a message and wait up to <structfield>timeout</structfield>
- milliseconds for a Feature Abort reply. In this case <structfield>rx_status</structfield>
- will either be set to <constant>CEC_RX_STATUS_TIMEOUT</constant> or
- <constant>CEC_RX_STATUS_FEATURE_ABORT</constant>.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>tx_arb_lost_cnt</structfield></entry>
- <entry>A counter of the number of transmit attempts that resulted in the
- Arbitration Lost error. This is only set if the hardware supports this, otherwise
- it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_ARB_LOST</constant>
- status bit is set.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>tx_nack_cnt</structfield></entry>
- <entry>A counter of the number of transmit attempts that resulted in the
- Not Acknowledged error. This is only set if the hardware supports this, otherwise
- it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_NACK</constant>
- status bit is set.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>tx_low_drive_cnt</structfield></entry>
- <entry>A counter of the number of transmit attempts that resulted in the
- Arbitration Lost error. This is only set if the hardware supports this, otherwise
- it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_LOW_DRIVE</constant>
- status bit is set.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>tx_error_cnt</structfield></entry>
- <entry>A counter of the number of transmit errors other than Arbitration Lost
- or Not Acknowledged. This is only set if the hardware supports this, otherwise
- it is always 0. This counter is only valid if the <constant>CEC_TX_STATUS_ERROR</constant>
- status bit is set.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-tx-status">
- <title>CEC Transmit Status</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_TX_STATUS_OK</constant></entry>
- <entry>0x01</entry>
- <entry>The message was transmitted successfully. This is mutually exclusive with
- <constant>CEC_TX_STATUS_MAX_RETRIES</constant>. Other bits can still be set if
- earlier attempts met with failure before the transmit was eventually successful.</entry>
- </row>
- <row>
- <entry><constant>CEC_TX_STATUS_ARB_LOST</constant></entry>
- <entry>0x02</entry>
- <entry>CEC line arbitration was lost.</entry>
- </row>
- <row>
- <entry><constant>CEC_TX_STATUS_NACK</constant></entry>
- <entry>0x04</entry>
- <entry>Message was not acknowledged.</entry>
- </row>
- <row>
- <entry><constant>CEC_TX_STATUS_LOW_DRIVE</constant></entry>
- <entry>0x08</entry>
- <entry>Low drive was detected on the CEC bus. This indicates that a follower
- detected an error on the bus and requests a retransmission.</entry>
- </row>
- <row>
- <entry><constant>CEC_TX_STATUS_ERROR</constant></entry>
- <entry>0x10</entry>
- <entry>Some error occurred. This is used for any errors that do not
- fit the previous two, either because the hardware could not tell
- which error occurred, or because the hardware tested for other conditions
- besides those two.</entry>
- </row>
- <row>
- <entry><constant>CEC_TX_STATUS_MAX_RETRIES</constant></entry>
- <entry>0x20</entry>
- <entry>The transmit failed after one or more retries. This status bit is mutually
- exclusive with <constant>CEC_TX_STATUS_OK</constant>. Other bits can still be set
- to explain which failures were seen.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="cec-rx-status">
- <title>CEC Receive Status</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>CEC_RX_STATUS_OK</constant></entry>
- <entry>0x01</entry>
- <entry>The message was received successfully.</entry>
- </row>
- <row>
- <entry><constant>CEC_RX_STATUS_TIMEOUT</constant></entry>
- <entry>0x02</entry>
- <entry>The reply to an earlier transmitted message timed out.</entry>
- </row>
- <row>
- <entry><constant>CEC_RX_STATUS_FEATURE_ABORT</constant></entry>
- <entry>0x04</entry>
- <entry>The message was received successfully but the reply was
- <constant>CEC_MSG_FEATURE_ABORT</constant>. This status is only
- set if this message was the reply to an earlier transmitted
- message.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/common.xml b/Documentation/DocBook/media/v4l/common.xml
deleted file mode 100644
index 8b5e014224d6..000000000000
--- a/Documentation/DocBook/media/v4l/common.xml
+++ /dev/null
@@ -1,1102 +0,0 @@
- <title>Common API Elements</title>
-
- <para>Programming a V4L2 device consists of these
-steps:</para>
-
- <itemizedlist>
- <listitem>
- <para>Opening the device</para>
- </listitem>
- <listitem>
- <para>Changing device properties, selecting a video and audio
-input, video standard, picture brightness a.&nbsp;o.</para>
- </listitem>
- <listitem>
- <para>Negotiating a data format</para>
- </listitem>
- <listitem>
- <para>Negotiating an input/output method</para>
- </listitem>
- <listitem>
- <para>The actual input/output loop</para>
- </listitem>
- <listitem>
- <para>Closing the device</para>
- </listitem>
- </itemizedlist>
-
- <para>In practice most steps are optional and can be executed out of
-order. It depends on the V4L2 device type, you can read about the
-details in <xref linkend="devices" />. In this chapter we will discuss
-the basic concepts applicable to all devices.</para>
-
- <section id="open">
- <title>Opening and Closing Devices</title>
-
- <section>
- <title>Device Naming</title>
-
- <para>V4L2 drivers are implemented as kernel modules, loaded
-manually by the system administrator or automatically when a device is
-first discovered. The driver modules plug into the "videodev" kernel
-module. It provides helper functions and a common application
-interface specified in this document.</para>
-
- <para>Each driver thus loaded registers one or more device nodes
-with major number 81 and a minor number between 0 and 255. Minor numbers
-are allocated dynamically unless the kernel is compiled with the kernel
-option CONFIG_VIDEO_FIXED_MINOR_RANGES. In that case minor numbers are
-allocated in ranges depending on the device node type (video, radio, etc.).</para>
-
- <para>Many drivers support "video_nr", "radio_nr" or "vbi_nr"
-module options to select specific video/radio/vbi node numbers. This allows
-the user to request that the device node is named e.g. /dev/video5 instead
-of leaving it to chance. When the driver supports multiple devices of the same
-type more than one device node number can be assigned, separated by commas:
- <informalexample>
- <screen>
-&gt; modprobe mydriver video_nr=0,1 radio_nr=0,1</screen>
- </informalexample></para>
-
- <para>In <filename>/etc/modules.conf</filename> this may be
-written as: <informalexample>
- <screen>
-options mydriver video_nr=0,1 radio_nr=0,1
- </screen>
- </informalexample> When no device node number is given as module
-option the driver supplies a default.</para>
-
- <para>Normally udev will create the device nodes in /dev automatically
-for you. If udev is not installed, then you need to enable the
-CONFIG_VIDEO_FIXED_MINOR_RANGES kernel option in order to be able to correctly
-relate a minor number to a device node number. I.e., you need to be certain
-that minor number 5 maps to device node name video5. With this kernel option
-different device types have different minor number ranges. These ranges are
-listed in <xref linkend="devices" />.
-</para>
-
- <para>The creation of character special files (with
-<application>mknod</application>) is a privileged operation and
-devices cannot be opened by major and minor number. That means
-applications cannot <emphasis>reliable</emphasis> scan for loaded or
-installed drivers. The user must enter a device name, or the
-application can try the conventional device names.</para>
- </section>
-
- <section id="related">
- <title>Related Devices</title>
-
- <para>Devices can support several functions. For example
-video capturing, VBI capturing and radio support.</para>
-
- <para>The V4L2 API creates different nodes for each of these functions.</para>
-
- <para>The V4L2 API was designed with the idea that one device node could support
-all functions. However, in practice this never worked: this 'feature'
-was never used by applications and many drivers did not support it and if
-they did it was certainly never tested. In addition, switching a device
-node between different functions only works when using the streaming I/O
-API, not with the read()/write() API.</para>
-
- <para>Today each device node supports just one function.</para>
-
- <para>Besides video input or output the hardware may also
-support audio sampling or playback. If so, these functions are
-implemented as ALSA PCM devices with optional ALSA audio mixer
-devices.</para>
-
- <para>One problem with all these devices is that the V4L2 API
-makes no provisions to find these related devices. Some really
-complex devices use the Media Controller (see <xref linkend="media_controller" />)
-which can be used for this purpose. But most drivers do not use it,
-and while some code exists that uses sysfs to discover related devices
-(see libmedia_dev in the <ulink url="http://git.linuxtv.org/cgit.cgi/v4l-utils.git/">v4l-utils</ulink>
-git repository), there is no library yet that can provide a single API towards
-both Media Controller-based devices and devices that do not use the Media Controller.
-If you want to work on this please write to the linux-media mailing list: &v4l-ml;.</para>
- </section>
-
- <section>
- <title>Multiple Opens</title>
-
- <para>V4L2 devices can be opened more than once.<footnote><para>
-There are still some old and obscure drivers that have not been updated to
-allow for multiple opens. This implies that for such drivers &func-open; can
-return an &EBUSY; when the device is already in use.</para></footnote>
-When this is supported by the driver, users can for example start a
-"panel" application to change controls like brightness or audio
-volume, while another application captures video and audio. In other words, panel
-applications are comparable to an ALSA audio mixer application.
-Just opening a V4L2 device should not change the state of the device.<footnote>
-<para>Unfortunately, opening a radio device often switches the state of the
-device to radio mode in many drivers. This behavior should be fixed eventually
-as it violates the V4L2 specification.</para></footnote></para>
-
- <para>Once an application has allocated the memory buffers needed for
-streaming data (by calling the &VIDIOC-REQBUFS; or &VIDIOC-CREATE-BUFS; ioctls,
-or implicitly by calling the &func-read; or &func-write; functions) that
-application (filehandle) becomes the owner of the device. It is no longer
-allowed to make changes that would affect the buffer sizes (e.g. by calling
-the &VIDIOC-S-FMT; ioctl) and other applications are no longer allowed to allocate
-buffers or start or stop streaming. The &EBUSY; will be returned instead.</para>
-
- <para>Merely opening a V4L2 device does not grant exclusive
-access.<footnote>
- <para>Drivers could recognize the
-<constant>O_EXCL</constant> open flag. Presently this is not required,
-so applications cannot know if it really works.</para>
- </footnote> Initiating data exchange however assigns the right
-to read or write the requested type of data, and to change related
-properties, to this file descriptor. Applications can request
-additional access privileges using the priority mechanism described in
-<xref linkend="app-pri" />.</para>
- </section>
-
- <section>
- <title>Shared Data Streams</title>
-
- <para>V4L2 drivers should not support multiple applications
-reading or writing the same data stream on a device by copying
-buffers, time multiplexing or similar means. This is better handled by
-a proxy application in user space.</para>
- </section>
-
- <section>
- <title>Functions</title>
-
- <para>To open and close V4L2 devices applications use the
-&func-open; and &func-close; function, respectively. Devices are
-programmed using the &func-ioctl; function as explained in the
-following sections.</para>
- </section>
- </section>
-
- <section id="querycap">
- <title>Querying Capabilities</title>
-
- <para>Because V4L2 covers a wide variety of devices not all
-aspects of the API are equally applicable to all types of devices.
-Furthermore devices of the same type have different capabilities and
-this specification permits the omission of a few complicated and less
-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.</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 a specific ioctl is
-supported, the V4L2 core now returns ENOTTY 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
-&VIDIOC-QUERYCAP; ioctl also allows driver specific applications to reliably identify
-the driver.</para>
-
- <para>All V4L2 drivers must support
-<constant>VIDIOC_QUERYCAP</constant>. Applications should always call
-this ioctl after opening the device.</para>
- </section>
-
- <section id="app-pri">
- <title>Application Priority</title>
-
- <para>When multiple applications share a device it may be
-desirable to assign them different priorities. Contrary to the
-traditional "rm -rf /" school of thought a video recording application
-could for example block other applications from changing video
-controls or switching the current TV channel. Another objective is to
-permit low priority applications working in background, which can be
-preempted by user controlled applications and automatically regain
-control of the device at a later time.</para>
-
- <para>Since these features cannot be implemented entirely in user
-space V4L2 defines the &VIDIOC-G-PRIORITY; and &VIDIOC-S-PRIORITY;
-ioctls to request and query the access priority associate with a file
-descriptor. Opening a device assigns a medium priority, compatible
-with earlier versions of V4L2 and drivers not supporting these ioctls.
-Applications requiring a different priority will usually call
-<constant>VIDIOC_S_PRIORITY</constant> after verifying the device with
-the &VIDIOC-QUERYCAP; ioctl.</para>
-
- <para>Ioctls changing driver properties, such as &VIDIOC-S-INPUT;,
-return an &EBUSY; after another application obtained higher priority.</para>
- </section>
-
- <section id="video">
- <title>Video Inputs and Outputs</title>
-
- <para>Video inputs and outputs are physical connectors of a
-device. These can be for example RF connectors (antenna/cable), CVBS
-a.k.a. Composite Video, S-Video or RGB connectors. Video and VBI
-capture devices have inputs. Video and VBI output devices have outputs,
-at least one each. Radio devices have no video inputs or outputs.</para>
-
- <para>To learn about the number and attributes of the
-available inputs and outputs applications can enumerate them with the
-&VIDIOC-ENUMINPUT; and &VIDIOC-ENUMOUTPUT; ioctl, respectively. The
-&v4l2-input; returned by the <constant>VIDIOC_ENUMINPUT</constant>
-ioctl also contains signal status information applicable when the
-current video input is queried.</para>
-
- <para>The &VIDIOC-G-INPUT; and &VIDIOC-G-OUTPUT; ioctls return the
-index of the current video input or output. To select a different
-input or output applications call the &VIDIOC-S-INPUT; and
-&VIDIOC-S-OUTPUT; ioctls. Drivers must implement all the input ioctls
-when the device has one or more inputs, all the output ioctls when the
-device has one or more outputs.</para>
-
- <example>
- <title>Information about the current video input</title>
-
- <programlisting>
-&v4l2-input; input;
-int index;
-
-if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;index)) {
- perror("VIDIOC_G_INPUT");
- exit(EXIT_FAILURE);
-}
-
-memset(&amp;input, 0, sizeof(input));
-input.index = index;
-
-if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
- perror("VIDIOC_ENUMINPUT");
- exit(EXIT_FAILURE);
-}
-
-printf("Current input: %s\n", input.name);
- </programlisting>
- </example>
-
- <example>
- <title>Switching to the first video input</title>
-
- <programlisting>
-int index;
-
-index = 0;
-
-if (-1 == ioctl(fd, &VIDIOC-S-INPUT;, &amp;index)) {
- perror("VIDIOC_S_INPUT");
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
- </section>
-
- <section id="audio">
- <title>Audio Inputs and Outputs</title>
-
- <para>Audio inputs and outputs are physical connectors of a
-device. Video capture devices have inputs, output devices have
-outputs, zero or more each. Radio devices have no audio inputs or
-outputs. They have exactly one tuner which in fact
-<emphasis>is</emphasis> an audio source, but this API associates
-tuners with video inputs or outputs only, and radio devices have
-none of these.<footnote>
- <para>Actually &v4l2-audio; ought to have a
-<structfield>tuner</structfield> field like &v4l2-input;, not only
-making the API more consistent but also permitting radio devices with
-multiple tuners.</para>
- </footnote> A connector on a TV card to loop back the received
-audio signal to a sound card is not considered an audio output.</para>
-
- <para>Audio and video inputs and outputs are associated. Selecting
-a video source also selects an audio source. This is most evident when
-the video and audio source is a tuner. Further audio connectors can
-combine with more than one video input or output. Assumed two
-composite video inputs and two audio inputs exist, there may be up to
-four valid combinations. The relation of video and audio connectors
-is defined in the <structfield>audioset</structfield> field of the
-respective &v4l2-input; or &v4l2-output;, where each bit represents
-the index number, starting at zero, of one audio input or output.</para>
-
- <para>To learn about the number and attributes of the
-available inputs and outputs applications can enumerate them with the
-&VIDIOC-ENUMAUDIO; and &VIDIOC-ENUMAUDOUT; ioctl, respectively. The
-&v4l2-audio; returned by the <constant>VIDIOC_ENUMAUDIO</constant> ioctl
-also contains signal status information applicable when the current
-audio input is queried.</para>
-
- <para>The &VIDIOC-G-AUDIO; and &VIDIOC-G-AUDOUT; ioctls report
-the current audio input and output, respectively. Note that, unlike
-&VIDIOC-G-INPUT; and &VIDIOC-G-OUTPUT; these ioctls return a structure
-as <constant>VIDIOC_ENUMAUDIO</constant> and
-<constant>VIDIOC_ENUMAUDOUT</constant> do, not just an index.</para>
-
- <para>To select an audio input and change its properties
-applications call the &VIDIOC-S-AUDIO; ioctl. To select an audio
-output (which presently has no changeable properties) applications
-call the &VIDIOC-S-AUDOUT; ioctl.</para>
-
- <para>Drivers must implement all audio input ioctls when the device
-has multiple selectable audio inputs, all audio output ioctls when the
-device has multiple selectable audio outputs. When the device has any
-audio inputs or outputs the driver must set the <constant>V4L2_CAP_AUDIO</constant>
-flag in the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl.</para>
-
- <example>
- <title>Information about the current audio input</title>
-
- <programlisting>
-&v4l2-audio; audio;
-
-memset(&amp;audio, 0, sizeof(audio));
-
-if (-1 == ioctl(fd, &VIDIOC-G-AUDIO;, &amp;audio)) {
- perror("VIDIOC_G_AUDIO");
- exit(EXIT_FAILURE);
-}
-
-printf("Current input: %s\n", audio.name);
- </programlisting>
- </example>
-
- <example>
- <title>Switching to the first audio input</title>
-
- <programlisting>
-&v4l2-audio; audio;
-
-memset(&amp;audio, 0, sizeof(audio)); /* clear audio.mode, audio.reserved */
-
-audio.index = 0;
-
-if (-1 == ioctl(fd, &VIDIOC-S-AUDIO;, &amp;audio)) {
- perror("VIDIOC_S_AUDIO");
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
- </section>
-
- <section id="tuner">
- <title>Tuners and Modulators</title>
-
- <section>
- <title>Tuners</title>
-
- <para>Video input devices can have one or more tuners
-demodulating a RF signal. Each tuner is associated with one or more
-video inputs, depending on the number of RF connectors on the tuner.
-The <structfield>type</structfield> field of the respective
-&v4l2-input; returned by the &VIDIOC-ENUMINPUT; ioctl is set to
-<constant>V4L2_INPUT_TYPE_TUNER</constant> and its
-<structfield>tuner</structfield> field contains the index number of
-the tuner.</para>
-
- <para>Radio input devices have exactly one tuner with index zero, no
-video inputs.</para>
-
- <para>To query and change tuner properties applications use the
-&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; ioctls, respectively. The
-&v4l2-tuner; returned by <constant>VIDIOC_G_TUNER</constant> also
-contains signal status information applicable when the tuner of the
-current video or radio input is queried. Note that
-<constant>VIDIOC_S_TUNER</constant> does not switch the current tuner,
-when there is more than one at all. The tuner is solely determined by
-the current video input. Drivers must support both ioctls and set the
-<constant>V4L2_CAP_TUNER</constant> flag in the &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl when the device has one or
-more tuners.</para>
- </section>
-
- <section>
- <title>Modulators</title>
-
- <para>Video output devices can have one or more modulators, uh,
-modulating a video signal for radiation or connection to the antenna
-input of a TV set or video recorder. Each modulator is associated with
-one or more video outputs, depending on the number of RF connectors on
-the modulator. The <structfield>type</structfield> field of the
-respective &v4l2-output; returned by the &VIDIOC-ENUMOUTPUT; ioctl is
-set to <constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> and its
-<structfield>modulator</structfield> field contains the index number
-of the modulator.</para>
-
- <para>Radio output devices have exactly one modulator with index
-zero, no video outputs.</para>
-
- <para>A video or radio device cannot support both a tuner and a
-modulator. Two separate device nodes will have to be used for such
-hardware, one that supports the tuner functionality and one that supports
-the modulator functionality. The reason is a limitation with the
-&VIDIOC-S-FREQUENCY; ioctl where you cannot specify whether the frequency
-is for a tuner or a modulator.</para>
-
- <para>To query and change modulator properties applications use
-the &VIDIOC-G-MODULATOR; and &VIDIOC-S-MODULATOR; ioctl. Note that
-<constant>VIDIOC_S_MODULATOR</constant> does not switch the current
-modulator, when there is more than one at all. The modulator is solely
-determined by the current video output. Drivers must support both
-ioctls and set the <constant>V4L2_CAP_MODULATOR</constant> flag in
-the &v4l2-capability; returned by the &VIDIOC-QUERYCAP; ioctl when the
-device has one or more modulators.</para>
- </section>
-
- <section>
- <title>Radio Frequency</title>
-
- <para>To get and set the tuner or modulator radio frequency
-applications use the &VIDIOC-G-FREQUENCY; and &VIDIOC-S-FREQUENCY;
-ioctl which both take a pointer to a &v4l2-frequency;. These ioctls
-are used for TV and radio devices alike. Drivers must support both
-ioctls when the tuner or modulator ioctls are supported, or
-when the device is a radio device.</para>
- </section>
- </section>
-
- <section id="standard">
- <title>Video Standards</title>
-
- <para>Video devices typically support one or more different video
-standards or variations of standards. Each video input and output may
-support another set of standards. This set is reported by the
-<structfield>std</structfield> field of &v4l2-input; and
-&v4l2-output; returned by the &VIDIOC-ENUMINPUT; and
-&VIDIOC-ENUMOUTPUT; ioctls, respectively.</para>
-
- <para>V4L2 defines one bit for each analog video standard
-currently in use worldwide, and sets aside bits for driver defined
-standards, &eg; hybrid standards to watch NTSC video tapes on PAL TVs
-and vice versa. Applications can use the predefined bits to select a
-particular standard, although presenting the user a menu of supported
-standards is preferred. To enumerate and query the attributes of the
-supported standards applications use the &VIDIOC-ENUMSTD; ioctl.</para>
-
- <para>Many of the defined standards are actually just variations
-of a few major standards. The hardware may in fact not distinguish
-between them, or do so internal and switch automatically. Therefore
-enumerated standards also contain sets of one or more standard
-bits.</para>
-
- <para>Assume a hypothetic tuner capable of demodulating B/PAL,
-G/PAL and I/PAL signals. The first enumerated standard is a set of B
-and G/PAL, switched automatically depending on the selected radio
-frequency in UHF or VHF band. Enumeration gives a "PAL-B/G" or "PAL-I"
-choice. Similar a Composite input may collapse standards, enumerating
-"PAL-B/G/H/I", "NTSC-M" and "SECAM-D/K".<footnote>
- <para>Some users are already confused by technical terms PAL,
-NTSC and SECAM. There is no point asking them to distinguish between
-B, G, D, or K when the software or hardware can do that
-automatically.</para>
- </footnote></para>
-
- <para>To query and select the standard used by the current video
-input or output applications call the &VIDIOC-G-STD; and
-&VIDIOC-S-STD; ioctl, respectively. The <emphasis>received</emphasis>
-standard can be sensed with the &VIDIOC-QUERYSTD; ioctl. Note that the
-parameter of all these ioctls is a pointer to a &v4l2-std-id; type
-(a standard set), <emphasis>not</emphasis> an index into the standard
-enumeration. Drivers must implement all video standard ioctls
-when the device has one or more video inputs or outputs.</para>
-
- <para>Special rules apply to devices such as USB cameras where the notion of video
-standards makes little sense. More generally for any capture or output device
-which is: <itemizedlist>
- <listitem>
- <para>incapable of capturing fields or frames at the nominal
-rate of the video standard, or</para>
- </listitem>
- <listitem>
- <para>that does not support the video standard formats at all.</para>
- </listitem>
- </itemizedlist> Here the driver shall set the
-<structfield>std</structfield> field of &v4l2-input; and &v4l2-output;
-to zero and the <constant>VIDIOC_G_STD</constant>,
-<constant>VIDIOC_S_STD</constant>,
-<constant>VIDIOC_QUERYSTD</constant> and
-<constant>VIDIOC_ENUMSTD</constant> ioctls shall return the
-&ENOTTY; or the &EINVAL;.</para>
- <para>Applications can make use of the <xref linkend="input-capabilities" /> and
-<xref linkend="output-capabilities"/> flags to determine whether the video standard ioctls
-can be used with the given input or output.</para>
-
- <example>
- <title>Information about the current video standard</title>
-
- <programlisting>
-&v4l2-std-id; std_id;
-&v4l2-standard; standard;
-
-if (-1 == ioctl(fd, &VIDIOC-G-STD;, &amp;std_id)) {
- /* Note when VIDIOC_ENUMSTD always returns ENOTTY this
- is no video device or it falls under the USB exception,
- and VIDIOC_G_STD returning ENOTTY is no error. */
-
- perror("VIDIOC_G_STD");
- exit(EXIT_FAILURE);
-}
-
-memset(&amp;standard, 0, sizeof(standard));
-standard.index = 0;
-
-while (0 == ioctl(fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
- if (standard.id &amp; std_id) {
- printf("Current video standard: %s\n", standard.name);
- exit(EXIT_SUCCESS);
- }
-
- standard.index++;
-}
-
-/* EINVAL indicates the end of the enumeration, which cannot be
- empty unless this device falls under the USB exception. */
-
-if (errno == EINVAL || standard.index == 0) {
- perror("VIDIOC_ENUMSTD");
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
-
- <example>
- <title>Listing the video standards supported by the current
-input</title>
-
- <programlisting>
-&v4l2-input; input;
-&v4l2-standard; standard;
-
-memset(&amp;input, 0, sizeof(input));
-
-if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
- perror("VIDIOC_G_INPUT");
- exit(EXIT_FAILURE);
-}
-
-if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
- perror("VIDIOC_ENUM_INPUT");
- exit(EXIT_FAILURE);
-}
-
-printf("Current input %s supports:\n", input.name);
-
-memset(&amp;standard, 0, sizeof(standard));
-standard.index = 0;
-
-while (0 == ioctl(fd, &VIDIOC-ENUMSTD;, &amp;standard)) {
- if (standard.id &amp; input.std)
- printf("%s\n", standard.name);
-
- standard.index++;
-}
-
-/* EINVAL indicates the end of the enumeration, which cannot be
- empty unless this device falls under the USB exception. */
-
-if (errno != EINVAL || standard.index == 0) {
- perror("VIDIOC_ENUMSTD");
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
-
- <example>
- <title>Selecting a new video standard</title>
-
- <programlisting>
-&v4l2-input; input;
-&v4l2-std-id; std_id;
-
-memset(&amp;input, 0, sizeof(input));
-
-if (-1 == ioctl(fd, &VIDIOC-G-INPUT;, &amp;input.index)) {
- perror("VIDIOC_G_INPUT");
- exit(EXIT_FAILURE);
-}
-
-if (-1 == ioctl(fd, &VIDIOC-ENUMINPUT;, &amp;input)) {
- perror("VIDIOC_ENUM_INPUT");
- exit(EXIT_FAILURE);
-}
-
-if (0 == (input.std &amp; V4L2_STD_PAL_BG)) {
- fprintf(stderr, "Oops. B/G PAL is not supported.\n");
- exit(EXIT_FAILURE);
-}
-
-/* Note this is also supposed to work when only B
- <emphasis>or</emphasis> G/PAL is supported. */
-
-std_id = V4L2_STD_PAL_BG;
-
-if (-1 == ioctl(fd, &VIDIOC-S-STD;, &amp;std_id)) {
- perror("VIDIOC_S_STD");
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
- </section>
- <section id="dv-timings">
- <title>Digital Video (DV) Timings</title>
- <para>
- The video standards discussed so far have been dealing with Analog TV and the
-corresponding video timings. Today there are many more different hardware interfaces
-such as High Definition TV interfaces (HDMI), VGA, DVI connectors etc., that carry
-video signals and there is a need to extend the API to select the video timings
-for these interfaces. Since it is not possible to extend the &v4l2-std-id; due to
-the limited bits available, a new set of ioctls was added to set/get video timings at
-the input and output.</para>
-
- <para>These ioctls deal with the detailed digital video timings that define
-each video format. This includes parameters such as the active video width and height,
-signal polarities, frontporches, backporches, sync widths etc. The <filename>linux/v4l2-dv-timings.h</filename>
-header can be used to get the timings of the formats in the <xref linkend="cea861" /> and
-<xref linkend="vesadmt" /> standards.
- </para>
-
- <para>To enumerate and query the attributes of the DV timings supported by a device
- applications use the &VIDIOC-ENUM-DV-TIMINGS; and &VIDIOC-DV-TIMINGS-CAP; ioctls.
- To set DV timings for the device applications use the
-&VIDIOC-S-DV-TIMINGS; ioctl and to get current DV timings they use the
-&VIDIOC-G-DV-TIMINGS; ioctl. To detect the DV timings as seen by the video receiver applications
-use the &VIDIOC-QUERY-DV-TIMINGS; ioctl.</para>
- <para>Applications can make use of the <xref linkend="input-capabilities" /> and
-<xref linkend="output-capabilities"/> flags to determine whether the digital video ioctls
-can be used with the given input or output.</para>
- </section>
-
- &sub-controls;
-
- <section id="format">
- <title>Data Formats</title>
-
- <section>
- <title>Data Format Negotiation</title>
-
- <para>Different devices exchange different kinds of data with
-applications, for example video images, raw or sliced VBI data, RDS
-datagrams. Even within one kind many different formats are possible,
-in particular an abundance of image formats. Although drivers must
-provide a default and the selection persists across closing and
-reopening a device, applications should always negotiate a data format
-before engaging in data exchange. Negotiation means the application
-asks for a particular format and the driver selects and reports the
-best the hardware can do to satisfy the request. Of course
-applications can also just query the current selection.</para>
-
- <para>A single mechanism exists to negotiate all data formats
-using the aggregate &v4l2-format; and the &VIDIOC-G-FMT; and
-&VIDIOC-S-FMT; ioctls. Additionally the &VIDIOC-TRY-FMT; ioctl can be
-used to examine what the hardware <emphasis>could</emphasis> do,
-without actually selecting a new data format. The data formats
-supported by the V4L2 API are covered in the respective device section
-in <xref linkend="devices" />. For a closer look at image formats see
-<xref linkend="pixfmt" />.</para>
-
- <para>The <constant>VIDIOC_S_FMT</constant> ioctl is a major
-turning-point in the initialization sequence. Prior to this point
-multiple panel applications can access the same device concurrently to
-select the current input, change controls or modify other properties.
-The first <constant>VIDIOC_S_FMT</constant> assigns a logical stream
-(video data, VBI data etc.) exclusively to one file descriptor.</para>
-
- <para>Exclusive means no other application, more precisely no
-other file descriptor, can grab this stream or change device
-properties inconsistent with the negotiated parameters. A video
-standard change for example, when the new standard uses a different
-number of scan lines, can invalidate the selected image format.
-Therefore only the file descriptor owning the stream can make
-invalidating changes. Accordingly multiple file descriptors which
-grabbed different logical streams prevent each other from interfering
-with their settings. When for example video overlay is about to start
-or already in progress, simultaneous video capturing may be restricted
-to the same cropping and image size.</para>
-
- <para>When applications omit the
-<constant>VIDIOC_S_FMT</constant> ioctl its locking side effects are
-implied by the next step, the selection of an I/O method with the
-&VIDIOC-REQBUFS; ioctl or implicit with the first &func-read; or
-&func-write; call.</para>
-
- <para>Generally only one logical stream can be assigned to a
-file descriptor, the exception being drivers permitting simultaneous
-video capturing and overlay using the same file descriptor for
-compatibility with V4L and earlier versions of V4L2. Switching the
-logical stream or returning into "panel mode" is possible by closing
-and reopening the device. Drivers <emphasis>may</emphasis> support a
-switch using <constant>VIDIOC_S_FMT</constant>.</para>
-
- <para>All drivers exchanging data with
-applications must support the <constant>VIDIOC_G_FMT</constant> and
-<constant>VIDIOC_S_FMT</constant> ioctl. Implementation of the
-<constant>VIDIOC_TRY_FMT</constant> is highly recommended but
-optional.</para>
- </section>
-
- <section>
- <title>Image Format Enumeration</title>
-
- <para>Apart of the generic format negotiation functions
-a special ioctl to enumerate all image formats supported by video
-capture, overlay or output devices is available.<footnote>
- <para>Enumerating formats an application has no a-priori
-knowledge of (otherwise it could explicitly ask for them and need not
-enumerate) seems useless, but there are applications serving as proxy
-between drivers and the actual video applications for which this is
-useful.</para>
- </footnote></para>
-
- <para>The &VIDIOC-ENUM-FMT; ioctl must be supported
-by all drivers exchanging image data with applications.</para>
-
- <important>
- <para>Drivers are not supposed to convert image formats in
-kernel space. They must enumerate only formats directly supported by
-the hardware. If necessary driver writers should publish an example
-conversion routine or library for integration into applications.</para>
- </important>
- </section>
- </section>
-
- &sub-planar-apis;
-
- <section id="crop">
- <title>Image Cropping, Insertion and Scaling</title>
-
- <para>Some video capture devices can sample a subsection of the
-picture and shrink or enlarge it to an image of arbitrary size. We
-call these abilities cropping and scaling. Some video output devices
-can scale an image up or down and insert it at an arbitrary scan line
-and horizontal offset into a video signal.</para>
-
- <para>Applications can use the following API to select an area in
-the video signal, query the default area and the hardware limits.
-<emphasis>Despite their name, the &VIDIOC-CROPCAP;, &VIDIOC-G-CROP;
-and &VIDIOC-S-CROP; ioctls apply to input as well as output
-devices.</emphasis></para>
-
- <para>Scaling requires a source and a target. On a video capture
-or overlay device the source is the video signal, and the cropping
-ioctls determine the area actually sampled. The target are images
-read by the application or overlaid onto the graphics screen. Their
-size (and position for an overlay) is negotiated with the
-&VIDIOC-G-FMT; and &VIDIOC-S-FMT; ioctls.</para>
-
- <para>On a video output device the source are the images passed in
-by the application, and their size is again negotiated with the
-<constant>VIDIOC_G/S_FMT</constant> ioctls, or may be encoded in a
-compressed video stream. The target is the video signal, and the
-cropping ioctls determine the area where the images are
-inserted.</para>
-
- <para>Source and target rectangles are defined even if the device
-does not support scaling or the <constant>VIDIOC_G/S_CROP</constant>
-ioctls. Their size (and position where applicable) will be fixed in
-this case. <emphasis>All capture and output device must support the
-<constant>VIDIOC_CROPCAP</constant> ioctl such that applications can
-determine if scaling takes place.</emphasis></para>
-
- <section>
- <title>Cropping Structures</title>
-
- <figure id="crop-scale">
- <title>Image Cropping, Insertion and Scaling</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="crop.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="crop.gif" format="GIF" />
- </imageobject>
- <textobject>
- <phrase>The cropping, insertion and scaling process</phrase>
- </textobject>
- </mediaobject>
- </figure>
-
- <para>For capture devices the coordinates of the top left
-corner, width and height of the area which can be sampled is given by
-the <structfield>bounds</structfield> substructure of the
-&v4l2-cropcap; returned by the <constant>VIDIOC_CROPCAP</constant>
-ioctl. To support a wide range of hardware this specification does not
-define an origin or units. However by convention drivers should
-horizontally count unscaled samples relative to 0H (the leading edge
-of the horizontal sync pulse, see <xref linkend="vbi-hsync" />).
-Vertically ITU-R line
-numbers of the first field (<xref linkend="vbi-525" />, <xref
-linkend="vbi-625" />), multiplied by two if the driver can capture both
-fields.</para>
-
- <para>The top left corner, width and height of the source
-rectangle, that is the area actually sampled, is given by &v4l2-crop;
-using the same coordinate system as &v4l2-cropcap;. Applications can
-use the <constant>VIDIOC_G_CROP</constant> and
-<constant>VIDIOC_S_CROP</constant> ioctls to get and set this
-rectangle. It must lie completely within the capture boundaries and
-the driver may further adjust the requested size and/or position
-according to hardware limitations.</para>
-
- <para>Each capture device has a default source rectangle, given
-by the <structfield>defrect</structfield> substructure of
-&v4l2-cropcap;. The center of this rectangle shall align with the
-center of the active picture area of the video signal, and cover what
-the driver writer considers the complete picture. Drivers shall reset
-the source rectangle to the default when the driver is first loaded,
-but not later.</para>
-
- <para>For output devices these structures and ioctls are used
-accordingly, defining the <emphasis>target</emphasis> rectangle where
-the images will be inserted into the video signal.</para>
-
- </section>
-
- <section>
- <title>Scaling Adjustments</title>
-
- <para>Video hardware can have various cropping, insertion and
-scaling limitations. It may only scale up or down, support only
-discrete scaling factors, or have different scaling abilities in
-horizontal and vertical direction. Also it may not support scaling at
-all. At the same time the &v4l2-crop; rectangle may have to be
-aligned, and both the source and target rectangles may have arbitrary
-upper and lower size limits. In particular the maximum
-<structfield>width</structfield> and <structfield>height</structfield>
-in &v4l2-crop; may be smaller than the
-&v4l2-cropcap;.<structfield>bounds</structfield> area. Therefore, as
-usual, drivers are expected to adjust the requested parameters and
-return the actual values selected.</para>
-
- <para>Applications can change the source or the target rectangle
-first, as they may prefer a particular image size or a certain area in
-the video signal. If the driver has to adjust both to satisfy hardware
-limitations, the last requested rectangle shall take priority, and the
-driver should preferably adjust the opposite one. The &VIDIOC-TRY-FMT;
-ioctl however shall not change the driver state and therefore only
-adjust the requested rectangle.</para>
-
- <para>Suppose scaling on a video capture device is restricted to
-a factor 1:1 or 2:1 in either direction and the target image size must
-be a multiple of 16&nbsp;&times;&nbsp;16 pixels. The source cropping
-rectangle is set to defaults, which are also the upper limit in this
-example, of 640&nbsp;&times;&nbsp;400 pixels at offset 0,&nbsp;0. An
-application requests an image size of 300&nbsp;&times;&nbsp;225
-pixels, assuming video will be scaled down from the "full picture"
-accordingly. The driver sets the image size to the closest possible
-values 304&nbsp;&times;&nbsp;224, then chooses the cropping rectangle
-closest to the requested size, that is 608&nbsp;&times;&nbsp;224
-(224&nbsp;&times;&nbsp;2:1 would exceed the limit 400). The offset
-0,&nbsp;0 is still valid, thus unmodified. Given the default cropping
-rectangle reported by <constant>VIDIOC_CROPCAP</constant> the
-application can easily propose another offset to center the cropping
-rectangle.</para>
-
- <para>Now the application may insist on covering an area using a
-picture aspect ratio closer to the original request, so it asks for a
-cropping rectangle of 608&nbsp;&times;&nbsp;456 pixels. The present
-scaling factors limit cropping to 640&nbsp;&times;&nbsp;384, so the
-driver returns the cropping size 608&nbsp;&times;&nbsp;384 and adjusts
-the image size to closest possible 304&nbsp;&times;&nbsp;192.</para>
-
- </section>
-
- <section>
- <title>Examples</title>
-
- <para>Source and target rectangles shall remain unchanged across
-closing and reopening a device, such that piping data into or out of a
-device will work without special preparations. More advanced
-applications should ensure the parameters are suitable before starting
-I/O.</para>
-
- <example>
- <title>Resetting the cropping parameters</title>
-
- <para>(A video capture device is assumed; change
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other
-devices.)</para>
-
- <programlisting>
-&v4l2-cropcap; cropcap;
-&v4l2-crop; crop;
-
-memset (&amp;cropcap, 0, sizeof (cropcap));
-cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-if (-1 == ioctl (fd, &VIDIOC-CROPCAP;, &amp;cropcap)) {
- perror ("VIDIOC_CROPCAP");
- exit (EXIT_FAILURE);
-}
-
-memset (&amp;crop, 0, sizeof (crop));
-crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-crop.c = cropcap.defrect;
-
-/* Ignore if cropping is not supported (EINVAL). */
-
-if (-1 == ioctl (fd, &VIDIOC-S-CROP;, &amp;crop)
- &amp;&amp; errno != EINVAL) {
- perror ("VIDIOC_S_CROP");
- exit (EXIT_FAILURE);
-}
- </programlisting>
- </example>
-
- <example>
- <title>Simple downscaling</title>
-
- <para>(A video capture device is assumed.)</para>
-
- <programlisting>
-&v4l2-cropcap; cropcap;
-&v4l2-format; format;
-
-reset_cropping_parameters ();
-
-/* Scale down to 1/4 size of full picture. */
-
-memset (&amp;format, 0, sizeof (format)); /* defaults */
-
-format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-format.fmt.pix.width = cropcap.defrect.width &gt;&gt; 1;
-format.fmt.pix.height = cropcap.defrect.height &gt;&gt; 1;
-format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
-
-if (-1 == ioctl (fd, &VIDIOC-S-FMT;, &amp;format)) {
- perror ("VIDIOC_S_FORMAT");
- exit (EXIT_FAILURE);
-}
-
-/* We could check the actual image size now, the actual scaling factor
- or if the driver can scale at all. */
- </programlisting>
- </example>
-
- <example>
- <title>Selecting an output area</title>
-
- <programlisting>
-&v4l2-cropcap; cropcap;
-&v4l2-crop; crop;
-
-memset (&amp;cropcap, 0, sizeof (cropcap));
-cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-
-if (-1 == ioctl (fd, VIDIOC_CROPCAP;, &amp;cropcap)) {
- perror ("VIDIOC_CROPCAP");
- exit (EXIT_FAILURE);
-}
-
-memset (&amp;crop, 0, sizeof (crop));
-
-crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-crop.c = cropcap.defrect;
-
-/* Scale the width and height to 50 % of their original size
- and center the output. */
-
-crop.c.width /= 2;
-crop.c.height /= 2;
-crop.c.left += crop.c.width / 2;
-crop.c.top += crop.c.height / 2;
-
-/* Ignore if cropping is not supported (EINVAL). */
-
-if (-1 == ioctl (fd, VIDIOC_S_CROP, &amp;crop)
- &amp;&amp; errno != EINVAL) {
- perror ("VIDIOC_S_CROP");
- exit (EXIT_FAILURE);
-}
-</programlisting>
- </example>
-
- <example>
- <title>Current scaling factor and pixel aspect</title>
-
- <para>(A video capture device is assumed.)</para>
-
- <programlisting>
-&v4l2-cropcap; cropcap;
-&v4l2-crop; crop;
-&v4l2-format; format;
-double hscale, vscale;
-double aspect;
-int dwidth, dheight;
-
-memset (&amp;cropcap, 0, sizeof (cropcap));
-cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-if (-1 == ioctl (fd, &VIDIOC-CROPCAP;, &amp;cropcap)) {
- perror ("VIDIOC_CROPCAP");
- exit (EXIT_FAILURE);
-}
-
-memset (&amp;crop, 0, sizeof (crop));
-crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-if (-1 == ioctl (fd, &VIDIOC-G-CROP;, &amp;crop)) {
- if (errno != EINVAL) {
- perror ("VIDIOC_G_CROP");
- exit (EXIT_FAILURE);
- }
-
- /* Cropping not supported. */
- crop.c = cropcap.defrect;
-}
-
-memset (&amp;format, 0, sizeof (format));
-format.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-if (-1 == ioctl (fd, &VIDIOC-G-FMT;, &amp;format)) {
- perror ("VIDIOC_G_FMT");
- exit (EXIT_FAILURE);
-}
-
-/* The scaling applied by the driver. */
-
-hscale = format.fmt.pix.width / (double) crop.c.width;
-vscale = format.fmt.pix.height / (double) crop.c.height;
-
-aspect = cropcap.pixelaspect.numerator /
- (double) cropcap.pixelaspect.denominator;
-aspect = aspect * hscale / vscale;
-
-/* Devices following ITU-R BT.601 do not capture
- square pixels. For playback on a computer monitor
- we should scale the images to this size. */
-
-dwidth = format.fmt.pix.width / aspect;
-dheight = format.fmt.pix.height;
- </programlisting>
- </example>
- </section>
- </section>
-
- &sub-selection-api;
-
- <section id="streaming-par">
- <title>Streaming Parameters</title>
-
- <para>Streaming parameters are intended to optimize the video
-capture process as well as I/O. Presently applications can request a
-high quality capture mode with the &VIDIOC-S-PARM; ioctl.</para>
-
- <para>The current video standard determines a nominal number of
-frames per second. If less than this number of frames is to be
-captured or output, applications can request frame skipping or
-duplicating on the driver side. This is especially useful when using
-the &func-read; or &func-write;, which are not augmented by timestamps
-or sequence counters, and to avoid unnecessary data copying.</para>
-
- <para>Finally these ioctls can be used to determine the number of
-buffers used internally by a driver in read/write mode. For
-implications see the section discussing the &func-read;
-function.</para>
-
- <para>To get and set the streaming parameters applications call
-the &VIDIOC-G-PARM; and &VIDIOC-S-PARM; ioctl, respectively. They take
-a pointer to a &v4l2-streamparm;, which contains a union holding
-separate parameters for input and output devices.</para>
-
- <para>These ioctls are optional, drivers need not implement
-them. If so, they return the &EINVAL;.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
deleted file mode 100644
index 82fa328abd58..000000000000
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ /dev/null
@@ -1,2723 +0,0 @@
- <title>Changes</title>
-
- <para>The following chapters document the evolution of the V4L2 API,
-errata or extensions. They are also intended to help application and
-driver writers to port or update their code.</para>
-
- <section id="diff-v4l">
- <title>Differences between V4L and V4L2</title>
-
- <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.
-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>
-
- <para>For compatibility reasons the character device file names
-recommended for V4L2 video capture, overlay, radio and raw
-vbi capture devices did not change from those used by V4L. They are
-listed in <xref linkend="devices" /> and below in <xref
- linkend="v4l-dev" />.</para>
-
- <para>The teletext devices (minor range 192-223) have been removed in
-V4L2 and no longer exist. There is no hardware available anymore for handling
-pure teletext. Instead raw or sliced VBI is used.</para>
-
- <para>The V4L <filename>videodev</filename> module automatically
-assigns minor numbers to drivers in load order, depending on the
-registered device type. We recommend that V4L2 drivers by default
-register devices with the same numbers, but the system administrator
-can assign arbitrary minor numbers using driver module options. The
-major device number remains 81.</para>
-
- <table id="v4l-dev">
- <title>V4L Device Types, Names and Numbers</title>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Device Type</entry>
- <entry>File Name</entry>
- <entry>Minor Numbers</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Video capture and overlay</entry>
- <entry><para><filename>/dev/video</filename> and
-<filename>/dev/bttv0</filename><footnote> <para>According to
-Documentation/devices.txt these should be symbolic links to
-<filename>/dev/video0</filename>. Note the original bttv interface is
-not compatible with V4L or V4L2.</para> </footnote>,
-<filename>/dev/video0</filename> to
-<filename>/dev/video63</filename></para></entry>
- <entry>0-63</entry>
- </row>
- <row>
- <entry>Radio receiver</entry>
- <entry><para><filename>/dev/radio</filename><footnote>
- <para>According to
-<filename>Documentation/devices.txt</filename> a symbolic link to
-<filename>/dev/radio0</filename>.</para>
- </footnote>, <filename>/dev/radio0</filename> to
-<filename>/dev/radio63</filename></para></entry>
- <entry>64-127</entry>
- </row>
- <row>
- <entry>Raw VBI capture</entry>
- <entry><para><filename>/dev/vbi</filename>,
-<filename>/dev/vbi0</filename> to
-<filename>/dev/vbi31</filename></para></entry>
- <entry>224-255</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>V4L prohibits (or used to prohibit) multiple opens of a
-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;.</para>
- </section>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>The V4L <constant>VIDIOCGCAP</constant> ioctl is
-equivalent to V4L2's &VIDIOC-QUERYCAP;.</para>
-
- <para>The <structfield>name</structfield> field in struct
-<structname>video_capability</structname> became
-<structfield>card</structfield> in &v4l2-capability;,
-<structfield>type</structfield> was replaced by
-<structfield>capabilities</structfield>. Note V4L2 does not
-distinguish between device types like this, better think of basic
-video input, video output and radio devices supporting a set of
-related functions like video capturing, video overlay and VBI
-capturing. See <xref linkend="open" /> for an
-introduction.<informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>struct
-<structname>video_capability</structname>
-<structfield>type</structfield></entry>
- <entry>&v4l2-capability;
-<structfield>capabilities</structfield> flags</entry>
- <entry>Purpose</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>VID_TYPE_CAPTURE</constant></entry>
- <entry><constant>V4L2_CAP_VIDEO_CAPTURE</constant></entry>
- <entry>The <link linkend="capture">video
-capture</link> interface is supported.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_TUNER</constant></entry>
- <entry><constant>V4L2_CAP_TUNER</constant></entry>
- <entry>The device has a <link linkend="tuner">tuner or
-modulator</link>.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_TELETEXT</constant></entry>
- <entry><constant>V4L2_CAP_VBI_CAPTURE</constant></entry>
- <entry>The <link linkend="raw-vbi">raw VBI
-capture</link> interface is supported.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_OVERLAY</constant></entry>
- <entry><constant>V4L2_CAP_VIDEO_OVERLAY</constant></entry>
- <entry>The <link linkend="overlay">video
-overlay</link> interface is supported.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_CHROMAKEY</constant></entry>
- <entry><constant>V4L2_FBUF_CAP_CHROMAKEY</constant> in
-field <structfield>capability</structfield> of
-&v4l2-framebuffer;</entry>
- <entry>Whether chromakey overlay is supported. For
-more information on overlay see
-<xref linkend="overlay" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_CLIPPING</constant></entry>
- <entry><constant>V4L2_FBUF_CAP_LIST_CLIPPING</constant>
-and <constant>V4L2_FBUF_CAP_BITMAP_CLIPPING</constant> in field
-<structfield>capability</structfield> of &v4l2-framebuffer;</entry>
- <entry>Whether clipping the overlaid image is
-supported, see <xref linkend="overlay" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_FRAMERAM</constant></entry>
- <entry><constant>V4L2_FBUF_CAP_EXTERNOVERLAY</constant>
-<emphasis>not set</emphasis> in field
-<structfield>capability</structfield> of &v4l2-framebuffer;</entry>
- <entry>Whether overlay overwrites frame buffer memory,
-see <xref linkend="overlay" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_SCALES</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>This flag indicates if the hardware can scale
-images. The V4L2 API implies the scale factor by setting the cropping
-dimensions and image size with the &VIDIOC-S-CROP; and &VIDIOC-S-FMT;
-ioctl, respectively. The driver returns the closest sizes possible.
-For more information on cropping and scaling see <xref
- linkend="crop" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_MONOCHROME</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>Applications can enumerate the supported image
-formats with the &VIDIOC-ENUM-FMT; ioctl to determine if the device
-supports grey scale capturing only. For more information on image
-formats see <xref linkend="pixfmt" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_SUBCAPTURE</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>Applications can call the &VIDIOC-G-CROP; ioctl
-to determine if the device supports capturing a subsection of the full
-picture ("cropping" in V4L2). If not, the ioctl returns the &EINVAL;.
-For more information on cropping and scaling see <xref
- linkend="crop" />.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_MPEG_DECODER</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>Applications can enumerate the supported image
-formats with the &VIDIOC-ENUM-FMT; ioctl to determine if the device
-supports MPEG streams.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_MPEG_ENCODER</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>See above.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_MJPEG_DECODER</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>See above.</entry>
- </row>
- <row>
- <entry><constant>VID_TYPE_MJPEG_ENCODER</constant></entry>
- <entry><constant>-</constant></entry>
- <entry>See above.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>The <structfield>audios</structfield> field was replaced
-by <structfield>capabilities</structfield> flag
-<constant>V4L2_CAP_AUDIO</constant>, indicating
-<emphasis>if</emphasis> the device has any audio inputs or outputs. To
-determine their number applications can enumerate audio inputs with
-the &VIDIOC-G-AUDIO; ioctl. The audio ioctls are described in <xref
- linkend="audio" />.</para>
-
- <para>The <structfield>maxwidth</structfield>,
-<structfield>maxheight</structfield>,
-<structfield>minwidth</structfield> and
-<structfield>minheight</structfield> fields were removed. Calling the
-&VIDIOC-S-FMT; or &VIDIOC-TRY-FMT; ioctl with the desired dimensions
-returns the closest size possible, taking into account the current
-video standard, cropping and scaling limitations.</para>
- </section>
-
- <section>
- <title>Video Sources</title>
-
- <para>V4L provides the <constant>VIDIOCGCHAN</constant> and
-<constant>VIDIOCSCHAN</constant> ioctl using struct
-<structname>video_channel</structname> to enumerate
-the video inputs of a V4L device. The equivalent V4L2 ioctls
-are &VIDIOC-ENUMINPUT;, &VIDIOC-G-INPUT; and &VIDIOC-S-INPUT;
-using &v4l2-input; as discussed in <xref linkend="video" />.</para>
-
- <para>The <structfield>channel</structfield> field counting
-inputs was renamed to <structfield>index</structfield>, the video
-input types were renamed as follows: <informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>struct <structname>video_channel</structname>
-<structfield>type</structfield></entry>
- <entry>&v4l2-input;
-<structfield>type</structfield></entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>VIDEO_TYPE_TV</constant></entry>
- <entry><constant>V4L2_INPUT_TYPE_TUNER</constant></entry>
- </row>
- <row>
- <entry><constant>VIDEO_TYPE_CAMERA</constant></entry>
- <entry><constant>V4L2_INPUT_TYPE_CAMERA</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>Unlike the <structfield>tuners</structfield> field
-expressing the number of tuners of this input, V4L2 assumes each video
-input is connected to at most one tuner. However a tuner can have more
-than one input, &ie; RF connectors, and a device can have multiple
-tuners. The index number of the tuner associated with the input, if
-any, is stored in field <structfield>tuner</structfield> of
-&v4l2-input;. Enumeration of tuners is discussed in <xref
- linkend="tuner" />.</para>
-
- <para>The redundant <constant>VIDEO_VC_TUNER</constant> flag was
-dropped. Video inputs associated with a tuner are of type
-<constant>V4L2_INPUT_TYPE_TUNER</constant>. The
-<constant>VIDEO_VC_AUDIO</constant> flag was replaced by the
-<structfield>audioset</structfield> field. V4L2 considers devices with
-up to 32 audio inputs. Each set bit in the
-<structfield>audioset</structfield> field represents one audio input
-this video input combines with. For information about audio inputs and
-how to switch between them see <xref linkend="audio" />.</para>
-
- <para>The <structfield>norm</structfield> field describing the
-supported video standards was replaced by
-<structfield>std</structfield>. The V4L specification mentions a flag
-<constant>VIDEO_VC_NORM</constant> indicating whether the standard can
-be changed. This flag was a later addition together with the
-<structfield>norm</structfield> field and has been removed in the
-meantime. V4L2 has a similar, albeit more comprehensive approach
-to video standards, see <xref linkend="standard" /> for more
-information.</para>
- </section>
-
- <section>
- <title>Tuning</title>
-
- <para>The V4L <constant>VIDIOCGTUNER</constant> and
-<constant>VIDIOCSTUNER</constant> ioctl and struct
-<structname>video_tuner</structname> can be used to enumerate the
-tuners of a V4L TV or radio device. The equivalent V4L2 ioctls are
-&VIDIOC-G-TUNER; and &VIDIOC-S-TUNER; using &v4l2-tuner;. Tuners are
-covered in <xref linkend="tuner" />.</para>
-
- <para>The <structfield>tuner</structfield> field counting tuners
-was renamed to <structfield>index</structfield>. The fields
-<structfield>name</structfield>, <structfield>rangelow</structfield>
-and <structfield>rangehigh</structfield> remained unchanged.</para>
-
- <para>The <constant>VIDEO_TUNER_PAL</constant>,
-<constant>VIDEO_TUNER_NTSC</constant> and
-<constant>VIDEO_TUNER_SECAM</constant> flags indicating the supported
-video standards were dropped. This information is now contained in the
-associated &v4l2-input;. No replacement exists for the
-<constant>VIDEO_TUNER_NORM</constant> flag indicating whether the
-video standard can be switched. The <structfield>mode</structfield>
-field to select a different video standard was replaced by a whole new
-set of ioctls and structures described in <xref linkend="standard" />.
-Due to its ubiquity it should be mentioned the BTTV driver supports
-several standards in addition to the regular
-<constant>VIDEO_MODE_PAL</constant> (0),
-<constant>VIDEO_MODE_NTSC</constant>,
-<constant>VIDEO_MODE_SECAM</constant> and
-<constant>VIDEO_MODE_AUTO</constant> (3). Namely N/PAL Argentina,
-M/PAL, N/PAL, and NTSC Japan with numbers 3-6 (sic).</para>
-
- <para>The <constant>VIDEO_TUNER_STEREO_ON</constant> flag
-indicating stereo reception became
-<constant>V4L2_TUNER_SUB_STEREO</constant> in field
-<structfield>rxsubchans</structfield>. This field also permits the
-detection of monaural and bilingual audio, see the definition of
-&v4l2-tuner; for details. Presently no replacement exists for the
-<constant>VIDEO_TUNER_RDS_ON</constant> and
-<constant>VIDEO_TUNER_MBS_ON</constant> flags.</para>
-
- <para> The <constant>VIDEO_TUNER_LOW</constant> flag was renamed
-to <constant>V4L2_TUNER_CAP_LOW</constant> in the &v4l2-tuner;
-<structfield>capability</structfield> field.</para>
-
- <para>The <constant>VIDIOCGFREQ</constant> and
-<constant>VIDIOCSFREQ</constant> ioctl to change the tuner frequency
-where renamed to &VIDIOC-G-FREQUENCY; and &VIDIOC-S-FREQUENCY;. They
-take a pointer to a &v4l2-frequency; instead of an unsigned long
-integer.</para>
- </section>
-
- <section id="v4l-image-properties">
- <title>Image Properties</title>
-
- <para>V4L2 has no equivalent of the
-<constant>VIDIOCGPICT</constant> and <constant>VIDIOCSPICT</constant>
-ioctl and struct <structname>video_picture</structname>. The following
-fields where replaced by V4L2 controls accessible with the
-&VIDIOC-QUERYCTRL;, &VIDIOC-G-CTRL; and &VIDIOC-S-CTRL; ioctls:<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>struct <structname>video_picture</structname></entry>
- <entry>V4L2 Control ID</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><structfield>brightness</structfield></entry>
- <entry><constant>V4L2_CID_BRIGHTNESS</constant></entry>
- </row>
- <row>
- <entry><structfield>hue</structfield></entry>
- <entry><constant>V4L2_CID_HUE</constant></entry>
- </row>
- <row>
- <entry><structfield>colour</structfield></entry>
- <entry><constant>V4L2_CID_SATURATION</constant></entry>
- </row>
- <row>
- <entry><structfield>contrast</structfield></entry>
- <entry><constant>V4L2_CID_CONTRAST</constant></entry>
- </row>
- <row>
- <entry><structfield>whiteness</structfield></entry>
- <entry><constant>V4L2_CID_WHITENESS</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>The V4L picture controls are assumed to range from 0 to
-65535 with no particular reset value. The V4L2 API permits arbitrary
-limits and defaults which can be queried with the &VIDIOC-QUERYCTRL;
-ioctl. For general information about controls see <xref
-linkend="control" />.</para>
-
- <para>The <structfield>depth</structfield> (average number of
-bits per pixel) of a video image is implied by the selected image
-format. V4L2 does not explicitly provide such information assuming
-applications recognizing the format are aware of the image depth and
-others need not know. The <structfield>palette</structfield> field
-moved into the &v4l2-pix-format;:<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>struct <structname>video_picture</structname>
-<structfield>palette</structfield></entry>
- <entry>&v4l2-pix-format;
-<structfield>pixfmt</structfield></entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>VIDEO_PALETTE_GREY</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-GREY"><constant>V4L2_PIX_FMT_GREY</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_HI240</constant></entry>
- <entry><para><link
-linkend="pixfmt-reserved"><constant>V4L2_PIX_FMT_HI240</constant></link><footnote>
- <para>This is a custom format used by the BTTV
-driver, not one of the V4L2 standard formats.</para>
- </footnote></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_RGB565</constant></entry>
- <entry><para><link
-linkend="pixfmt-rgb"><constant>V4L2_PIX_FMT_RGB565</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_RGB555</constant></entry>
- <entry><para><link
-linkend="pixfmt-rgb"><constant>V4L2_PIX_FMT_RGB555</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_RGB24</constant></entry>
- <entry><para><link
-linkend="pixfmt-rgb"><constant>V4L2_PIX_FMT_BGR24</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_RGB32</constant></entry>
- <entry><para><link
-linkend="pixfmt-rgb"><constant>V4L2_PIX_FMT_BGR32</constant></link><footnote>
- <para>Presumably all V4L RGB formats are
-little-endian, although some drivers might interpret them according to machine endianness. V4L2 defines little-endian, big-endian and red/blue
-swapped variants. For details see <xref linkend="pixfmt-rgb" />.</para>
- </footnote></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV422</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YUYV"><constant>V4L2_PIX_FMT_YUYV</constant></link></para></entry>
- </row>
- <row>
- <entry><para><constant>VIDEO_PALETTE_YUYV</constant><footnote>
- <para><constant>VIDEO_PALETTE_YUV422</constant>
-and <constant>VIDEO_PALETTE_YUYV</constant> are the same formats. Some
-V4L drivers respond to one, some to the other.</para>
- </footnote></para></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YUYV"><constant>V4L2_PIX_FMT_YUYV</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_UYVY</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-UYVY"><constant>V4L2_PIX_FMT_UYVY</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV420</constant></entry>
- <entry>None</entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV411</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-Y41P"><constant>V4L2_PIX_FMT_Y41P</constant></link><footnote>
- <para>Not to be confused with
-<constant>V4L2_PIX_FMT_YUV411P</constant>, which is a planar
-format.</para> </footnote></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_RAW</constant></entry>
- <entry><para>None<footnote> <para>V4L explains this
-as: "RAW capture (BT848)"</para> </footnote></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV422P</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YUV422P"><constant>V4L2_PIX_FMT_YUV422P</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV411P</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YUV411P"><constant>V4L2_PIX_FMT_YUV411P</constant></link><footnote>
- <para>Not to be confused with
-<constant>V4L2_PIX_FMT_Y41P</constant>, which is a packed
-format.</para> </footnote></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV420P</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YVU420"><constant>V4L2_PIX_FMT_YVU420</constant></link></para></entry>
- </row>
- <row>
- <entry><constant>VIDEO_PALETTE_YUV410P</constant></entry>
- <entry><para><link
-linkend="V4L2-PIX-FMT-YVU410"><constant>V4L2_PIX_FMT_YVU410</constant></link></para></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>V4L2 image formats are defined in <xref
-linkend="pixfmt" />. The image format can be selected with the
-&VIDIOC-S-FMT; ioctl.</para>
- </section>
-
- <section>
- <title>Audio</title>
-
- <para>The <constant>VIDIOCGAUDIO</constant> and
-<constant>VIDIOCSAUDIO</constant> ioctl and struct
-<structname>video_audio</structname> are used to enumerate the
-audio inputs of a V4L device. The equivalent V4L2 ioctls are
-&VIDIOC-G-AUDIO; and &VIDIOC-S-AUDIO; using &v4l2-audio; as
-discussed in <xref linkend="audio" />.</para>
-
- <para>The <structfield>audio</structfield> "channel number"
-field counting audio inputs was renamed to
-<structfield>index</structfield>.</para>
-
- <para>On <constant>VIDIOCSAUDIO</constant> the
-<structfield>mode</structfield> field selects <emphasis>one</emphasis>
-of the <constant>VIDEO_SOUND_MONO</constant>,
-<constant>VIDEO_SOUND_STEREO</constant>,
-<constant>VIDEO_SOUND_LANG1</constant> or
-<constant>VIDEO_SOUND_LANG2</constant> audio demodulation modes. When
-the current audio standard is BTSC
-<constant>VIDEO_SOUND_LANG2</constant> refers to SAP and
-<constant>VIDEO_SOUND_LANG1</constant> is meaningless. Also
-undocumented in the V4L specification, there is no way to query the
-selected mode. On <constant>VIDIOCGAUDIO</constant> the driver returns
-the <emphasis>actually received</emphasis> audio programmes in this
-field. In the V4L2 API this information is stored in the &v4l2-tuner;
-<structfield>rxsubchans</structfield> and
-<structfield>audmode</structfield> fields, respectively. See <xref
-linkend="tuner" /> for more information on tuners. Related to audio
-modes &v4l2-audio; also reports if this is a mono or stereo
-input, regardless if the source is a tuner.</para>
-
- <para>The following fields where replaced by V4L2 controls
-accessible with the &VIDIOC-QUERYCTRL;, &VIDIOC-G-CTRL; and
-&VIDIOC-S-CTRL; ioctls:<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>struct
-<structname>video_audio</structname></entry>
- <entry>V4L2 Control ID</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><structfield>volume</structfield></entry>
- <entry><constant>V4L2_CID_AUDIO_VOLUME</constant></entry>
- </row>
- <row>
- <entry><structfield>bass</structfield></entry>
- <entry><constant>V4L2_CID_AUDIO_BASS</constant></entry>
- </row>
- <row>
- <entry><structfield>treble</structfield></entry>
- <entry><constant>V4L2_CID_AUDIO_TREBLE</constant></entry>
- </row>
- <row>
- <entry><structfield>balance</structfield></entry>
- <entry><constant>V4L2_CID_AUDIO_BALANCE</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>To determine which of these controls are supported by a
-driver V4L provides the <structfield>flags</structfield>
-<constant>VIDEO_AUDIO_VOLUME</constant>,
-<constant>VIDEO_AUDIO_BASS</constant>,
-<constant>VIDEO_AUDIO_TREBLE</constant> and
-<constant>VIDEO_AUDIO_BALANCE</constant>. In the V4L2 API the
-&VIDIOC-QUERYCTRL; ioctl reports if the respective control is
-supported. Accordingly the <constant>VIDEO_AUDIO_MUTABLE</constant>
-and <constant>VIDEO_AUDIO_MUTE</constant> flags where replaced by the
-boolean <constant>V4L2_CID_AUDIO_MUTE</constant> control.</para>
-
- <para>All V4L2 controls have a <structfield>step</structfield>
-attribute replacing the struct <structname>video_audio</structname>
-<structfield>step</structfield> field. The V4L audio controls are
-assumed to range from 0 to 65535 with no particular reset value. The
-V4L2 API permits arbitrary limits and defaults which can be queried
-with the &VIDIOC-QUERYCTRL; ioctl. For general information about
-controls see <xref linkend="control" />.</para>
- </section>
-
- <section>
- <title>Frame Buffer Overlay</title>
-
- <para>The V4L2 ioctls equivalent to
-<constant>VIDIOCGFBUF</constant> and <constant>VIDIOCSFBUF</constant>
-are &VIDIOC-G-FBUF; and &VIDIOC-S-FBUF;. The
-<structfield>base</structfield> field of struct
-<structname>video_buffer</structname> remained unchanged, except V4L2
-defines a flag to indicate non-destructive overlays instead of a
-<constant>NULL</constant> pointer. All other fields moved into the
-&v4l2-pix-format; <structfield>fmt</structfield> substructure of
-&v4l2-framebuffer;. The <structfield>depth</structfield> field was
-replaced by <structfield>pixelformat</structfield>. See <xref
- linkend="pixfmt-rgb" /> for a list of RGB formats and their
-respective color depths.</para>
-
- <para>Instead of the special ioctls
-<constant>VIDIOCGWIN</constant> and <constant>VIDIOCSWIN</constant>
-V4L2 uses the general-purpose data format negotiation ioctls
-&VIDIOC-G-FMT; and &VIDIOC-S-FMT;. They take a pointer to a
-&v4l2-format; as argument. Here the <structfield>win</structfield>
-member of the <structfield>fmt</structfield> union is used, a
-&v4l2-window;.</para>
-
- <para>The <structfield>x</structfield>,
-<structfield>y</structfield>, <structfield>width</structfield> and
-<structfield>height</structfield> fields of struct
-<structname>video_window</structname> moved into &v4l2-rect;
-substructure <structfield>w</structfield> of struct
-<structname>v4l2_window</structname>. The
-<structfield>chromakey</structfield>,
-<structfield>clips</structfield>, and
-<structfield>clipcount</structfield> fields remained unchanged. Struct
-<structname>video_clip</structname> was renamed to &v4l2-clip;, also
-containing a struct <structname>v4l2_rect</structname>, but the
-semantics are still the same.</para>
-
- <para>The <constant>VIDEO_WINDOW_INTERLACE</constant> flag was
-dropped. Instead applications must set the
-<structfield>field</structfield> field to
-<constant>V4L2_FIELD_ANY</constant> or
-<constant>V4L2_FIELD_INTERLACED</constant>. The
-<constant>VIDEO_WINDOW_CHROMAKEY</constant> flag moved into
-&v4l2-framebuffer;, under the new name
-<constant>V4L2_FBUF_FLAG_CHROMAKEY</constant>.</para>
-
- <para>In V4L, storing a bitmap pointer in
-<structfield>clips</structfield> and setting
-<structfield>clipcount</structfield> to
-<constant>VIDEO_CLIP_BITMAP</constant> (-1) requests bitmap
-clipping, using a fixed size bitmap of 1024 &times; 625 bits. Struct
-<structname>v4l2_window</structname> has a separate
-<structfield>bitmap</structfield> pointer field for this purpose and
-the bitmap size is determined by <structfield>w.width</structfield> and
-<structfield>w.height</structfield>.</para>
-
- <para>The <constant>VIDIOCCAPTURE</constant> ioctl to enable or
-disable overlay was renamed to &VIDIOC-OVERLAY;.</para>
- </section>
-
- <section>
- <title>Cropping</title>
-
- <para>To capture only a subsection of the full picture V4L
-defines the <constant>VIDIOCGCAPTURE</constant> and
-<constant>VIDIOCSCAPTURE</constant> ioctls using struct
-<structname>video_capture</structname>. The equivalent V4L2 ioctls are
-&VIDIOC-G-CROP; and &VIDIOC-S-CROP; using &v4l2-crop;, and the related
-&VIDIOC-CROPCAP; ioctl. This is a rather complex matter, see
-<xref linkend="crop" /> for details.</para>
-
- <para>The <structfield>x</structfield>,
-<structfield>y</structfield>, <structfield>width</structfield> and
-<structfield>height</structfield> fields moved into &v4l2-rect;
-substructure <structfield>c</structfield> of struct
-<structname>v4l2_crop</structname>. The
-<structfield>decimation</structfield> field was dropped. In the V4L2
-API the scaling factor is implied by the size of the cropping
-rectangle and the size of the captured or overlaid image.</para>
-
- <para>The <constant>VIDEO_CAPTURE_ODD</constant>
-and <constant>VIDEO_CAPTURE_EVEN</constant> flags to capture only the
-odd or even field, respectively, were replaced by
-<constant>V4L2_FIELD_TOP</constant> and
-<constant>V4L2_FIELD_BOTTOM</constant> in the field named
-<structfield>field</structfield> of &v4l2-pix-format; and
-&v4l2-window;. These structures are used to select a capture or
-overlay format with the &VIDIOC-S-FMT; ioctl.</para>
- </section>
-
- <section>
- <title>Reading Images, Memory Mapping</title>
-
- <section>
- <title>Capturing using the read method</title>
-
- <para>There is no essential difference between reading images
-from a V4L or V4L2 device using the &func-read; function, however V4L2
-drivers are not required to support this I/O method. Applications can
-determine if the function is available with the &VIDIOC-QUERYCAP;
-ioctl. All V4L2 devices exchanging data with applications must support
-the &func-select; and &func-poll; functions.</para>
-
- <para>To select an image format and size, V4L provides the
-<constant>VIDIOCSPICT</constant> and <constant>VIDIOCSWIN</constant>
-ioctls. V4L2 uses the general-purpose data format negotiation ioctls
-&VIDIOC-G-FMT; and &VIDIOC-S-FMT;. They take a pointer to a
-&v4l2-format; as argument, here the &v4l2-pix-format; named
-<structfield>pix</structfield> of its <structfield>fmt</structfield>
-union is used.</para>
-
- <para>For more information about the V4L2 read interface see
-<xref linkend="rw" />.</para>
- </section>
- <section>
- <title>Capturing using memory mapping</title>
-
- <para>Applications can read from V4L devices by mapping
-buffers in device memory, or more often just buffers allocated in
-DMA-able system memory, into their address space. This avoids the data
-copying overhead of the read method. V4L2 supports memory mapping as
-well, with a few differences.</para>
-
- <informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>V4L</entry>
- <entry>V4L2</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>The image format must be selected before
-buffers are allocated, with the &VIDIOC-S-FMT; ioctl. When no format
-is selected the driver may use the last, possibly by another
-application requested format.</entry>
- </row>
- <row>
- <entry><para>Applications cannot change the number of
-buffers. The it is built into the driver, unless it has a module
-option to change the number when the driver module is
-loaded.</para></entry>
- <entry><para>The &VIDIOC-REQBUFS; ioctl allocates the
-desired number of buffers, this is a required step in the initialization
-sequence.</para></entry>
- </row>
- <row>
- <entry><para>Drivers map all buffers as one contiguous
-range of memory. The <constant>VIDIOCGMBUF</constant> ioctl is
-available to query the number of buffers, the offset of each buffer
-from the start of the virtual file, and the overall amount of memory
-used, which can be used as arguments for the &func-mmap;
-function.</para></entry>
- <entry><para>Buffers are individually mapped. The
-offset and size of each buffer can be determined with the
-&VIDIOC-QUERYBUF; ioctl.</para></entry>
- </row>
- <row>
- <entry><para>The <constant>VIDIOCMCAPTURE</constant>
-ioctl prepares a buffer for capturing. It also determines the image
-format for this buffer. The ioctl returns immediately, eventually with
-an &EAGAIN; if no video signal had been detected. When the driver
-supports more than one buffer applications can call the ioctl multiple
-times and thus have multiple outstanding capture
-requests.</para><para>The <constant>VIDIOCSYNC</constant> ioctl
-suspends execution until a particular buffer has been
-filled.</para></entry>
- <entry><para>Drivers maintain an incoming and outgoing
-queue. &VIDIOC-QBUF; enqueues any empty buffer into the incoming
-queue. Filled buffers are dequeued from the outgoing queue with the
-&VIDIOC-DQBUF; ioctl. To wait until filled buffers become available this
-function, &func-select; or &func-poll; can be used. The
-&VIDIOC-STREAMON; ioctl must be called once after enqueuing one or
-more buffers to start capturing. Its counterpart
-&VIDIOC-STREAMOFF; stops capturing and dequeues all buffers from both
-queues. Applications can query the signal status, if known, with the
-&VIDIOC-ENUMINPUT; ioctl.</para></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>For a more in-depth discussion of memory mapping and
-examples, see <xref linkend="mmap" />.</para>
- </section>
- </section>
-
- <section>
- <title>Reading Raw VBI Data</title>
-
- <para>Originally the V4L API did not specify a raw VBI capture
-interface, only the device file <filename>/dev/vbi</filename> was
-reserved for this purpose. The only driver supporting this interface
-was the BTTV driver, de-facto defining the V4L VBI interface. Reading
-from the device yields a raw VBI image with the following
-parameters:<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>&v4l2-vbi-format;</entry>
- <entry>V4L, BTTV driver</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>sampling_rate</entry>
- <entry>28636363&nbsp;Hz NTSC (or any other 525-line
-standard); 35468950&nbsp;Hz PAL and SECAM (625-line standards)</entry>
- </row>
- <row>
- <entry>offset</entry>
- <entry>?</entry>
- </row>
- <row>
- <entry>samples_per_line</entry>
- <entry>2048</entry>
- </row>
- <row>
- <entry>sample_format</entry>
- <entry>V4L2_PIX_FMT_GREY. The last four bytes (a
-machine endianness integer) contain a frame counter.</entry>
- </row>
- <row>
- <entry>start[]</entry>
- <entry>10, 273 NTSC; 22, 335 PAL and SECAM</entry>
- </row>
- <row>
- <entry>count[]</entry>
- <entry><para>16, 16<footnote><para>Old driver
-versions used different values, eventually the custom
-<constant>BTTV_VBISIZE</constant> ioctl was added to query the
-correct values.</para></footnote></para></entry>
- </row>
- <row>
- <entry>flags</entry>
- <entry>0</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>Undocumented in the V4L specification, in Linux 2.3 the
-<constant>VIDIOCGVBIFMT</constant> and
-<constant>VIDIOCSVBIFMT</constant> ioctls using struct
-<structname>vbi_format</structname> were added to determine the VBI
-image parameters. These ioctls are only partially compatible with the
-V4L2 VBI interface specified in <xref linkend="raw-vbi" />.</para>
-
- <para>An <structfield>offset</structfield> field does not
-exist, <structfield>sample_format</structfield> is supposed to be
-<constant>VIDEO_PALETTE_RAW</constant>, equivalent to
-<constant>V4L2_PIX_FMT_GREY</constant>. The remaining fields are
-probably equivalent to &v4l2-vbi-format;.</para>
-
- <para>Apparently only the Zoran (ZR 36120) driver implements
-these ioctls. The semantics differ from those specified for V4L2 in two
-ways. The parameters are reset on &func-open; and
-<constant>VIDIOCSVBIFMT</constant> always returns an &EINVAL; if the
-parameters are invalid.</para>
- </section>
-
- <section>
- <title>Miscellaneous</title>
-
- <para>V4L2 has no equivalent of the
-<constant>VIDIOCGUNIT</constant> ioctl. Applications can find the VBI
-device associated with a video capture device (or vice versa) by
-reopening the device and requesting VBI data. For details see
-<xref linkend="open" />.</para>
-
- <para>No replacement exists for <constant>VIDIOCKEY</constant>,
-and the V4L functions for microcode programming. A new interface for
-MPEG compression and playback devices is documented in <xref
- linkend="extended-controls" />.</para>
- </section>
-
- </section>
-
- <section id="hist-v4l2">
- <title>Changes of the V4L2 API</title>
-
- <para>Soon after the V4L API was added to the kernel it was
-criticised as too inflexible. In August 1998 Bill Dirks proposed a
-number of improvements and began to work on documentation, example
-drivers and applications. With the help of other volunteers this
-eventually became the V4L2 API, not just an extension but a
-replacement for the V4L API. However it took another four years and
-two stable kernel releases until the new API was finally accepted for
-inclusion into the kernel in its present form.</para>
-
- <section>
- <title>Early Versions</title>
- <para>1998-08-20: First version.</para>
-
- <para>1998-08-27: The &func-select; function was introduced.</para>
-
- <para>1998-09-10: New video standard interface.</para>
-
- <para>1998-09-18: The <constant>VIDIOC_NONCAP</constant> ioctl
-was replaced by the otherwise meaningless <constant>O_TRUNC</constant>
-&func-open; flag, and the aliases <constant>O_NONCAP</constant> and
-<constant>O_NOIO</constant> were defined. Applications can set this
-flag if they intend to access controls only, as opposed to capture
-applications which need exclusive access. The
-<constant>VIDEO_STD_XXX</constant> identifiers are now ordinals
-instead of flags, and the <function>video_std_construct()</function>
-helper function takes id and transmission arguments.</para>
-
- <para>1998-09-28: Revamped video standard. Made video controls
-individually enumerable.</para>
-
- <para>1998-10-02: The <structfield>id</structfield> field was
-removed from struct <structname>video_standard</structname> and the
-color subcarrier fields were renamed. The &VIDIOC-QUERYSTD; ioctl was
-renamed to &VIDIOC-ENUMSTD;, &VIDIOC-G-INPUT; to &VIDIOC-ENUMINPUT;. A
-first draft of the Codec API was released.</para>
-
- <para>1998-11-08: Many minor changes. Most symbols have been
-renamed. Some material changes to &v4l2-capability;.</para>
-
- <para>1998-11-12: The read/write directon of some ioctls was misdefined.</para>
-
- <para>1998-11-14: <constant>V4L2_PIX_FMT_RGB24</constant>
-changed to <constant>V4L2_PIX_FMT_BGR24</constant>, and
-<constant>V4L2_PIX_FMT_RGB32</constant> changed to
-<constant>V4L2_PIX_FMT_BGR32</constant>. Audio controls are now
-accessible with the &VIDIOC-G-CTRL; and &VIDIOC-S-CTRL; ioctls under
-names starting with <constant>V4L2_CID_AUDIO</constant>. The
-<constant>V4L2_MAJOR</constant> define was removed from
-<filename>videodev.h</filename> since it was only used once in the
-<filename>videodev</filename> kernel module. The
-<constant>YUV422</constant> and <constant>YUV411</constant> planar
-image formats were added.</para>
-
- <para>1998-11-28: A few ioctl symbols changed. Interfaces for codecs and
-video output devices were added.</para>
-
- <para>1999-01-14: A raw VBI capture interface was added.</para>
-
- <para>1999-01-19: The <constant>VIDIOC_NEXTBUF</constant> ioctl
- was removed.</para>
- </section>
-
- <section>
- <title>V4L2 Version 0.16 1999-01-31</title>
- <para>1999-01-27: There is now one QBUF ioctl, VIDIOC_QWBUF and VIDIOC_QRBUF
-are gone. VIDIOC_QBUF takes a v4l2_buffer as a parameter. Added
-digital zoom (cropping) controls.</para>
- </section>
-
- <!-- Where's 0.17? mhs couldn't find that videodev.h, perhaps Bill
- forgot to bump the version number or never released it. -->
-
- <section>
- <title>V4L2 Version 0.18 1999-03-16</title>
- <para>Added a v4l to V4L2 ioctl compatibility layer to
-videodev.c. Driver writers, this changes how you implement your ioctl
-handler. See the Driver Writer's Guide. Added some more control id
-codes.</para>
- </section>
-
- <section>
- <title>V4L2 Version 0.19 1999-06-05</title>
- <para>1999-03-18: Fill in the category and catname fields of
-v4l2_queryctrl objects before passing them to the driver. Required a
-minor change to the VIDIOC_QUERYCTRL handlers in the sample
-drivers.</para>
- <para>1999-03-31: Better compatibility for v4l memory capture
-ioctls. Requires changes to drivers to fully support new compatibility
-features, see Driver Writer's Guide and v4l2cap.c. Added new control
-IDs: V4L2_CID_HFLIP, _VFLIP. Changed V4L2_PIX_FMT_YUV422P to _YUV422P,
-and _YUV411P to _YUV411P.</para>
- <para>1999-04-04: Added a few more control IDs.</para>
- <para>1999-04-07: Added the button control type.</para>
- <para>1999-05-02: Fixed a typo in videodev.h, and added the
-V4L2_CTRL_FLAG_GRAYED (later V4L2_CTRL_FLAG_GRABBED) flag.</para>
- <para>1999-05-20: Definition of VIDIOC_G_CTRL was wrong causing
-a malfunction of this ioctl.</para>
- <para>1999-06-05: Changed the value of
-V4L2_CID_WHITENESS.</para>
- </section>
-
- <section>
- <title>V4L2 Version 0.20 (1999-09-10)</title>
-
- <para>Version 0.20 introduced a number of changes which were
-<emphasis>not backward compatible</emphasis> with 0.19 and earlier
-versions. Purpose of these changes was to simplify the API, while
-making it more extensible and following common Linux driver API
-conventions.</para>
-
- <orderedlist>
- <listitem>
- <para>Some typos in <constant>V4L2_FMT_FLAG</constant>
-symbols were fixed. &v4l2-clip; was changed for compatibility with
-v4l. (1999-08-30)</para>
- </listitem>
-
- <listitem>
- <para><constant>V4L2_TUNER_SUB_LANG1</constant> was added.
-(1999-09-05)</para>
- </listitem>
-
- <listitem>
- <para>All ioctl() commands that used an integer argument now
-take a pointer to an integer. Where it makes sense, ioctls will return
-the actual new value in the integer pointed to by the argument, a
-common convention in the V4L2 API. The affected ioctls are:
-VIDIOC_PREVIEW, VIDIOC_STREAMON, VIDIOC_STREAMOFF, VIDIOC_S_FREQ,
-VIDIOC_S_INPUT, VIDIOC_S_OUTPUT, VIDIOC_S_EFFECT. For example
-<programlisting>
-err = ioctl (fd, VIDIOC_XXX, V4L2_XXX);
-</programlisting> becomes <programlisting>
-int a = V4L2_XXX; err = ioctl(fd, VIDIOC_XXX, &amp;a);
-</programlisting>
- </para>
- </listitem>
-
- <listitem>
- <para>All the different get- and set-format commands were
-swept into one &VIDIOC-G-FMT; and &VIDIOC-S-FMT; ioctl taking a union
-and a type field selecting the union member as parameter. Purpose is to
-simplify the API by eliminating several ioctls and to allow new and
-driver private data streams without adding new ioctls.</para>
-
- <para>This change obsoletes the following ioctls:
-<constant>VIDIOC_S_INFMT</constant>,
-<constant>VIDIOC_G_INFMT</constant>,
-<constant>VIDIOC_S_OUTFMT</constant>,
-<constant>VIDIOC_G_OUTFMT</constant>,
-<constant>VIDIOC_S_VBIFMT</constant> and
-<constant>VIDIOC_G_VBIFMT</constant>. The image format structure
-<structname>v4l2_format</structname> was renamed to &v4l2-pix-format;,
-while &v4l2-format; is now the envelopping structure for all format
-negotiations.</para>
- </listitem>
-
- <listitem>
- <para>Similar to the changes above, the
-<constant>VIDIOC_G_PARM</constant> and
-<constant>VIDIOC_S_PARM</constant> ioctls were merged with
-<constant>VIDIOC_G_OUTPARM</constant> and
-<constant>VIDIOC_S_OUTPARM</constant>. A
-<structfield>type</structfield> field in the new &v4l2-streamparm;
-selects the respective union member.</para>
-
- <para>This change obsoletes the
-<constant>VIDIOC_G_OUTPARM</constant> and
-<constant>VIDIOC_S_OUTPARM</constant> ioctls.</para>
- </listitem>
-
- <listitem>
- <para>Control enumeration was simplified, and two new
-control flags were introduced and one dropped. The
-<structfield>catname</structfield> field was replaced by a
-<structfield>group</structfield> field.</para>
-
- <para>Drivers can now flag unsupported and temporarily
-unavailable controls with <constant>V4L2_CTRL_FLAG_DISABLED</constant>
-and <constant>V4L2_CTRL_FLAG_GRABBED</constant> respectively. The
-<structfield>group</structfield> name indicates a possibly narrower
-classification than the <structfield>category</structfield>. In other
-words, there may be multiple groups within a category. Controls within
-a group would typically be drawn within a group box. Controls in
-different categories might have a greater separation, or may even
-appear in separate windows.</para>
- </listitem>
-
- <listitem>
- <para>The &v4l2-buffer; <structfield>timestamp</structfield>
-was changed to a 64 bit integer, containing the sampling or output
-time of the frame in nanoseconds. Additionally timestamps will be in
-absolute system time, not starting from zero at the beginning of a
-stream. The data type name for timestamps is stamp_t, defined as a
-signed 64-bit integer. Output devices should not send a buffer out
-until the time in the timestamp field has arrived. I would like to
-follow SGI's lead, and adopt a multimedia timestamping system like
-their UST (Unadjusted System Time). See
-http://web.archive.org/web/*/http://reality.sgi.com
-/cpirazzi_engr/lg/time/intro.html.
-UST uses timestamps that are 64-bit signed integers
-(not struct timeval's) and given in nanosecond units. The UST clock
-starts at zero when the system is booted and runs continuously and
-uniformly. It takes a little over 292 years for UST to overflow. There
-is no way to set the UST clock. The regular Linux time-of-day clock
-can be changed periodically, which would cause errors if it were being
-used for timestamping a multimedia stream. A real UST style clock will
-require some support in the kernel that is not there yet. But in
-anticipation, I will change the timestamp field to a 64-bit integer,
-and I will change the v4l2_masterclock_gettime() function (used only
-by drivers) to return a 64-bit integer.</para>
- </listitem>
-
- <listitem>
- <para>A <structfield>sequence</structfield> field was added
-to &v4l2-buffer;. The <structfield>sequence</structfield> field counts
-captured frames, it is ignored by output devices. When a capture
-driver drops a frame, the sequence number of that frame is
-skipped.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 Version 0.20 incremental changes</title>
- <!-- Version number didn't change anymore, reason unknown. -->
-
- <para>1999-12-23: In &v4l2-vbi-format; the
-<structfield>reserved1</structfield> field became
-<structfield>offset</structfield>. Previously drivers were required to
-clear the <structfield>reserved1</structfield> field.</para>
-
- <para>2000-01-13: The
- <constant>V4L2_FMT_FLAG_NOT_INTERLACED</constant> flag was added.</para>
-
- <para>2000-07-31: The <filename>linux/poll.h</filename> header
-is now included by <filename>videodev.h</filename> for compatibility
-with the original <filename>videodev.h</filename> file.</para>
-
- <para>2000-11-20: <constant>V4L2_TYPE_VBI_OUTPUT</constant> and
-<constant>V4L2_PIX_FMT_Y41P</constant> were added.</para>
-
- <para>2000-11-25: <constant>V4L2_TYPE_VBI_INPUT</constant> was
-added.</para>
-
- <para>2000-12-04: A couple typos in symbol names were fixed.</para>
-
- <para>2001-01-18: To avoid namespace conflicts the
-<constant>fourcc</constant> macro defined in the
-<filename>videodev.h</filename> header file was renamed to
-<constant>v4l2_fourcc</constant>.</para>
-
- <para>2001-01-25: A possible driver-level compatibility problem
-between the <filename>videodev.h</filename> file in Linux 2.4.0 and
-the <filename>videodev.h</filename> file included in the
-<filename>videodevX</filename> patch was fixed. Users of an earlier
-version of <filename>videodevX</filename> on Linux 2.4.0 should
-recompile their V4L and V4L2 drivers.</para>
-
- <para>2001-01-26: A possible kernel-level incompatibility
-between the <filename>videodev.h</filename> file in the
-<filename>videodevX</filename> patch and the
-<filename>videodev.h</filename> file in Linux 2.2.x with devfs patches
-applied was fixed.</para>
-
- <para>2001-03-02: Certain V4L ioctls which pass data in both
-direction although they are defined with read-only parameter, did not
-work correctly through the backward compatibility layer.
-[Solution?]</para>
-
- <para>2001-04-13: Big endian 16-bit RGB formats were added.</para>
-
- <para>2001-09-17: New YUV formats and the &VIDIOC-G-FREQUENCY; and
-&VIDIOC-S-FREQUENCY; ioctls were added. (The old
-<constant>VIDIOC_G_FREQ</constant> and
-<constant>VIDIOC_S_FREQ</constant> ioctls did not take multiple tuners
-into account.)</para>
-
- <para>2000-09-18: <constant>V4L2_BUF_TYPE_VBI</constant> was
-added. This may <emphasis>break compatibility</emphasis> as the
-&VIDIOC-G-FMT; and &VIDIOC-S-FMT; ioctls may fail now if the struct
-<structname>v4l2_fmt</structname> <structfield>type</structfield>
-field does not contain <constant>V4L2_BUF_TYPE_VBI</constant>. In the
-documentation of the &v4l2-vbi-format;
-<structfield>offset</structfield> field the ambiguous phrase "rising
-edge" was changed to "leading edge".</para>
- </section>
-
- <section>
- <title>V4L2 Version 0.20 2000-11-23</title>
-
- <para>A number of changes were made to the raw VBI
-interface.</para>
-
- <orderedlist>
- <listitem>
- <para>Figures clarifying the line numbering scheme were
-added to the V4L2 API specification. The
-<structfield>start</structfield>[0] and
-<structfield>start</structfield>[1] fields no longer count line
-numbers beginning at zero. Rationale: a) The previous definition was
-unclear. b) The <structfield>start</structfield>[] values are ordinal
-numbers. c) There is no point in inventing a new line numbering
-scheme. We now use line number as defined by ITU-R, period.
-Compatibility: Add one to the start values. Applications depending on
-the previous semantics may not function correctly.</para>
- </listitem>
-
- <listitem>
- <para>The restriction "count[0] &gt; 0 and count[1] &gt; 0"
-has been relaxed to "(count[0] + count[1]) &gt; 0". Rationale:
-Drivers may allocate resources at scan line granularity and some data
-services are transmitted only on the first field. The comment that
-both <structfield>count</structfield> values will usually be equal is
-misleading and pointless and has been removed. This change
-<emphasis>breaks compatibility</emphasis> with earlier versions:
-Drivers may return EINVAL, applications may not function
-correctly.</para>
- </listitem>
-
- <listitem>
- <para>Drivers are again permitted to return negative
-(unknown) start values as proposed earlier. Why this feature was
-dropped is unclear. This change may <emphasis>break
-compatibility</emphasis> with applications depending on the start
-values being positive. The use of <constant>EBUSY</constant> and
-<constant>EINVAL</constant> error codes with the &VIDIOC-S-FMT; ioctl
-was clarified. The &EBUSY; was finally documented, and the
-<structfield>reserved2</structfield> field which was previously
-mentioned only in the <filename>videodev.h</filename> header
-file.</para>
- </listitem>
-
- <listitem>
- <para>New buffer types
-<constant>V4L2_TYPE_VBI_INPUT</constant> and
-<constant>V4L2_TYPE_VBI_OUTPUT</constant> were added. The former is an
-alias for the old <constant>V4L2_TYPE_VBI</constant>, the latter was
-missing in the <filename>videodev.h</filename> file.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 Version 0.20 2002-07-25</title>
- <para>Added sliced VBI interface proposal.</para>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.5.46, 2002-10</title>
-
- <para>Around October-November 2002, prior to an announced
-feature freeze of Linux 2.5, the API was revised, drawing from
-experience with V4L2 0.20. This unnamed version was finally merged
-into Linux 2.5.46.</para>
-
- <orderedlist>
- <listitem>
- <para>As specified in <xref linkend="related" />, drivers
-must make related device functions available under all minor device
-numbers.</para>
- </listitem>
-
- <listitem>
- <para>The &func-open; function requires access mode
-<constant>O_RDWR</constant> regardless of the device type. All V4L2
-drivers exchanging data with applications must support the
-<constant>O_NONBLOCK</constant> flag. The <constant>O_NOIO</constant>
-flag, a V4L2 symbol which aliased the meaningless
-<constant>O_TRUNC</constant> to indicate accesses without data
-exchange (panel applications) was dropped. Drivers must stay in "panel
-mode" until the application attempts to initiate a data exchange, see
-<xref linkend="open" />.</para>
- </listitem>
-
- <listitem>
- <para>The &v4l2-capability; changed dramatically. Note that
-also the size of the structure changed, which is encoded in the ioctl
-request code, thus older V4L2 devices will respond with an &EINVAL; to
-the new &VIDIOC-QUERYCAP; ioctl.</para>
-
- <para>There are new fields to identify the driver, a new RDS
-device function <constant>V4L2_CAP_RDS_CAPTURE</constant>, the
-<constant>V4L2_CAP_AUDIO</constant> flag indicates if the device has
-any audio connectors, another I/O capability
-<constant>V4L2_CAP_ASYNCIO</constant> can be flagged. In response to
-these changes the <structfield>type</structfield> field became a bit
-set and was merged into the <structfield>flags</structfield> field.
-<constant>V4L2_FLAG_TUNER</constant> was renamed to
-<constant>V4L2_CAP_TUNER</constant>,
-<constant>V4L2_CAP_VIDEO_OVERLAY</constant> replaced
-<constant>V4L2_FLAG_PREVIEW</constant> and
-<constant>V4L2_CAP_VBI_CAPTURE</constant> and
-<constant>V4L2_CAP_VBI_OUTPUT</constant> replaced
-<constant>V4L2_FLAG_DATA_SERVICE</constant>.
-<constant>V4L2_FLAG_READ</constant> and
-<constant>V4L2_FLAG_WRITE</constant> were merged into
-<constant>V4L2_CAP_READWRITE</constant>.</para>
-
- <para>The redundant fields
-<structfield>inputs</structfield>, <structfield>outputs</structfield>
-and <structfield>audios</structfield> were removed. These properties
-can be determined as described in <xref linkend="video" /> and <xref
-linkend="audio" />.</para>
-
- <para>The somewhat volatile and therefore barely useful
-fields <structfield>maxwidth</structfield>,
-<structfield>maxheight</structfield>,
-<structfield>minwidth</structfield>,
-<structfield>minheight</structfield>,
-<structfield>maxframerate</structfield> were removed. This information
-is available as described in <xref linkend="format" /> and
-<xref linkend="standard" />.</para>
-
- <para><constant>V4L2_FLAG_SELECT</constant> was removed. We
-believe the select() function is important enough to require support
-of it in all V4L2 drivers exchanging data with applications. The
-redundant <constant>V4L2_FLAG_MONOCHROME</constant> flag was removed,
-this information is available as described in <xref
- linkend="format" />.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-input; the
-<structfield>assoc_audio</structfield> field and the
-<structfield>capability</structfield> field and its only flag
-<constant>V4L2_INPUT_CAP_AUDIO</constant> was replaced by the new
-<structfield>audioset</structfield> field. Instead of linking one
-video input to one audio input this field reports all audio inputs
-this video input combines with.</para>
-
- <para>New fields are <structfield>tuner</structfield>
-(reversing the former link from tuners to video inputs),
-<structfield>std</structfield> and
-<structfield>status</structfield>.</para>
-
- <para>Accordingly &v4l2-output; lost its
-<structfield>capability</structfield> and
-<structfield>assoc_audio</structfield> fields.
-<structfield>audioset</structfield>,
-<structfield>modulator</structfield> and
-<structfield>std</structfield> where added instead.</para>
- </listitem>
-
- <listitem>
- <para>The &v4l2-audio; field
-<structfield>audio</structfield> was renamed to
-<structfield>index</structfield>, for consistency with other
-structures. A new capability flag
-<constant>V4L2_AUDCAP_STEREO</constant> was added to indicated if the
-audio input in question supports stereo sound.
-<constant>V4L2_AUDCAP_EFFECTS</constant> and the corresponding
-<constant>V4L2_AUDMODE</constant> flags where removed. This can be
-easily implemented using controls. (However the same applies to AVL
-which is still there.)</para>
-
- <para>Again for consistency the &v4l2-audioout; field
-<structfield>audio</structfield> was renamed to
-<structfield>index</structfield>.</para>
- </listitem>
-
- <listitem>
- <para>The &v4l2-tuner;
-<structfield>input</structfield> field was replaced by an
-<structfield>index</structfield> field, permitting devices with
-multiple tuners. The link between video inputs and tuners is now
-reversed, inputs point to their tuner. The
-<structfield>std</structfield> substructure became a
-simple set (more about this below) and moved into &v4l2-input;. A
-<structfield>type</structfield> field was added.</para>
-
- <para>Accordingly in &v4l2-modulator; the
-<structfield>output</structfield> was replaced by an
-<structfield>index</structfield> field.</para>
-
- <para>In &v4l2-frequency; the
-<structfield>port</structfield> field was replaced by a
-<structfield>tuner</structfield> field containing the respective tuner
-or modulator index number. A tuner <structfield>type</structfield>
-field was added and the <structfield>reserved</structfield> field
-became larger for future extensions (satellite tuners in
-particular).</para>
- </listitem>
-
- <listitem>
- <para>The idea of completely transparent video standards was
-dropped. Experience showed that applications must be able to work with
-video standards beyond presenting the user a menu. Instead of
-enumerating supported standards with an ioctl applications can now
-refer to standards by &v4l2-std-id; and symbols defined in the
-<filename>videodev2.h</filename> header file. For details see <xref
- linkend="standard" />. The &VIDIOC-G-STD; and
-&VIDIOC-S-STD; now take a pointer to this type as argument.
-&VIDIOC-QUERYSTD; was added to autodetect the received standard, if
-the hardware has this capability. In &v4l2-standard; an
-<structfield>index</structfield> field was added for &VIDIOC-ENUMSTD;.
-A &v4l2-std-id; field named <structfield>id</structfield> was added as
-machine readable identifier, also replacing the
-<structfield>transmission</structfield> field. The misleading
-<structfield>framerate</structfield> field was renamed
-to <structfield>frameperiod</structfield>. The now obsolete
-<structfield>colorstandard</structfield> information, originally
-needed to distguish between variations of standards, were
-removed.</para>
-
- <para>Struct <structname>v4l2_enumstd</structname> ceased to
-be. &VIDIOC-ENUMSTD; now takes a pointer to a &v4l2-standard;
-directly. The information which standards are supported by a
-particular video input or output moved into &v4l2-input; and
-&v4l2-output; fields named <structfield>std</structfield>,
-respectively.</para>
- </listitem>
-
- <listitem>
- <para>The &v4l2-queryctrl; fields
-<structfield>category</structfield> and
-<structfield>group</structfield> did not catch on and/or were not
-implemented as expected and therefore removed.</para>
- </listitem>
-
- <listitem>
- <para>The &VIDIOC-TRY-FMT; ioctl was added to negotiate data
-formats as with &VIDIOC-S-FMT;, but without the overhead of
-programming the hardware and regardless of I/O in progress.</para>
-
- <para>In &v4l2-format; the <structfield>fmt</structfield>
-union was extended to contain &v4l2-window;. All image format
-negotiations are now possible with <constant>VIDIOC_G_FMT</constant>,
-<constant>VIDIOC_S_FMT</constant> and
-<constant>VIDIOC_TRY_FMT</constant>; ioctl. The
-<constant>VIDIOC_G_WIN</constant> and
-<constant>VIDIOC_S_WIN</constant> ioctls to prepare for a video
-overlay were removed. The <structfield>type</structfield> field
-changed to type &v4l2-buf-type; and the buffer type names changed as
-follows.<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Old defines</entry>
- <entry>&v4l2-buf-type;</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_BUF_TYPE_CAPTURE</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant></entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_CODECIN</constant></entry>
- <entry>Omitted for now</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_CODECOUT</constant></entry>
- <entry>Omitted for now</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_EFFECTSIN</constant></entry>
- <entry>Omitted for now</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_EFFECTSIN2</constant></entry>
- <entry>Omitted for now</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_EFFECTSOUT</constant></entry>
- <entry>Omitted for now</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEOOUT</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_VBI_CAPTURE</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_SLICED_VBI_CAPTURE</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_SLICED_VBI_OUTPUT</constant></entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_PRIVATE_BASE</constant></entry>
- <entry><constant>V4L2_BUF_TYPE_PRIVATE</constant> (but this is deprecated)</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-fmtdesc; a &v4l2-buf-type; field named
-<structfield>type</structfield> was added as in &v4l2-format;. The
-<constant>VIDIOC_ENUM_FBUFFMT</constant> ioctl is no longer needed and
-was removed. These calls can be replaced by &VIDIOC-ENUM-FMT; with
-type <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-pix-format; the
-<structfield>depth</structfield> field was removed, assuming
-applications which recognize the format by its four-character-code
-already know the color depth, and others do not care about it. The
-same rationale lead to the removal of the
-<constant>V4L2_FMT_FLAG_COMPRESSED</constant> flag. The
-<constant>V4L2_FMT_FLAG_SWCONVECOMPRESSED</constant> flag was removed
-because drivers are not supposed to convert images in kernel space. A
-user library of conversion functions should be provided instead. The
-<constant>V4L2_FMT_FLAG_BYTESPERLINE</constant> flag was redundant.
-Applications can set the <structfield>bytesperline</structfield> field
-to zero to get a reasonable default. Since the remaining flags were
-replaced as well, the <structfield>flags</structfield> field itself
-was removed.</para>
- <para>The interlace flags were replaced by a &v4l2-field;
-value in a newly added <structfield>field</structfield>
-field.<informaltable>
- <tgroup cols="2">
- <thead>
- <row>
- <entry>Old flag</entry>
- <entry>&v4l2-field;</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FMT_FLAG_NOT_INTERLACED</constant></entry>
- <entry>?</entry>
- </row>
- <row>
- <entry><constant>V4L2_FMT_FLAG_INTERLACED</constant>
-= <constant>V4L2_FMT_FLAG_COMBINED</constant></entry>
- <entry><constant>V4L2_FIELD_INTERLACED</constant></entry>
- </row>
- <row>
- <entry><constant>V4L2_FMT_FLAG_TOPFIELD</constant>
-= <constant>V4L2_FMT_FLAG_ODDFIELD</constant></entry>
- <entry><constant>V4L2_FIELD_TOP</constant></entry>
- </row>
- <row>
- <entry><constant>V4L2_FMT_FLAG_BOTFIELD</constant>
-= <constant>V4L2_FMT_FLAG_EVENFIELD</constant></entry>
- <entry><constant>V4L2_FIELD_BOTTOM</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_FIELD_SEQ_TB</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_FIELD_SEQ_BT</constant></entry>
- </row>
- <row>
- <entry><constant>-</constant></entry>
- <entry><constant>V4L2_FIELD_ALTERNATE</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
-
- <para>The color space flags were replaced by a
-&v4l2-colorspace; value in a newly added
-<structfield>colorspace</structfield> field, where one of
-<constant>V4L2_COLORSPACE_SMPTE170M</constant>,
-<constant>V4L2_COLORSPACE_BT878</constant>,
-<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant> or
-<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant> replaces
-<constant>V4L2_FMT_CS_601YUV</constant>.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-requestbuffers; the
-<structfield>type</structfield> field was properly defined as
-&v4l2-buf-type;. Buffer types changed as mentioned above. A new
-<structfield>memory</structfield> field of type &v4l2-memory; was
-added to distinguish between I/O methods using buffers allocated
-by the driver or the application. See <xref linkend="io" /> for
-details.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-buffer; the <structfield>type</structfield>
-field was properly defined as &v4l2-buf-type;. Buffer types changed as
-mentioned above. A <structfield>field</structfield> field of type
-&v4l2-field; was added to indicate if a buffer contains a top or
-bottom field. The old field flags were removed. Since no unadjusted
-system time clock was added to the kernel as planned, the
-<structfield>timestamp</structfield> field changed back from type
-stamp_t, an unsigned 64 bit integer expressing the sample time in
-nanoseconds, to struct <structname>timeval</structname>. With the
-addition of a second memory mapping method the
-<structfield>offset</structfield> field moved into union
-<structfield>m</structfield>, and a new
-<structfield>memory</structfield> field of type &v4l2-memory; was
-added to distinguish between I/O methods. See <xref linkend="io" />
-for details.</para>
-
- <para>The <constant>V4L2_BUF_REQ_CONTIG</constant>
-flag was used by the V4L compatibility layer, after changes to this
-code it was no longer needed. The
-<constant>V4L2_BUF_ATTR_DEVICEMEM</constant> flag would indicate if
-the buffer was indeed allocated in device memory rather than DMA-able
-system memory. It was barely useful and so was removed.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-framebuffer; the
-<structfield>base[3]</structfield> array anticipating double- and
-triple-buffering in off-screen video memory, however without defining
-a synchronization mechanism, was replaced by a single pointer. The
-<constant>V4L2_FBUF_CAP_SCALEUP</constant> and
-<constant>V4L2_FBUF_CAP_SCALEDOWN</constant> flags were removed.
-Applications can determine this capability more accurately using the
-new cropping and scaling interface. The
-<constant>V4L2_FBUF_CAP_CLIPPING</constant> flag was replaced by
-<constant>V4L2_FBUF_CAP_LIST_CLIPPING</constant> and
-<constant>V4L2_FBUF_CAP_BITMAP_CLIPPING</constant>.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-clip; the <structfield>x</structfield>,
-<structfield>y</structfield>, <structfield>width</structfield> and
-<structfield>height</structfield> field moved into a
-<structfield>c</structfield> substructure of type &v4l2-rect;. The
-<structfield>x</structfield> and <structfield>y</structfield> fields
-were renamed to <structfield>left</structfield> and
-<structfield>top</structfield>, &ie; offsets to a context dependent
-origin.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-window; the <structfield>x</structfield>,
-<structfield>y</structfield>, <structfield>width</structfield> and
-<structfield>height</structfield> field moved into a
-<structfield>w</structfield> substructure as above. A
-<structfield>field</structfield> field of type %v4l2-field; was added
-to distinguish between field and frame (interlaced) overlay.</para>
- </listitem>
-
- <listitem>
- <para>The digital zoom interface, including struct
-<structname>v4l2_zoomcap</structname>, struct
-<structname>v4l2_zoom</structname>,
-<constant>V4L2_ZOOM_NONCAP</constant> and
-<constant>V4L2_ZOOM_WHILESTREAMING</constant> was replaced by a new
-cropping and scaling interface. The previously unused struct
-<structname>v4l2_cropcap</structname> and
-<structname>v4l2_crop</structname> where redefined for this purpose.
-See <xref linkend="crop" /> for details.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-vbi-format; the
-<structfield>SAMPLE_FORMAT</structfield> field now contains a
-four-character-code as used to identify video image formats and
-<constant>V4L2_PIX_FMT_GREY</constant> replaces the
-<constant>V4L2_VBI_SF_UBYTE</constant> define. The
-<structfield>reserved</structfield> field was extended.</para>
- </listitem>
-
- <listitem>
- <para>In &v4l2-captureparm; the type of the
-<structfield>timeperframe</structfield> field changed from unsigned
-long to &v4l2-fract;. This allows the accurate expression of multiples
-of the NTSC-M frame rate 30000 / 1001. A new field
-<structfield>readbuffers</structfield> was added to control the driver
-behaviour in read I/O mode.</para>
-
- <para>Similar changes were made to &v4l2-outputparm;.</para>
- </listitem>
-
- <listitem>
- <para>The struct <structname>v4l2_performance</structname>
-and <constant>VIDIOC_G_PERF</constant> ioctl were dropped. Except when
-using the <link linkend="rw">read/write I/O method</link>, which is
-limited anyway, this information is already available to
-applications.</para>
- </listitem>
-
- <listitem>
- <para>The example transformation from RGB to YCbCr color
-space in the old V4L2 documentation was inaccurate, this has been
-corrected in <xref linkend="pixfmt" />.<!-- 0.5670G should be
-0.587, and 127/112 != 255/224 --></para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 2003-06-19</title>
-
- <orderedlist>
- <listitem>
- <para>A new capability flag
-<constant>V4L2_CAP_RADIO</constant> was added for radio devices. Prior
-to this change radio devices would identify solely by having exactly one
-tuner whose type field reads <constant>V4L2_TUNER_RADIO</constant>.</para>
- </listitem>
-
- <listitem>
- <para>An optional driver access priority mechanism was
-added, see <xref linkend="app-pri" /> for details.</para>
- </listitem>
-
- <listitem>
- <para>The audio input and output interface was found to be
-incomplete.</para>
- <para>Previously the &VIDIOC-G-AUDIO;
-ioctl would enumerate the available audio inputs. An ioctl to
-determine the current audio input, if more than one combines with the
-current video input, did not exist. So
-<constant>VIDIOC_G_AUDIO</constant> was renamed to
-<constant>VIDIOC_G_AUDIO_OLD</constant>, this ioctl was removed on
-Kernel 2.6.39. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate
-audio inputs, while &VIDIOC-G-AUDIO; now reports the current audio
-input.</para>
- <para>The same changes were made to &VIDIOC-G-AUDOUT; and
-&VIDIOC-ENUMAUDOUT;.</para>
- <para>Until further the "videodev" module will automatically
-translate between the old and new ioctls, but drivers and applications
-must be updated to successfully compile again.</para>
- </listitem>
-
- <listitem>
- <para>The &VIDIOC-OVERLAY; ioctl was incorrectly defined with
-write-read parameter. It was changed to write-only, while the write-read
-version was renamed to <constant>VIDIOC_OVERLAY_OLD</constant>. The old
-ioctl was removed on Kernel 2.6.39. Until further the "videodev"
-kernel module will automatically translate to the new version, so drivers
-must be recompiled, but not applications.</para>
- </listitem>
-
- <listitem>
- <para><xref linkend="overlay" /> incorrectly stated that
-clipping rectangles define regions where the video can be seen.
-Correct is that clipping rectangles define regions where
-<emphasis>no</emphasis> video shall be displayed and so the graphics
-surface can be seen.</para>
- </listitem>
-
- <listitem>
- <para>The &VIDIOC-S-PARM; and &VIDIOC-S-CTRL; ioctls were
-defined with write-only parameter, inconsistent with other ioctls
-modifying their argument. They were changed to write-read, while a
-<constant>_OLD</constant> suffix was added to the write-only versions.
-The old ioctls were removed on Kernel 2.6.39. Drivers and
-applications assuming a constant parameter need an update.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 2003-11-05</title>
- <orderedlist>
- <listitem>
- <para>In <xref linkend="pixfmt-rgb" /> the following pixel
-formats were incorrectly transferred from Bill Dirks' V4L2
-specification. Descriptions below refer to bytes in memory, in
-ascending address order.<informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Symbol</entry>
- <entry>In this document prior to revision
-0.5</entry>
- <entry>Corrected</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_PIX_FMT_RGB24</constant></entry>
- <entry>B, G, R</entry>
- <entry>R, G, B</entry>
- </row>
- <row>
- <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
- <entry>R, G, B</entry>
- <entry>B, G, R</entry>
- </row>
- <row>
- <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
- <entry>B, G, R, X</entry>
- <entry>R, G, B, X</entry>
- </row>
- <row>
- <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
- <entry>R, G, B, X</entry>
- <entry>B, G, R, X</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable> The
-<constant>V4L2_PIX_FMT_BGR24</constant> example was always
-correct.</para>
- <para>In <xref linkend="v4l-image-properties" /> the mapping
-of the V4L <constant>VIDEO_PALETTE_RGB24</constant> and
-<constant>VIDEO_PALETTE_RGB32</constant> formats to V4L2 pixel formats
-was accordingly corrected.</para>
- </listitem>
-
- <listitem>
- <para>Unrelated to the fixes above, drivers may still
-interpret some V4L2 RGB pixel formats differently. These issues have
-yet to be addressed, for details see <xref
- linkend="pixfmt-rgb" />.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.6, 2004-05-09</title>
- <orderedlist>
- <listitem>
- <para>The &VIDIOC-CROPCAP; ioctl was incorrectly defined
-with read-only parameter. It is now defined as write-read ioctl, while
-the read-only version was renamed to
-<constant>VIDIOC_CROPCAP_OLD</constant>. The old ioctl was removed
-on Kernel 2.6.39.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.8</title>
- <orderedlist>
- <listitem>
- <para>A new field <structfield>input</structfield> (former
-<structfield>reserved[0]</structfield>) was added to the &v4l2-buffer;
-structure. Purpose of this field is to alternate between video inputs
-(&eg; cameras) in step with the video capturing process. This function
-must be enabled with the new <constant>V4L2_BUF_FLAG_INPUT</constant>
-flag. The <structfield>flags</structfield> field is no longer
-read-only.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2004-08-01</title>
-
- <orderedlist>
- <listitem>
- <para>The return value of the
-<xref linkend="func-open" /> function was incorrectly documented.</para>
- </listitem>
-
- <listitem>
- <para>Audio output ioctls end in -AUDOUT, not -AUDIOOUT.</para>
- </listitem>
-
- <listitem>
- <para>In the Current Audio Input example the
-<constant>VIDIOC_G_AUDIO</constant> ioctl took the wrong
-argument.</para>
- </listitem>
-
- <listitem>
- <para>The documentation of the &VIDIOC-QBUF; and
-&VIDIOC-DQBUF; ioctls did not mention the &v4l2-buffer;
-<structfield>memory</structfield> field. It was also missing from
-examples. Also on the <constant>VIDIOC_DQBUF</constant> page the &EIO;
-was not documented.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.14</title>
- <orderedlist>
- <listitem>
- <para>A new sliced VBI interface was added. It is documented
-in <xref linkend="sliced" /> and replaces the interface first
-proposed in V4L2 specification 0.8.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.15</title>
- <orderedlist>
- <listitem>
- <para>The &VIDIOC-LOG-STATUS; ioctl was added.</para>
- </listitem>
-
- <listitem>
- <para>New video standards
-<constant>V4L2_STD_NTSC_443</constant>,
-<constant>V4L2_STD_SECAM_LC</constant>,
-<constant>V4L2_STD_SECAM_DK</constant> (a set of SECAM D, K and K1),
-and <constant>V4L2_STD_ATSC</constant> (a set of
-<constant>V4L2_STD_ATSC_8_VSB</constant> and
-<constant>V4L2_STD_ATSC_16_VSB</constant>) were defined. Note the
-<constant>V4L2_STD_525_60</constant> set now includes
-<constant>V4L2_STD_NTSC_443</constant>. See also <xref
- linkend="v4l2-std-id" />.</para>
- </listitem>
-
- <listitem>
- <para>The <constant>VIDIOC_G_COMP</constant> and
-<constant>VIDIOC_S_COMP</constant> ioctl were renamed to
-<constant>VIDIOC_G_MPEGCOMP</constant> and
-<constant>VIDIOC_S_MPEGCOMP</constant> respectively. Their argument
-was replaced by a struct
-<structname>v4l2_mpeg_compression</structname> pointer. (The
-<constant>VIDIOC_G_MPEGCOMP</constant> and
-<constant>VIDIOC_S_MPEGCOMP</constant> ioctls where removed in Linux
-2.6.25.)</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2005-11-27</title>
- <para>The capture example in <xref linkend="capture-example" />
-called the &VIDIOC-S-CROP; ioctl without checking if cropping is
-supported. In the video standard selection example in
-<xref linkend="standard" /> the &VIDIOC-S-STD; call used the wrong
-argument type.</para>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2006-01-10</title>
- <orderedlist>
- <listitem>
- <para>The <constant>V4L2_IN_ST_COLOR_KILL</constant> flag in
-&v4l2-input; not only indicates if the color killer is enabled, but
-also if it is active. (The color killer disables color decoding when
-it detects no color in the video signal to improve the image
-quality.)</para>
- </listitem>
-
- <listitem>
- <para>&VIDIOC-S-PARM; is a write-read ioctl, not write-only as
-stated on its reference page. The ioctl changed in 2003 as noted above.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2006-02-03</title>
- <orderedlist>
- <listitem>
- <para>In &v4l2-captureparm; and &v4l2-outputparm; the
-<structfield>timeperframe</structfield> field gives the time in
-seconds, not microseconds.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2006-02-04</title>
- <orderedlist>
- <listitem>
- <para>The <structfield>clips</structfield> field in
-&v4l2-window; must point to an array of &v4l2-clip;, not a linked
-list, because drivers ignore the struct
-<structname>v4l2_clip</structname>.<structfield>next</structfield>
-pointer.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.17</title>
- <orderedlist>
- <listitem>
- <para>New video standard macros were added:
-<constant>V4L2_STD_NTSC_M_KR</constant> (NTSC M South Korea), and the
-sets <constant>V4L2_STD_MN</constant>,
-<constant>V4L2_STD_B</constant>, <constant>V4L2_STD_GH</constant> and
-<constant>V4L2_STD_DK</constant>. The
-<constant>V4L2_STD_NTSC</constant> and
-<constant>V4L2_STD_SECAM</constant> sets now include
-<constant>V4L2_STD_NTSC_M_KR</constant> and
-<constant>V4L2_STD_SECAM_LC</constant> respectively.</para>
- </listitem>
-
- <listitem>
- <para>A new <constant>V4L2_TUNER_MODE_LANG1_LANG2</constant>
-was defined to record both languages of a bilingual program. The
-use of <constant>V4L2_TUNER_MODE_STEREO</constant> for this purpose
-is deprecated now. See the &VIDIOC-G-TUNER; section for
-details.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2006-09-23 (Draft 0.15)</title>
- <orderedlist>
- <listitem>
- <para>In various places
-<constant>V4L2_BUF_TYPE_SLICED_VBI_CAPTURE</constant> and
-<constant>V4L2_BUF_TYPE_SLICED_VBI_OUTPUT</constant> of the sliced VBI
-interface were not mentioned along with other buffer types.</para>
- </listitem>
-
- <listitem>
- <para>In <xref linkend="vidioc-g-audio" /> it was clarified
-that the &v4l2-audio; <structfield>mode</structfield> field is a flags
-field.</para>
- </listitem>
-
- <listitem>
- <para><xref linkend="vidioc-querycap" /> did not mention the
-sliced VBI and radio capability flags.</para>
- </listitem>
-
- <listitem>
- <para>In <xref linkend="vidioc-g-frequency" /> it was
-clarified that applications must initialize the tuner
-<structfield>type</structfield> field of &v4l2-frequency; before
-calling &VIDIOC-S-FREQUENCY;.</para>
- </listitem>
-
- <listitem>
- <para>The <structfield>reserved</structfield> array
-in &v4l2-requestbuffers; has 2 elements, not 32.</para>
- </listitem>
-
- <listitem>
- <para>In <xref linkend="output" /> and <xref
- linkend="raw-vbi" /> the device file names
-<filename>/dev/vout</filename> which never caught on were replaced
-by <filename>/dev/video</filename>.</para>
- </listitem>
-
- <listitem>
- <para>With Linux 2.6.15 the possible range for VBI device minor
-numbers was extended from 224-239 to 224-255. Accordingly device file names
-<filename>/dev/vbi0</filename> to <filename>/dev/vbi31</filename> are
-possible now.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.18</title>
- <orderedlist>
- <listitem>
- <para>New ioctls &VIDIOC-G-EXT-CTRLS;, &VIDIOC-S-EXT-CTRLS;
-and &VIDIOC-TRY-EXT-CTRLS; were added, a flag to skip unsupported
-controls with &VIDIOC-QUERYCTRL;, new control types
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
-<constant>V4L2_CTRL_TYPE_CTRL_CLASS</constant> (<xref
- linkend="v4l2-ctrl-type" />), and new control flags
-<constant>V4L2_CTRL_FLAG_READ_ONLY</constant>,
-<constant>V4L2_CTRL_FLAG_UPDATE</constant>,
-<constant>V4L2_CTRL_FLAG_INACTIVE</constant> and
-<constant>V4L2_CTRL_FLAG_SLIDER</constant> (<xref
- linkend="control-flags" />). See <xref
- linkend="extended-controls" /> for details.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.19</title>
- <orderedlist>
- <listitem>
- <para>In &v4l2-sliced-vbi-cap; a buffer type field was added
-replacing a reserved field. Note on architectures where the size of
-enum types differs from int types the size of the structure changed.
-The &VIDIOC-G-SLICED-VBI-CAP; ioctl was redefined from being read-only
-to write-read. Applications must initialize the type field and clear
-the reserved fields now. These changes may <emphasis>break the
-compatibility</emphasis> with older drivers and applications.</para>
- </listitem>
-
- <listitem>
- <para>The ioctls &VIDIOC-ENUM-FRAMESIZES; and
-&VIDIOC-ENUM-FRAMEINTERVALS; were added.</para>
- </listitem>
-
- <listitem>
- <para>A new pixel format <constant>V4L2_PIX_FMT_RGB444</constant> (<xref
-linkend="rgb-formats" />) was added.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 spec erratum 2006-10-12 (Draft 0.17)</title>
- <orderedlist>
- <listitem>
- <para><constant>V4L2_PIX_FMT_HM12</constant> (<xref
-linkend="reserved-formats" />) is a YUV 4:2:0, not 4:2:2 format.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.21</title>
- <orderedlist>
- <listitem>
- <para>The <filename>videodev2.h</filename> header file is
-now dual licensed under GNU General Public License version two or
-later, and under a 3-clause BSD-style license.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.22</title>
- <orderedlist>
- <listitem>
- <para>Two new field orders
- <constant>V4L2_FIELD_INTERLACED_TB</constant> and
- <constant>V4L2_FIELD_INTERLACED_BT</constant> were
- added. See <xref linkend="v4l2-field" /> for details.</para>
- </listitem>
-
- <listitem>
- <para>Three new clipping/blending methods with a global or
-straight or inverted local alpha value were added to the video overlay
-interface. See the description of the &VIDIOC-G-FBUF; and
-&VIDIOC-S-FBUF; ioctls for details.</para>
- <para>A new <structfield>global_alpha</structfield> field
-was added to <link
-linkend="v4l2-window"><structname>v4l2_window</structname></link>,
-extending the structure. This may <emphasis>break
-compatibility</emphasis> with applications using a struct
-<structname>v4l2_window</structname> directly. However the <link
-linkend="vidioc-g-fmt">VIDIOC_G/S/TRY_FMT</link> ioctls, which take a
-pointer to a <link linkend="v4l2-format">v4l2_format</link> parent
-structure with padding bytes at the end, are not affected.</para>
- </listitem>
-
- <listitem>
- <para>The format of the <structfield>chromakey</structfield>
-field in &v4l2-window; changed from "host order RGB32" to a pixel
-value in the same format as the framebuffer. This may <emphasis>break
-compatibility</emphasis> with existing applications. Drivers
-supporting the "host order RGB32" format are not known.</para>
- </listitem>
-
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.24</title>
- <orderedlist>
- <listitem>
- <para>The pixel formats
-<constant>V4L2_PIX_FMT_PAL8</constant>,
-<constant>V4L2_PIX_FMT_YUV444</constant>,
-<constant>V4L2_PIX_FMT_YUV555</constant>,
-<constant>V4L2_PIX_FMT_YUV565</constant> and
-<constant>V4L2_PIX_FMT_YUV32</constant> were added.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.25</title>
- <orderedlist>
- <listitem>
- <para>The pixel formats <link linkend="V4L2-PIX-FMT-Y16">
-<constant>V4L2_PIX_FMT_Y16</constant></link> and <link
-linkend="V4L2-PIX-FMT-SBGGR16">
-<constant>V4L2_PIX_FMT_SBGGR16</constant></link> were added.</para>
- </listitem>
- <listitem>
- <para>New <link linkend="control">controls</link>
-<constant>V4L2_CID_POWER_LINE_FREQUENCY</constant>,
-<constant>V4L2_CID_HUE_AUTO</constant>,
-<constant>V4L2_CID_WHITE_BALANCE_TEMPERATURE</constant>,
-<constant>V4L2_CID_SHARPNESS</constant> and
-<constant>V4L2_CID_BACKLIGHT_COMPENSATION</constant> were added. The
-controls <constant>V4L2_CID_BLACK_LEVEL</constant>,
-<constant>V4L2_CID_WHITENESS</constant>,
-<constant>V4L2_CID_HCENTER</constant> and
-<constant>V4L2_CID_VCENTER</constant> were deprecated.
-</para>
- </listitem>
- <listitem>
- <para>A <link linkend="camera-controls">Camera controls
-class</link> was added, with the new controls
-<constant>V4L2_CID_EXPOSURE_AUTO</constant>,
-<constant>V4L2_CID_EXPOSURE_ABSOLUTE</constant>,
-<constant>V4L2_CID_EXPOSURE_AUTO_PRIORITY</constant>,
-<constant>V4L2_CID_PAN_RELATIVE</constant>,
-<constant>V4L2_CID_TILT_RELATIVE</constant>,
-<constant>V4L2_CID_PAN_RESET</constant>,
-<constant>V4L2_CID_TILT_RESET</constant>,
-<constant>V4L2_CID_PAN_ABSOLUTE</constant>,
-<constant>V4L2_CID_TILT_ABSOLUTE</constant>,
-<constant>V4L2_CID_FOCUS_ABSOLUTE</constant>,
-<constant>V4L2_CID_FOCUS_RELATIVE</constant> and
-<constant>V4L2_CID_FOCUS_AUTO</constant>.</para>
- </listitem>
- <listitem>
- <para>The <constant>VIDIOC_G_MPEGCOMP</constant> and
-<constant>VIDIOC_S_MPEGCOMP</constant> ioctls, which were superseded
-by the <link linkend="extended-controls">extended controls</link>
-interface in Linux 2.6.18, where finally removed from the
-<filename>videodev2.h</filename> header file.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.26</title>
- <orderedlist>
- <listitem>
- <para>The pixel formats
-<constant>V4L2_PIX_FMT_Y16</constant> and
-<constant>V4L2_PIX_FMT_SBGGR16</constant> were added.</para>
- </listitem>
- <listitem>
- <para>Added user controls
-<constant>V4L2_CID_CHROMA_AGC</constant> and
-<constant>V4L2_CID_COLOR_KILLER</constant>.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.27</title>
- <orderedlist>
- <listitem>
- <para>The &VIDIOC-S-HW-FREQ-SEEK; ioctl and the
-<constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability were added.</para>
- </listitem>
- <listitem>
- <para>The pixel formats
-<constant>V4L2_PIX_FMT_YVYU</constant>,
-<constant>V4L2_PIX_FMT_PCA501</constant>,
-<constant>V4L2_PIX_FMT_PCA505</constant>,
-<constant>V4L2_PIX_FMT_PCA508</constant>,
-<constant>V4L2_PIX_FMT_PCA561</constant>,
-<constant>V4L2_PIX_FMT_SGBRG8</constant>,
-<constant>V4L2_PIX_FMT_PAC207</constant> and
-<constant>V4L2_PIX_FMT_PJPG</constant> were added.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.28</title>
- <orderedlist>
- <listitem>
- <para>Added <constant>V4L2_MPEG_AUDIO_ENCODING_AAC</constant> and
-<constant>V4L2_MPEG_AUDIO_ENCODING_AC3</constant> MPEG audio encodings.</para>
- </listitem>
- <listitem>
- <para>Added <constant>V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC</constant> MPEG
-video encoding.</para>
- </listitem>
- <listitem>
- <para>The pixel formats
-<constant>V4L2_PIX_FMT_SGRBG10</constant> and
-<constant>V4L2_PIX_FMT_SGRBG10DPCM8</constant> were added.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 2.6.29</title>
- <orderedlist>
- <listitem>
- <para>The <constant>VIDIOC_G_CHIP_IDENT</constant> ioctl was renamed
-to <constant>VIDIOC_G_CHIP_IDENT_OLD</constant> and <constant>VIDIOC_DBG_G_CHIP_IDENT</constant>
-was introduced in its place. The old struct <structname>v4l2_chip_ident</structname>
-was renamed to <structname id="v4l2-chip-ident-old">v4l2_chip_ident_old</structname>.</para>
- </listitem>
- <listitem>
- <para>The pixel formats
-<constant>V4L2_PIX_FMT_VYUY</constant>,
-<constant>V4L2_PIX_FMT_NV16</constant> and
-<constant>V4L2_PIX_FMT_NV61</constant> were added.</para>
- </listitem>
- <listitem>
- <para>Added camera controls
-<constant>V4L2_CID_ZOOM_ABSOLUTE</constant>,
-<constant>V4L2_CID_ZOOM_RELATIVE</constant>,
-<constant>V4L2_CID_ZOOM_CONTINUOUS</constant> and
-<constant>V4L2_CID_PRIVACY</constant>.</para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.30</title>
- <orderedlist>
- <listitem>
- <para>New control flag <constant>V4L2_CTRL_FLAG_WRITE_ONLY</constant> was added.</para>
- </listitem>
- <listitem>
- <para>New control <constant>V4L2_CID_COLORFX</constant> was added.</para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.32</title>
- <orderedlist>
- <listitem>
- <para>In order to be easier to compare a V4L2 API and a kernel
-version, now V4L2 API is numbered using the Linux Kernel version numeration.</para>
- </listitem>
- <listitem>
- <para>Finalized the RDS capture API. See <xref linkend="rds" /> for
-more information.</para>
- </listitem>
- <listitem>
- <para>Added new capabilities for modulators and RDS encoders.</para>
- </listitem>
- <listitem>
- <para>Add description for libv4l API.</para>
- </listitem>
- <listitem>
- <para>Added support for string controls via new type <constant>V4L2_CTRL_TYPE_STRING</constant>.</para>
- </listitem>
- <listitem>
- <para>Added <constant>V4L2_CID_BAND_STOP_FILTER</constant> documentation.</para>
- </listitem>
- <listitem>
- <para>Added FM Modulator (FM TX) Extended Control Class: <constant>V4L2_CTRL_CLASS_FM_TX</constant> and their Control IDs.</para>
- </listitem>
-<listitem>
- <para>Added FM Receiver (FM RX) Extended Control Class: <constant>V4L2_CTRL_CLASS_FM_RX</constant> and their Control IDs.</para>
- </listitem>
- <listitem>
- <para>Added Remote Controller chapter, describing the default Remote Controller mapping for media devices.</para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.33</title>
- <orderedlist>
- <listitem>
- <para>Added support for Digital Video timings in order to support HDTV receivers and transmitters.</para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.34</title>
- <orderedlist>
- <listitem>
- <para>Added
-<constant>V4L2_CID_IRIS_ABSOLUTE</constant> and
-<constant>V4L2_CID_IRIS_RELATIVE</constant> controls to the
- <link linkend="camera-controls">Camera controls class</link>.
- </para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.37</title>
- <orderedlist>
- <listitem>
- <para>Remove the vtx (videotext/teletext) API. This API was no longer
-used and no hardware exists to verify the API. Nor were any userspace applications found
-that used it. It was originally scheduled for removal in 2.6.35.
- </para>
- </listitem>
- </orderedlist>
- </section>
- <section>
- <title>V4L2 in Linux 2.6.39</title>
- <orderedlist>
- <listitem>
- <para>The old VIDIOC_*_OLD symbols and V4L1 support were removed.</para>
- </listitem>
- <listitem>
- <para>Multi-planar API added. Does not affect the compatibility of
- current drivers and applications. See
- <link linkend="planar-apis">multi-planar API</link>
- for details.</para>
- </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>
- <title>V4L2 in Linux 3.2</title>
- <orderedlist>
- <listitem>
- <para>V4L2_CTRL_FLAG_VOLATILE was added to signal volatile controls to userspace.</para>
- </listitem>
- <listitem>
- <para>Add selection API for extended control over cropping
- and composing. Does not affect the compatibility of current
- drivers and applications. See <link
- linkend="selection-api"> selection API </link> for
- details.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.3</title>
- <orderedlist>
- <listitem>
- <para>Added <constant>V4L2_CID_ALPHA_COMPONENT</constant> control
- to the <link linkend="control">User controls class</link>.
- </para>
- </listitem>
- <listitem>
- <para>Added the device_caps field to struct v4l2_capabilities and added the new
- V4L2_CAP_DEVICE_CAPS capability.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.4</title>
- <orderedlist>
- <listitem>
- <para>Added <link linkend="jpeg-controls">JPEG compression control
- class</link>.</para>
- </listitem>
- <listitem>
- <para>Extended the DV Timings API:
- &VIDIOC-ENUM-DV-TIMINGS;, &VIDIOC-QUERY-DV-TIMINGS; and
- &VIDIOC-DV-TIMINGS-CAP;.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.5</title>
- <orderedlist>
- <listitem>
- <para>Added integer menus, the new type will be
- V4L2_CTRL_TYPE_INTEGER_MENU.</para>
- </listitem>
- <listitem>
- <para>Added selection API for V4L2 subdev interface:
- &VIDIOC-SUBDEV-G-SELECTION; and
- &VIDIOC-SUBDEV-S-SELECTION;.</para>
- </listitem>
- <listitem>
- <para> Added <constant>V4L2_COLORFX_ANTIQUE</constant>,
- <constant>V4L2_COLORFX_ART_FREEZE</constant>,
- <constant>V4L2_COLORFX_AQUA</constant>,
- <constant>V4L2_COLORFX_SILHOUETTE</constant>,
- <constant>V4L2_COLORFX_SOLARIZATION</constant>,
- <constant>V4L2_COLORFX_VIVID</constant> and
- <constant>V4L2_COLORFX_ARBITRARY_CBCR</constant> menu items
- to the <constant>V4L2_CID_COLORFX</constant> control.</para>
- </listitem>
- <listitem>
- <para> Added <constant>V4L2_CID_COLORFX_CBCR</constant> control.</para>
- </listitem>
- <listitem>
- <para> Added camera controls <constant>V4L2_CID_AUTO_EXPOSURE_BIAS</constant>,
- <constant>V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE</constant>,
- <constant>V4L2_CID_IMAGE_STABILIZATION</constant>,
- <constant>V4L2_CID_ISO_SENSITIVITY</constant>,
- <constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>,
- <constant>V4L2_CID_EXPOSURE_METERING</constant>,
- <constant>V4L2_CID_SCENE_MODE</constant>,
- <constant>V4L2_CID_3A_LOCK</constant>,
- <constant>V4L2_CID_AUTO_FOCUS_START</constant>,
- <constant>V4L2_CID_AUTO_FOCUS_STOP</constant>,
- <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant> and
- <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.6</title>
- <orderedlist>
- <listitem>
- <para>Replaced <structfield>input</structfield> in
- <structname>v4l2_buffer</structname> by
- <structfield>reserved2</structfield> and removed
- <constant>V4L2_BUF_FLAG_INPUT</constant>.</para>
- </listitem>
- <listitem>
- <para>Added V4L2_CAP_VIDEO_M2M and V4L2_CAP_VIDEO_M2M_MPLANE capabilities.</para>
- </listitem>
- <listitem>
- <para>Added support for frequency band enumerations: &VIDIOC-ENUM-FREQ-BANDS;.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.9</title>
- <orderedlist>
- <listitem>
- <para>Added timestamp types to
- <structfield>flags</structfield> field in
- <structname>v4l2_buffer</structname>. See <xref
- linkend="buffer-flags" />.</para>
- </listitem>
- <listitem>
- <para>Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control event
- changes flag. See <xref linkend="ctrl-changes-flags"/>.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.10</title>
- <orderedlist>
- <listitem>
- <para>Removed obsolete and unused DV_PRESET ioctls
- VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
- VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
- flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS.
- </para>
- </listitem>
- <listitem>
- <para>Added new debugging ioctl &VIDIOC-DBG-G-CHIP-INFO;.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.11</title>
- <orderedlist>
- <listitem>
- <para>Remove obsolete <constant>VIDIOC_DBG_G_CHIP_IDENT</constant> ioctl.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.14</title>
- <orderedlist>
- <listitem>
- <para> In struct <structname>v4l2_rect</structname>, the type
-of <structfield>width</structfield> and <structfield>height</structfield>
-fields changed from _s32 to _u32.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.15</title>
- <orderedlist>
- <listitem>
- <para>Added Software Defined Radio (SDR) Interface.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.16</title>
- <orderedlist>
- <listitem>
- <para>Added event V4L2_EVENT_SOURCE_CHANGE.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.17</title>
- <orderedlist>
- <listitem>
- <para>Extended &v4l2-pix-format;. Added format flags.
- </para>
- </listitem>
- <listitem>
- <para>Added compound control types and &VIDIOC-QUERY-EXT-CTRL;.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.18</title>
- <orderedlist>
- <listitem>
- <para>Added <constant>V4L2_CID_PAN_SPEED</constant> and
- <constant>V4L2_CID_TILT_SPEED</constant> camera controls.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 3.19</title>
- <orderedlist>
- <listitem>
- <para>Rewrote Colorspace chapter, added new &v4l2-ycbcr-encoding;
-and &v4l2-quantization; fields to &v4l2-pix-format;, &v4l2-pix-format-mplane;
-and &v4l2-mbus-framefmt;.
- </para>
- </listitem>
- </orderedlist>
- </section>
-
- <section>
- <title>V4L2 in Linux 4.4</title>
- <orderedlist>
- <listitem>
- <para>Renamed <constant>V4L2_TUNER_ADC</constant> to
-<constant>V4L2_TUNER_SDR</constant>. The use of
-<constant>V4L2_TUNER_ADC</constant> is deprecated now.
- </para>
- </listitem>
- <listitem>
- <para>Added <constant>V4L2_CID_RF_TUNER_RF_GAIN</constant>
-RF Tuner control.</para>
- </listitem>
- <listitem>
- <para>Added transmitter support for Software Defined Radio (SDR)
-Interface.</para>
- </listitem>
- </orderedlist>
- </section>
-
- <section id="other">
- <title>Relation of V4L2 to other Linux multimedia APIs</title>
-
- <section id="xvideo">
- <title>X Video Extension</title>
-
- <para>The X Video Extension (abbreviated XVideo or just Xv) is
-an extension of the X Window system, implemented for example by the
-XFree86 project. Its scope is similar to V4L2, an API to video capture
-and output devices for X clients. Xv allows applications to display
-live video in a window, send window contents to a TV output, and
-capture or output still images in XPixmaps<footnote>
- <para>This is not implemented in XFree86.</para>
- </footnote>. With their implementation XFree86 makes the
-extension available across many operating systems and
-architectures.</para>
-
- <para>Because the driver is embedded into the X server Xv has a
-number of advantages over the V4L2 <link linkend="overlay">video
-overlay interface</link>. The driver can easily determine the overlay
-target, &ie; visible graphics memory or off-screen buffers for a
-destructive overlay. It can program the RAMDAC for a non-destructive
-overlay, scaling or color-keying, or the clipping functions of the
-video capture hardware, always in sync with drawing operations or
-windows moving or changing their stacking order.</para>
-
- <para>To combine the advantages of Xv and V4L a special Xv
-driver exists in XFree86 and XOrg, just programming any overlay capable
-Video4Linux device it finds. To enable it
-<filename>/etc/X11/XF86Config</filename> must contain these lines:</para>
- <para><screen>
-Section "Module"
- Load "v4l"
-EndSection</screen></para>
-
- <para>As of XFree86 4.2 this driver still supports only V4L
-ioctls, however it should work just fine with all V4L2 devices through
-the V4L2 backward-compatibility layer. Since V4L2 permits multiple
-opens it is possible (if supported by the V4L2 driver) to capture
-video while an X client requested video overlay. Restrictions of
-simultaneous capturing and overlay are discussed in <xref
- linkend="overlay" /> apply.</para>
-
- <para>Only marginally related to V4L2, XFree86 extended Xv to
-support hardware YUV to RGB conversion and scaling for faster video
-playback, and added an interface to MPEG-2 decoding hardware. This API
-is useful to display images captured with V4L2 devices.</para>
- </section>
-
- <section>
- <title>Digital Video</title>
-
- <para>V4L2 does not support digital terrestrial, cable or
-satellite broadcast. A separate project aiming at digital receivers
-exists. You can find its homepage at <ulink
-url="https://linuxtv.org">https://linuxtv.org</ulink>. The Linux DVB API
-has no connection to the V4L2 API except that drivers for hybrid
-hardware may support both.</para>
- </section>
-
- <section>
- <title>Audio Interfaces</title>
-
- <para>[to do - OSS/ALSA]</para>
- </section>
- </section>
-
- <section id="experimental">
- <title>Experimental API Elements</title>
-
- <para>The following V4L2 API elements are currently experimental
-and may change in the future.</para>
-
- <itemizedlist>
- <listitem>
- <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER;
-ioctls.</para>
- </listitem>
- <listitem>
- <para>&VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section id="obsolete">
- <title>Obsolete API Elements</title>
-
- <para>The following V4L2 API elements were superseded by new
-interfaces and should not be implemented in new drivers.</para>
-
- <itemizedlist>
- <listitem>
- <para><constant>VIDIOC_G_MPEGCOMP</constant> and
-<constant>VIDIOC_S_MPEGCOMP</constant> ioctls. Use Extended Controls,
-<xref linkend="extended-controls" />.</para>
- </listitem>
- <listitem>
- <para>VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_ENUM_DV_PRESETS and
- VIDIOC_QUERY_DV_PRESET ioctls. Use the DV Timings API (<xref linkend="dv-timings" />).</para>
- </listitem>
- <listitem>
- <para><constant>VIDIOC_SUBDEV_G_CROP</constant> and
- <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctls. Use
- <constant>VIDIOC_SUBDEV_G_SELECTION</constant> and
- <constant>VIDIOC_SUBDEV_S_SELECTION</constant>, <xref
- linkend="vidioc-subdev-g-selection" />.</para>
- </listitem>
- </itemizedlist>
- </section>
- </section>
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
deleted file mode 100644
index e2e5484d2d9b..000000000000
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ /dev/null
@@ -1,5505 +0,0 @@
- <section id="control">
- <title>User Controls</title>
-
- <para>Devices typically have a number of user-settable controls
-such as brightness, saturation and so on, which would be presented to
-the user on a graphical user interface. But, different devices
-will have different controls available, and furthermore, the range of
-possible values, and the default value will vary from device to
-device. The control ioctls provide the information and a mechanism to
-create a nice user interface for these controls that will work
-correctly with any device.</para>
-
- <para>All controls are accessed using an ID value. V4L2 defines
-several IDs for specific purposes. Drivers can also implement their
-own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
-<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
-is problematic because different drivers may use the same
-<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
-This makes it hard to programatically set such controls since the meaning
-of the control with that ID is driver dependent. In order to resolve this
-drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
-IDs are mapped to those unique IDs by the kernel. Consider these
-<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
-IDs.</para>
-<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
-IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
-flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
-is still around.</para></footnote>
-and higher values. The pre-defined control IDs have the prefix
-<constant>V4L2_CID_</constant>, and are listed in <xref
-linkend="control-id" />. The ID is used when querying the attributes of
-a control, and when getting or setting the current value.</para>
-
- <para>Generally applications should present controls to the user
-without assumptions about their purpose. Each control comes with a
-name string the user is supposed to understand. When the purpose is
-non-intuitive the driver writer should provide a user manual, a user
-interface plug-in or a driver specific panel application. Predefined
-IDs were introduced to change a few controls programmatically, for
-example to mute a device during a channel switch.</para>
-
- <para>Drivers may enumerate different controls after switching
-the current video input or output, tuner or modulator, or audio input
-or output. Different in the sense of other bounds, another default and
-current value, step size or other menu items. A control with a certain
-<emphasis>custom</emphasis> ID can also change name and
-type.</para>
-
- <para>If a control is not applicable to the current configuration
-of the device (for example, it doesn't apply to the current video input)
-drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
-
- <para>Control values are stored globally, they do not
-change when switching except to stay within the reported bounds. They
-also do not change &eg; when the device is opened or closed, when the
-tuner radio frequency is changed or generally never without
-application request.</para>
-
- <para>V4L2 specifies an event mechanism to notify applications
-when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
-<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
-use of that in order to always reflect the correct control value.</para>
-
- <para>
- All controls use machine endianness.
- </para>
-
- <table pgwide="1" frame="none" id="control-id">
- <title>Control IDs</title>
- <tgroup cols="3">
- &cs-def;
- <thead>
- <row>
- <entry>ID</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CID_BASE</constant></entry>
- <entry></entry>
- <entry>First predefined ID, equal to
-<constant>V4L2_CID_BRIGHTNESS</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_USER_BASE</constant></entry>
- <entry></entry>
- <entry>Synonym of <constant>V4L2_CID_BASE</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_BRIGHTNESS</constant></entry>
- <entry>integer</entry>
- <entry>Picture brightness, or more precisely, the black
-level.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_CONTRAST</constant></entry>
- <entry>integer</entry>
- <entry>Picture contrast or luma gain.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_SATURATION</constant></entry>
- <entry>integer</entry>
- <entry>Picture color saturation or chroma gain.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_HUE</constant></entry>
- <entry>integer</entry>
- <entry>Hue or color balance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_VOLUME</constant></entry>
- <entry>integer</entry>
- <entry>Overall audio volume. Note some drivers also
-provide an OSS or ALSA mixer interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_BALANCE</constant></entry>
- <entry>integer</entry>
- <entry>Audio stereo balance. Minimum corresponds to all
-the way left, maximum to right.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_BASS</constant></entry>
- <entry>integer</entry>
- <entry>Audio bass adjustment.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_TREBLE</constant></entry>
- <entry>integer</entry>
- <entry>Audio treble adjustment.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_MUTE</constant></entry>
- <entry>boolean</entry>
- <entry>Mute audio, &ie; set the volume to zero, however
-without affecting <constant>V4L2_CID_AUDIO_VOLUME</constant>. Like
-ALSA drivers, V4L2 drivers must mute at load time to avoid excessive
-noise. Actually the entire device should be reset to a low power
-consumption state.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUDIO_LOUDNESS</constant></entry>
- <entry>boolean</entry>
- <entry>Loudness mode (bass boost).</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_BLACK_LEVEL</constant></entry>
- <entry>integer</entry>
- <entry>Another name for brightness (not a synonym of
-<constant>V4L2_CID_BRIGHTNESS</constant>). This control is deprecated
-and should not be used in new drivers and applications.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUTO_WHITE_BALANCE</constant></entry>
- <entry>boolean</entry>
- <entry>Automatic white balance (cameras).</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_DO_WHITE_BALANCE</constant></entry>
- <entry>button</entry>
- <entry>This is an action control. When set (the value is
-ignored), the device will do a white balance and then hold the current
-setting. Contrast this with the boolean
-<constant>V4L2_CID_AUTO_WHITE_BALANCE</constant>, which, when
-activated, keeps adjusting the white balance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_RED_BALANCE</constant></entry>
- <entry>integer</entry>
- <entry>Red chroma balance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_BLUE_BALANCE</constant></entry>
- <entry>integer</entry>
- <entry>Blue chroma balance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_GAMMA</constant></entry>
- <entry>integer</entry>
- <entry>Gamma adjust.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_WHITENESS</constant></entry>
- <entry>integer</entry>
- <entry>Whiteness for grey-scale devices. This is a synonym
-for <constant>V4L2_CID_GAMMA</constant>. This control is deprecated
-and should not be used in new drivers and applications.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_EXPOSURE</constant></entry>
- <entry>integer</entry>
- <entry>Exposure (cameras). [Unit?]</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUTOGAIN</constant></entry>
- <entry>boolean</entry>
- <entry>Automatic gain/exposure control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_GAIN</constant></entry>
- <entry>integer</entry>
- <entry>Gain control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_HFLIP</constant></entry>
- <entry>boolean</entry>
- <entry>Mirror the picture horizontally.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_VFLIP</constant></entry>
- <entry>boolean</entry>
- <entry>Mirror the picture vertically.</entry>
- </row>
- <row id="v4l2-power-line-frequency">
- <entry><constant>V4L2_CID_POWER_LINE_FREQUENCY</constant></entry>
- <entry>enum</entry>
- <entry>Enables a power line frequency filter to avoid
-flicker. Possible values for <constant>enum v4l2_power_line_frequency</constant> are:
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_DISABLED</constant> (0),
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_50HZ</constant> (1),
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_60HZ</constant> (2) and
-<constant>V4L2_CID_POWER_LINE_FREQUENCY_AUTO</constant> (3).</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_HUE_AUTO</constant></entry>
- <entry>boolean</entry>
- <entry>Enables automatic hue control by the device. The
-effect of setting <constant>V4L2_CID_HUE</constant> while automatic
-hue control is enabled is undefined, drivers should ignore such
-request.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_WHITE_BALANCE_TEMPERATURE</constant></entry>
- <entry>integer</entry>
- <entry>This control specifies the white balance settings
-as a color temperature in Kelvin. A driver should have a minimum of
-2800 (incandescent) to 6500 (daylight). For more information about
-color temperature see <ulink
-url="http://en.wikipedia.org/wiki/Color_temperature">Wikipedia</ulink>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_SHARPNESS</constant></entry>
- <entry>integer</entry>
- <entry>Adjusts the sharpness filters in a camera. The
-minimum value disables the filters, higher values give a sharper
-picture.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_BACKLIGHT_COMPENSATION</constant></entry>
- <entry>integer</entry>
- <entry>Adjusts the backlight compensation in a camera. The
-minimum value disables backlight compensation.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_CHROMA_AGC</constant></entry>
- <entry>boolean</entry>
- <entry>Chroma automatic gain control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_CHROMA_GAIN</constant></entry>
- <entry>integer</entry>
- <entry>Adjusts the Chroma gain control (for use when chroma AGC
- is disabled).</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_COLOR_KILLER</constant></entry>
- <entry>boolean</entry>
- <entry>Enable the color killer (&ie; force a black &amp; white image in case of a weak video signal).</entry>
- </row>
- <row id="v4l2-colorfx">
- <entry><constant>V4L2_CID_COLORFX</constant></entry>
- <entry>enum</entry>
- <entry>Selects a color effect. The following values are defined:
- </entry>
- </row><row>
- <entry></entry>
- <entry></entry>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_COLORFX_NONE</constant>&nbsp;</entry>
- <entry>Color effect is disabled.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_ANTIQUE</constant>&nbsp;</entry>
- <entry>An aging (old photo) effect.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_ART_FREEZE</constant>&nbsp;</entry>
- <entry>Frost color effect.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_AQUA</constant>&nbsp;</entry>
- <entry>Water color, cool tone.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_BW</constant>&nbsp;</entry>
- <entry>Black and white.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_EMBOSS</constant>&nbsp;</entry>
- <entry>Emboss, the highlights and shadows replace light/dark boundaries
- and low contrast areas are set to a gray background.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_GRASS_GREEN</constant>&nbsp;</entry>
- <entry>Grass green.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_NEGATIVE</constant>&nbsp;</entry>
- <entry>Negative.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SEPIA</constant>&nbsp;</entry>
- <entry>Sepia tone.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SKETCH</constant>&nbsp;</entry>
- <entry>Sketch.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SKIN_WHITEN</constant>&nbsp;</entry>
- <entry>Skin whiten.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SKY_BLUE</constant>&nbsp;</entry>
- <entry>Sky blue.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SOLARIZATION</constant>&nbsp;</entry>
- <entry>Solarization, the image is partially reversed in tone,
- only color values above or below a certain threshold are inverted.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SILHOUETTE</constant>&nbsp;</entry>
- <entry>Silhouette (outline).</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_VIVID</constant>&nbsp;</entry>
- <entry>Vivid colors.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORFX_SET_CBCR</constant>&nbsp;</entry>
- <entry>The Cb and Cr chroma components are replaced by fixed
- coefficients determined by <constant>V4L2_CID_COLORFX_CBCR</constant>
- control.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row>
- <entry><constant>V4L2_CID_COLORFX_CBCR</constant></entry>
- <entry>integer</entry>
- <entry>Determines the Cb and Cr coefficients for <constant>V4L2_COLORFX_SET_CBCR</constant>
- color effect. Bits [7:0] of the supplied 32 bit value are interpreted as
- Cr component, bits [15:8] as Cb component and bits [31:16] must be zero.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_AUTOBRIGHTNESS</constant></entry>
- <entry>boolean</entry>
- <entry>Enable Automatic Brightness.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_ROTATE</constant></entry>
- <entry>integer</entry>
- <entry>Rotates the image by specified angle. Common angles are 90,
- 270 and 180. Rotating the image to 90 and 270 will reverse the height
- and width of the display window. It is necessary to set the new height and
- width of the picture using the &VIDIOC-S-FMT; ioctl according to
- the rotation angle selected.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_BG_COLOR</constant></entry>
- <entry>integer</entry>
- <entry>Sets the background color on the current output device.
- Background color needs to be specified in the RGB24 format. The
- supplied 32 bit value is interpreted as bits 0-7 Red color information,
- bits 8-15 Green color information, bits 16-23 Blue color
- information and bits 24-31 must be zero.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_ILLUMINATORS_1</constant>
- <constant>V4L2_CID_ILLUMINATORS_2</constant></entry>
- <entry>boolean</entry>
- <entry>Switch on or off the illuminator 1 or 2 of the device
- (usually a microscope).</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 id="v4l2-alpha-component">
- <entry><constant>V4L2_CID_ALPHA_COMPONENT</constant></entry>
- <entry>integer</entry>
- <entry>Sets the alpha color component. When a capture device (or
- capture queue of a mem-to-mem device) produces a frame format that
- includes an alpha component
- (e.g. <link linkend="rgb-formats">packed RGB image formats</link>)
- and the alpha value is not defined by the device or the mem-to-mem
- input data this control lets you select the alpha component value of
- all pixels. When an output device (or output queue of a mem-to-mem
- device) consumes a frame format that doesn't include an alpha
- component and the device supports alpha channel processing this
- control lets you set the alpha component value of all pixels for
- further processing in the device.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_LASTP1</constant></entry>
- <entry></entry>
- <entry>End of the predefined control IDs (currently
- <constant>V4L2_CID_ALPHA_COMPONENT</constant> + 1).</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
- <entry></entry>
- <entry>ID of the first custom (driver specific) control.
-Applications depending on particular custom controls should check the
-driver name and version, see <xref linkend="querycap" />.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Applications can enumerate the available controls with the
-&VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls, get and set a
-control value with the &VIDIOC-G-CTRL; and &VIDIOC-S-CTRL; ioctls.
-Drivers must implement <constant>VIDIOC_QUERYCTRL</constant>,
-<constant>VIDIOC_G_CTRL</constant> and
-<constant>VIDIOC_S_CTRL</constant> when the device has one or more
-controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
-more menu type controls.</para>
-
- <example id="enum_all_controls">
- <title>Enumerating all user controls</title>
-
- <programlisting>
-&v4l2-queryctrl; queryctrl;
-&v4l2-querymenu; querymenu;
-
-static void enumerate_menu(void)
-{
- printf(" Menu items:\n");
-
- memset(&amp;querymenu, 0, sizeof(querymenu));
- querymenu.id = queryctrl.id;
-
- for (querymenu.index = queryctrl.minimum;
- querymenu.index &lt;= queryctrl.maximum;
- querymenu.index++) {
- if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
- printf(" %s\n", querymenu.name);
- }
- }
-}
-
-memset(&amp;queryctrl, 0, sizeof(queryctrl));
-
-for (queryctrl.id = V4L2_CID_BASE;
- queryctrl.id &lt; V4L2_CID_LASTP1;
- queryctrl.id++) {
- if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
- if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
- continue;
-
- printf("Control %s\n", queryctrl.name);
-
- if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu();
- } else {
- if (errno == EINVAL)
- continue;
-
- perror("VIDIOC_QUERYCTRL");
- exit(EXIT_FAILURE);
- }
-}
-
-for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
- queryctrl.id++) {
- if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
- if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
- continue;
-
- printf("Control %s\n", queryctrl.name);
-
- if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu();
- } else {
- if (errno == EINVAL)
- break;
-
- perror("VIDIOC_QUERYCTRL");
- exit(EXIT_FAILURE);
- }
-}
-</programlisting>
- </example>
-
- <example>
- <title>Enumerating all user controls (alternative)</title>
- <programlisting>
-memset(&amp;queryctrl, 0, sizeof(queryctrl));
-
-queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
- if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
- break;
- if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
- continue;
-
- printf("Control %s\n", queryctrl.name);
-
- if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu();
-
- queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-}
-if (errno != EINVAL) {
- perror("VIDIOC_QUERYCTRL");
- exit(EXIT_FAILURE);
-}
-</programlisting>
- </example>
-
- <example>
- <title>Changing controls</title>
-
- <programlisting>
-&v4l2-queryctrl; queryctrl;
-&v4l2-control; control;
-
-memset(&amp;queryctrl, 0, sizeof(queryctrl));
-queryctrl.id = V4L2_CID_BRIGHTNESS;
-
-if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
- if (errno != EINVAL) {
- perror("VIDIOC_QUERYCTRL");
- exit(EXIT_FAILURE);
- } else {
- printf("V4L2_CID_BRIGHTNESS is not supported\n");
- }
-} else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
- printf("V4L2_CID_BRIGHTNESS is not supported\n");
-} else {
- memset(&amp;control, 0, sizeof (control));
- control.id = V4L2_CID_BRIGHTNESS;
- control.value = queryctrl.default_value;
-
- if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
- perror("VIDIOC_S_CTRL");
- exit(EXIT_FAILURE);
- }
-}
-
-memset(&amp;control, 0, sizeof(control));
-control.id = V4L2_CID_CONTRAST;
-
-if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
- control.value += 1;
-
- /* The driver may clamp the value or return ERANGE, ignored here */
-
- if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
- &amp;&amp; errno != ERANGE) {
- perror("VIDIOC_S_CTRL");
- exit(EXIT_FAILURE);
- }
-/* Ignore if V4L2_CID_CONTRAST is unsupported */
-} else if (errno != EINVAL) {
- perror("VIDIOC_G_CTRL");
- exit(EXIT_FAILURE);
-}
-
-control.id = V4L2_CID_AUDIO_MUTE;
-control.value = 1; /* silence */
-
-/* Errors ignored */
-ioctl(fd, VIDIOC_S_CTRL, &amp;control);
-</programlisting>
- </example>
- </section>
-
- <section id="extended-controls">
- <title>Extended Controls</title>
-
- <section>
- <title>Introduction</title>
-
- <para>The control mechanism as originally designed was meant
-to be used for user settings (brightness, saturation, etc). However,
-it turned out to be a very useful model for implementing more
-complicated driver APIs where each driver implements only a subset of
-a larger API.</para>
-
- <para>The MPEG encoding API was the driving force behind
-designing and implementing this extended control mechanism: the MPEG
-standard is quite large and the currently supported hardware MPEG
-encoders each only implement a subset of this standard. Further more,
-many parameters relating to how the video is encoded into an MPEG
-stream are specific to the MPEG encoding chip since the MPEG standard
-only defines the format of the resulting MPEG stream, not how the
-video is actually encoded into that format.</para>
-
- <para>Unfortunately, the original control API lacked some
-features needed for these new uses and so it was extended into the
-(not terribly originally named) extended control API.</para>
-
- <para>Even though the MPEG encoding API was the first effort
-to use the Extended Control API, nowadays there are also other classes
-of Extended Controls, such as Camera Controls and FM Transmitter Controls.
-The Extended Controls API as well as all Extended Controls classes are
-described in the following text.</para>
- </section>
-
- <section>
- <title>The Extended Control API</title>
-
- <para>Three new ioctls are available: &VIDIOC-G-EXT-CTRLS;,
-&VIDIOC-S-EXT-CTRLS; and &VIDIOC-TRY-EXT-CTRLS;. These ioctls act on
-arrays of controls (as opposed to the &VIDIOC-G-CTRL; and
-&VIDIOC-S-CTRL; ioctls that act on a single control). This is needed
-since it is often required to atomically change several controls at
-once.</para>
-
- <para>Each of the new ioctls expects a pointer to a
-&v4l2-ext-controls;. This structure contains a pointer to the control
-array, a count of the number of controls in that array and a control
-class. Control classes are used to group similar controls into a
-single class. For example, control class
-<constant>V4L2_CTRL_CLASS_USER</constant> contains all user controls
-(&ie; all controls that can also be set using the old
-<constant>VIDIOC_S_CTRL</constant> ioctl). Control class
-<constant>V4L2_CTRL_CLASS_MPEG</constant> contains all controls
-relating to MPEG encoding, etc.</para>
-
- <para>All controls in the control array must belong to the
-specified control class. An error is returned if this is not the
-case.</para>
-
- <para>It is also possible to use an empty control array (count
-== 0) to check whether the specified control class is
-supported.</para>
-
- <para>The control array is a &v4l2-ext-control; array. The
-<structname>v4l2_ext_control</structname> structure is very similar to
-&v4l2-control;, except for the fact that it also allows for 64-bit
-values and pointers to be passed.</para>
-
- <para>Since the &v4l2-ext-control; supports pointers it is now
-also possible to have controls with compound types such as N-dimensional arrays
-and/or structures. You need to specify the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
-when enumerating controls to actually be able to see such compound controls.
-In other words, these controls with compound types should only be used
-programmatically.</para>
-
- <para>Since such compound controls need to expose more information
-about themselves than is possible with &VIDIOC-QUERYCTRL; the
-&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
-the dimensions of the N-dimensional array if this control consists of more than
-one element.</para>
-
- <para>It is important to realize that due to the flexibility of
-controls it is necessary to check whether the control you want to set
-actually is supported in the driver and what the valid range of values
-is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
-&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
-that some of the menu indices in a control of type
-<constant>V4L2_CTRL_TYPE_MENU</constant> 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>
- <title>Enumerating Extended Controls</title>
-
- <para>The recommended way to enumerate over the extended
-controls is by using &VIDIOC-QUERYCTRL; in combination with the
-<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> flag:</para>
-
- <informalexample>
- <programlisting>
-&v4l2-queryctrl; qctrl;
-
-qctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
- /* ... */
- qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-}
-</programlisting>
- </informalexample>
-
- <para>The initial control ID is set to 0 ORed with the
-<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> flag. The
-<constant>VIDIOC_QUERYCTRL</constant> ioctl will return the first
-control with a higher ID than the specified one. When no such controls
-are found an error is returned.</para>
-
- <para>If you want to get all controls within a specific control
-class, then you can set the initial
-<structfield>qctrl.id</structfield> value to the control class and add
-an extra check to break out of the loop when a control of another
-control class is found:</para>
-
- <informalexample>
- <programlisting>
-qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
- if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
- break;
- /* ... */
- qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-}
-</programlisting>
- </informalexample>
-
- <para>The 32-bit <structfield>qctrl.id</structfield> value is
-subdivided into three bit ranges: the top 4 bits are reserved for
-flags (&eg; <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>) and are not
-actually part of the ID. The remaining 28 bits form the control ID, of
-which the most significant 12 bits define the control class and the
-least significant 16 bits identify the control within the control
-class. It is guaranteed that these last 16 bits are always non-zero
-for controls. The range of 0x1000 and up are reserved for
-driver-specific controls. The macro
-<constant>V4L2_CTRL_ID2CLASS(id)</constant> returns the control class
-ID based on a control ID.</para>
-
- <para>If the driver does not support extended controls, then
-<constant>VIDIOC_QUERYCTRL</constant> will fail when used in
-combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
-that case the old method of enumerating control should be used (see
-<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
-all controls, including driver-private controls.</para>
- </section>
-
- <section>
- <title>Creating Control Panels</title>
-
- <para>It is possible to create control panels for a graphical
-user interface where the user can select the various controls.
-Basically you will have to iterate over all controls using the method
-described above. Each control class starts with a control of type
-<constant>V4L2_CTRL_TYPE_CTRL_CLASS</constant>.
-<constant>VIDIOC_QUERYCTRL</constant> will return the name of this
-control class which can be used as the title of a tab page within a
-control panel.</para>
-
- <para>The flags field of &v4l2-queryctrl; also contains hints on
-the behavior of the control. See the &VIDIOC-QUERYCTRL; documentation
-for more details.</para>
- </section>
-
- <section id="mpeg-controls">
- <title>Codec Control Reference</title>
-
- <para>Below all controls within the Codec control class are
-described. First the generic controls, then controls specific for
-certain hardware.</para>
-
- <para>Note: These controls are applicable to all codecs and
-not just MPEG. The defines are prefixed with V4L2_CID_MPEG/V4L2_MPEG
-as the controls were originally made for MPEG codecs and later
-extended to cover all encoding formats.</para>
-
- <section>
- <title>Generic Codec Controls</title>
-
- <table pgwide="1" frame="none" id="mpeg-control-id">
- <title>Codec 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_MPEG_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The Codec class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class. This description can be used as the
-caption of a Tab page in a GUI, for example.</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-stream-type">
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_TYPE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_stream_type</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. This control is specific to multiplexed MPEG streams.
-The currently defined stream types are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG2_PS</constant>&nbsp;</entry>
- <entry>MPEG-2 program stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG2_TS</constant>&nbsp;</entry>
- <entry>MPEG-2 transport stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG1_SS</constant>&nbsp;</entry>
- <entry>MPEG-1 system stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG2_DVD</constant>&nbsp;</entry>
- <entry>MPEG-2 DVD-compatible stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG1_VCD</constant>&nbsp;</entry>
- <entry>MPEG-1 VCD-compatible stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD</constant>&nbsp;</entry>
- <entry>MPEG-2 SVCD-compatible stream</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PID_PMT</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Program Map Table
-Packet ID for the MPEG transport stream (default 16)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PID_AUDIO</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Audio Packet ID for
-the MPEG transport stream (default 256)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PID_VIDEO</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Video Packet ID for
-the MPEG transport stream (default 260)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PID_PCR</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Packet ID for the
-MPEG transport stream carrying PCR fields (default 259)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PES_ID_AUDIO</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Audio ID for MPEG
-PES</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_PES_ID_VIDEO</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Video ID for MPEG
-PES</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-stream-vbi-fmt">
- <entry spanname="id"><constant>V4L2_CID_MPEG_STREAM_VBI_FMT</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_stream_vbi_fmt</entry>
- </row><row><entry spanname="descr">Some cards can embed
-VBI data (&eg; Closed Caption, Teletext) into the MPEG stream. This
-control selects whether VBI data should be embedded, and if so, what
-embedding method should be used. The list of possible VBI formats
-depends on the driver. The currently defined VBI format types
-are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_STREAM_VBI_FMT_NONE</constant>&nbsp;</entry>
- <entry>No VBI in the MPEG stream</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_STREAM_VBI_FMT_IVTV</constant>&nbsp;</entry>
- <entry>VBI in private packets, IVTV format (documented
-in the kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.vbi</filename>)</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-sampling-freq">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_sampling_freq</entry>
- </row><row><entry spanname="descr">MPEG Audio sampling
-frequency. Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100</constant>&nbsp;</entry>
- <entry>44.1 kHz</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000</constant>&nbsp;</entry>
- <entry>48 kHz</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000</constant>&nbsp;</entry>
- <entry>32 kHz</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-encoding">
- <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>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_ENCODING_LAYER_1</constant>&nbsp;</entry>
- <entry>MPEG-1/2 Layer I encoding</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_ENCODING_LAYER_2</constant>&nbsp;</entry>
- <entry>MPEG-1/2 Layer II encoding</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_ENCODING_LAYER_3</constant>&nbsp;</entry>
- <entry>MPEG-1/2 Layer III encoding</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_ENCODING_AAC</constant>&nbsp;</entry>
- <entry>MPEG-2/4 AAC (Advanced Audio Coding)</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_ENCODING_AC3</constant>&nbsp;</entry>
- <entry>AC-3 aka ATSC A/52 encoding</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-l1-bitrate">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_L1_BITRATE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_l1_bitrate</entry>
- </row><row><entry spanname="descr">MPEG-1/2 Layer I bitrate.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_32K</constant>&nbsp;</entry>
- <entry>32 kbit/s</entry></row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_64K</constant>&nbsp;</entry>
- <entry>64 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_96K</constant>&nbsp;</entry>
- <entry>96 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_128K</constant>&nbsp;</entry>
- <entry>128 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_160K</constant>&nbsp;</entry>
- <entry>160 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_192K</constant>&nbsp;</entry>
- <entry>192 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_224K</constant>&nbsp;</entry>
- <entry>224 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_256K</constant>&nbsp;</entry>
- <entry>256 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_288K</constant>&nbsp;</entry>
- <entry>288 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_320K</constant>&nbsp;</entry>
- <entry>320 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_352K</constant>&nbsp;</entry>
- <entry>352 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_384K</constant>&nbsp;</entry>
- <entry>384 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_416K</constant>&nbsp;</entry>
- <entry>416 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L1_BITRATE_448K</constant>&nbsp;</entry>
- <entry>448 kbit/s</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-l2-bitrate">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_L2_BITRATE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_l2_bitrate</entry>
- </row><row><entry spanname="descr">MPEG-1/2 Layer II bitrate.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_32K</constant>&nbsp;</entry>
- <entry>32 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_48K</constant>&nbsp;</entry>
- <entry>48 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_56K</constant>&nbsp;</entry>
- <entry>56 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_64K</constant>&nbsp;</entry>
- <entry>64 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_80K</constant>&nbsp;</entry>
- <entry>80 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_96K</constant>&nbsp;</entry>
- <entry>96 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_112K</constant>&nbsp;</entry>
- <entry>112 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_128K</constant>&nbsp;</entry>
- <entry>128 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_160K</constant>&nbsp;</entry>
- <entry>160 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_192K</constant>&nbsp;</entry>
- <entry>192 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_224K</constant>&nbsp;</entry>
- <entry>224 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_256K</constant>&nbsp;</entry>
- <entry>256 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_320K</constant>&nbsp;</entry>
- <entry>320 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L2_BITRATE_384K</constant>&nbsp;</entry>
- <entry>384 kbit/s</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-l3-bitrate">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_L3_BITRATE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_l3_bitrate</entry>
- </row><row><entry spanname="descr">MPEG-1/2 Layer III bitrate.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_32K</constant>&nbsp;</entry>
- <entry>32 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_40K</constant>&nbsp;</entry>
- <entry>40 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_48K</constant>&nbsp;</entry>
- <entry>48 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_56K</constant>&nbsp;</entry>
- <entry>56 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_64K</constant>&nbsp;</entry>
- <entry>64 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_80K</constant>&nbsp;</entry>
- <entry>80 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_96K</constant>&nbsp;</entry>
- <entry>96 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_112K</constant>&nbsp;</entry>
- <entry>112 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_128K</constant>&nbsp;</entry>
- <entry>128 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_160K</constant>&nbsp;</entry>
- <entry>160 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_192K</constant>&nbsp;</entry>
- <entry>192 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_224K</constant>&nbsp;</entry>
- <entry>224 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_256K</constant>&nbsp;</entry>
- <entry>256 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_L3_BITRATE_320K</constant>&nbsp;</entry>
- <entry>320 kbit/s</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_AAC_BITRATE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">AAC bitrate in bits per second.</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-ac3-bitrate">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_AC3_BITRATE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_ac3_bitrate</entry>
- </row><row><entry spanname="descr">AC-3 bitrate.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_32K</constant>&nbsp;</entry>
- <entry>32 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_40K</constant>&nbsp;</entry>
- <entry>40 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_48K</constant>&nbsp;</entry>
- <entry>48 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_56K</constant>&nbsp;</entry>
- <entry>56 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_64K</constant>&nbsp;</entry>
- <entry>64 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_80K</constant>&nbsp;</entry>
- <entry>80 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_96K</constant>&nbsp;</entry>
- <entry>96 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_112K</constant>&nbsp;</entry>
- <entry>112 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_128K</constant>&nbsp;</entry>
- <entry>128 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_160K</constant>&nbsp;</entry>
- <entry>160 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_192K</constant>&nbsp;</entry>
- <entry>192 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_224K</constant>&nbsp;</entry>
- <entry>224 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_256K</constant>&nbsp;</entry>
- <entry>256 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_320K</constant>&nbsp;</entry>
- <entry>320 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_384K</constant>&nbsp;</entry>
- <entry>384 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_448K</constant>&nbsp;</entry>
- <entry>448 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_512K</constant>&nbsp;</entry>
- <entry>512 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_576K</constant>&nbsp;</entry>
- <entry>576 kbit/s</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_AC3_BITRATE_640K</constant>&nbsp;</entry>
- <entry>640 kbit/s</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_mode</entry>
- </row><row><entry spanname="descr">MPEG Audio mode.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_STEREO</constant>&nbsp;</entry>
- <entry>Stereo</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_JOINT_STEREO</constant>&nbsp;</entry>
- <entry>Joint Stereo</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_DUAL</constant>&nbsp;</entry>
- <entry>Bilingual</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_MONO</constant>&nbsp;</entry>
- <entry>Mono</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-mode-extension">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_MODE_EXTENSION</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_mode_extension</entry>
- </row><row><entry spanname="descr">Joint Stereo
-audio mode extension. In Layer I and II they indicate which subbands
-are in intensity stereo. All other subbands are coded in stereo. Layer
-III is not (yet) supported. Possible values
-are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4</constant>&nbsp;</entry>
- <entry>Subbands 4-31 in intensity stereo</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8</constant>&nbsp;</entry>
- <entry>Subbands 8-31 in intensity stereo</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12</constant>&nbsp;</entry>
- <entry>Subbands 12-31 in intensity stereo</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16</constant>&nbsp;</entry>
- <entry>Subbands 16-31 in intensity stereo</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-emphasis">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_EMPHASIS</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_emphasis</entry>
- </row><row><entry spanname="descr">Audio Emphasis.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_EMPHASIS_NONE</constant>&nbsp;</entry>
- <entry>None</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS</constant>&nbsp;</entry>
- <entry>50/15 microsecond emphasis</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17</constant>&nbsp;</entry>
- <entry>CCITT J.17</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-crc">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_CRC</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_crc</entry>
- </row><row><entry spanname="descr">CRC method. Possible
-values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_CRC_NONE</constant>&nbsp;</entry>
- <entry>None</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_CRC_CRC16</constant>&nbsp;</entry>
- <entry>16 bit parity check</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_MUTE</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Mutes the audio when
-capturing. This is not done by muting audio hardware, which can still
-produce a slight hiss, but in the encoder itself, guaranteeing a fixed
-and reproducible audio bitstream. 0 = unmuted, 1 = muted.</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-dec-playback">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_dec_playback</entry>
- </row><row><entry spanname="descr">Determines how monolingual audio should be played back.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO</constant>&nbsp;</entry>
- <entry>Automatically determines the best playback mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO</constant>&nbsp;</entry>
- <entry>Stereo playback.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT</constant>&nbsp;</entry>
- <entry>Left channel playback.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT</constant>&nbsp;</entry>
- <entry>Right channel playback.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO</constant>&nbsp;</entry>
- <entry>Mono playback.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO</constant>&nbsp;</entry>
- <entry>Stereo playback with swapped left and right channels.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-audio-dec-multilingual-playback">
- <entry spanname="id"><constant>V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_audio_dec_playback</entry>
- </row><row><entry spanname="descr">Determines how multilingual audio should be played back.</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-encoding">
- <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. This control is specific to multiplexed MPEG streams.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ENCODING_MPEG_1</constant>&nbsp;</entry>
- <entry>MPEG-1 Video encoding</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ENCODING_MPEG_2</constant>&nbsp;</entry>
- <entry>MPEG-2 Video encoding</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC</constant>&nbsp;</entry>
- <entry>MPEG-4 AVC (H.264) Video encoding</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-aspect">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_ASPECT</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_aspect</entry>
- </row><row><entry spanname="descr">Video aspect.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ASPECT_1x1</constant>&nbsp;</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ASPECT_4x3</constant>&nbsp;</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ASPECT_16x9</constant>&nbsp;</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_ASPECT_221x100</constant>&nbsp;</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_B_FRAMES</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Number of B-Frames
-(default 2)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_GOP_SIZE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">GOP size (default
-12)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_GOP_CLOSURE</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">GOP closure (default
-1)</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_PULLDOWN</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Enable 3:2 pulldown
-(default 0)</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-bitrate-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_BITRATE_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_bitrate_mode</entry>
- </row><row><entry spanname="descr">Video bitrate mode.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_BITRATE_MODE_VBR</constant>&nbsp;</entry>
- <entry>Variable bitrate</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_BITRATE_MODE_CBR</constant>&nbsp;</entry>
- <entry>Constant bitrate</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_BITRATE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Video bitrate in bits
-per second.</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_BITRATE_PEAK</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Peak video bitrate in
-bits per second. Must be larger or equal to the average video bitrate.
-It is ignored if the video bitrate mode is set to constant
-bitrate.</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">For every captured
-frame, skip this many subsequent frames (default 0).</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MUTE</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">"Mutes" the video to a
-fixed color when capturing. This is useful for testing, to produce a
-fixed video bitstream. 0 = unmuted, 1 = muted.</entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MUTE_YUV</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Sets the "mute" color
-of the video. 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 id="v4l2-mpeg-video-dec-pts">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DEC_PTS</constant>&nbsp;</entry>
- <entry>integer64</entry>
- </row><row><entry spanname="descr">This read-only control returns the
-33-bit video Presentation Time Stamp as defined in ITU T-REC-H.222.0 and ISO/IEC 13818-1 of
-the currently displayed frame. This is the same PTS as is used in &VIDIOC-DECODER-CMD;.</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-dec-frame">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_DEC_FRAME</constant>&nbsp;</entry>
- <entry>integer64</entry>
- </row><row><entry spanname="descr">This read-only control returns the
-frame counter of the frame that is currently displayed (decoded). This value is reset to 0 whenever
-the decoder is started.</entry>
- </row>
-
- <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>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <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-video-h264-vui-sar-idc">
- <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_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_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>
- <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 id="v4l2-mpeg-video-h264-level">
- <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_VIDEO_H264_LEVEL_1_0</constant>&nbsp;</entry>
- <entry>Level 1.0</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1B</constant>&nbsp;</entry>
- <entry>Level 1B</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_1</constant>&nbsp;</entry>
- <entry>Level 1.1</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_LEVEL_1_2</constant>&nbsp;</entry>
- <entry>Level 1.2</entry>
- </row>
- <row>
- <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="v4l2-mpeg-video-mpeg4-level">
- <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_VIDEO_LEVEL_0</constant>&nbsp;</entry>
- <entry>Level 0</entry>
- </row>
- <row>
- <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-video-h264-profile">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_PROFILE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_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_VIDEO_H264_PROFILE_BASELINE</constant>&nbsp;</entry>
- <entry>Baseline profile</entry>
- </row>
- <row>
- <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 id="v4l2-mpeg-video-mpeg4-profile">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_mpeg4_profile</entry>
- </row>
- <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_VIDEO_PROFILE_SIMPLE</constant>&nbsp;</entry>
- <entry>Simple profile</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_PROFILE_ADVANCED_SIMPLE</constant>&nbsp;</entry>
- <entry>Advanced Simple profile</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_PROFILE_CORE</constant>&nbsp;</entry>
- <entry>Core profile</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_PROFILE_SIMPLE_SCALABLE</constant>&nbsp;</entry>
- <entry>Simple Scalable profile</entry>
- </row>
- <row>
- <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_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 id="v4l2-mpeg-video-multi-slice-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_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>
- <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_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_VIDEO_MULTI_SLICE_MAX_BYTES</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <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>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-h264-loop-filter-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_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 id="v4l2-mpeg-video-h264-entropy-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_h264_entropy_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 successive 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 successfully 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 id="v4l2-mpeg-video-vbv-delay">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VBV_DELAY</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Sets the initial delay in milliseconds for
-VBV buffer control.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-hor-search-range">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Horizontal search range defines maximum horizontal search area in pixels
-to search and match for the present Macroblock (MB) in the reference picture. This V4L2 control macro is used to set
-horizontal search range for motion estimation module in video encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-vert-search-range">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Vertical search range defines maximum vertical search area in pixels
-to search and match for the present Macroblock (MB) in the reference picture. This V4L2 control macro is used to set
-vertical search range for motion estimation module in video encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-force-key-frame">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME</constant>&nbsp;</entry>
- <entry>button</entry>
- </row><row><entry spanname="descr">Force a key frame for the next queued buffer. Applicable to encoders.
-This is a general, codec-agnostic keyframe control.</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 successfully 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 id="v4l2-mpeg-video-header-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_HEADER_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_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_REPEAT_SEQ_HEADER</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Repeat the video sequence headers. Repeating these
-headers makes random access to the video stream easier. Applicable to the MPEG1, 2 and 4 encoder.</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>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enable generation of frame packing supplemental enhancement information in the encoded bitstream.
-The frame packing SEI message contains the arrangement of L and R planes for 3D viewing. Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Sets current frame as frame0 in frame packing SEI.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-h264-sei-fp-arrangement-type">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_h264_sei_fp_arrangement_type</entry>
- </row>
- <row><entry spanname="descr">Frame packing arrangement type for H264 SEI.
-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_SEI_FP_ARRANGEMENT_TYPE_CHEKERBOARD</constant>&nbsp;</entry>
- <entry>Pixels are alternatively from L and R.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_COLUMN</constant>&nbsp;</entry>
- <entry>L and R are interlaced by column.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_ROW</constant>&nbsp;</entry>
- <entry>L and R are interlaced by row.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE</constant>&nbsp;</entry>
- <entry>L is on the left, R on the right.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TOP_BOTTOM</constant>&nbsp;</entry>
- <entry>L is on top, R on bottom.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL</constant>&nbsp;</entry>
- <entry>One view per frame.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables flexible macroblock ordering in the encoded bitstream. It is a technique
-used for restructuring the ordering of macroblocks in pictures. Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-h264-fmo-map-type">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_map_type</entry>
- </row>
- <row><entry spanname="descr">When using FMO, the map type divides the image in different scan patterns of macroblocks.
-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_FMO_MAP_TYPE_INTERLEAVED_SLICES</constant>&nbsp;</entry>
- <entry>Slices are interleaved one after other with macroblocks in run length order.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES</constant>&nbsp;</entry>
- <entry>Scatters the macroblocks based on a mathematical function known to both encoder and decoder.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_FOREGROUND_WITH_LEFT_OVER</constant>&nbsp;</entry>
- <entry>Macroblocks arranged in rectangular areas or regions of interest.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_BOX_OUT</constant>&nbsp;</entry>
- <entry>Slice groups grow in a cyclic way from centre to outwards.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN</constant>&nbsp;</entry>
- <entry>Slice groups grow in raster scan pattern from left to right.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN</constant>&nbsp;</entry>
- <entry>Slice groups grow in wipe scan pattern from top to bottom.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_EXPLICIT</constant>&nbsp;</entry>
- <entry>User defined map type.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Number of slice groups in FMO.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-h264-fmo-change-direction">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_h264_fmo_change_dir</entry>
- </row>
- <row><entry spanname="descr">Specifies a direction of the slice group change for raster and wipe maps.
-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_FMO_CHANGE_DIR_RIGHT</constant>&nbsp;</entry>
- <entry>Raster scan or wipe right.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT</constant>&nbsp;</entry>
- <entry>Reverse raster scan or wipe left.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Specifies the size of the first slice group for raster and wipe map.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Specifies the number of consecutive macroblocks for the interleaved map.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables arbitrary slice ordering in encoded bitstream.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Specifies the slice order in ASO. Applicable to the H264 encoder.
-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:15</entry>
- <entry>Slice ID</entry>
- </row>
- <row>
- <entry>Bit 16:32</entry>
- <entry>Slice position or order</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables H264 hierarchical coding.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-mpeg-video-h264-hierarchical-coding-type">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_video_h264_hierarchical_coding_type</entry>
- </row>
- <row><entry spanname="descr">Specifies the hierarchical coding type.
-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_HIERARCHICAL_CODING_B</constant>&nbsp;</entry>
- <entry>Hierarchical B coding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P</constant>&nbsp;</entry>
- <entry>Hierarchical P coding.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Specifies the number of hierarchical coding layers.
-Applicable to the H264 encoder.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Specifies a user defined QP for each layer. Applicable to the H264 encoder.
-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:15</entry>
- <entry>QP value</entry>
- </row>
- <row>
- <entry>Bit 16:32</entry>
- <entry>Layer number</entry>
- </row>
- </tbody>
- </entrytbl>
- </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>boolean</entry>
- </row><row><entry spanname="descr">If the display delay is enabled then the decoder is forced to return a
-CAPTURE buffer (decoded frame) after processing a certain number of OUTPUT buffers. The delay can be set through
-<constant>V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY</constant>. 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 id="v4l2-mpeg-mfc51-video-frame-skip-mode">
- <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_mfc51_video_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 constraints. Applicable to encoders.
-</entry>
- </row>
- <row><entry></entry></row>
- <row id="v4l2-mpeg-mfc51-video-force-frame-type">
- <entry spanname="id"><constant>V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_mpeg_mfc51_video_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>
-
- <section>
- <title>VPX Control Reference</title>
-
- <para>The VPX controls include controls for encoding parameters
- of VPx video codec.</para>
-
- <table pgwide="1" frame="none" id="vpx-control-id">
- <title>VPX 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></entry></row>
- <row id="v4l2-vpx-num-partitions">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS</constant></entry>
- <entry>enum v4l2_vp8_num_partitions</entry>
- </row>
- <row><entry spanname="descr">The number of token partitions to use in VP8 encoder.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION</constant></entry>
- <entry>1 coefficient partition</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS</constant></entry>
- <entry>2 coefficient partitions</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS</constant></entry>
- <entry>4 coefficient partitions</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS</constant></entry>
- <entry>8 coefficient partitions</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4</constant></entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Setting this prevents intra 4x4 mode in the intra mode decision.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-vpx-num-ref-frames">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES</constant></entry>
- <entry>enum v4l2_vp8_num_ref_frames</entry>
- </row>
- <row><entry spanname="descr">The number of reference pictures for encoding P frames.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME</constant></entry>
- <entry>Last encoded frame will be searched</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME</constant></entry>
- <entry>Two frames will be searched among the last encoded frame, the golden frame
-and the alternate reference (altref) frame. The encoder implementation will decide which two are chosen.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_3_REF_FRAME</constant></entry>
- <entry>The last encoded frame, the golden frame and the altref frame will be searched.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL</constant></entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Indicates the loop filter level. The adjustment of the loop
-filter level is done via a delta value against a baseline loop filter value.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS</constant></entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">This parameter affects the loop filter. Anything above
-zero weakens the deblocking effect on the loop filter.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD</constant></entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the refresh period for the golden frame. The period is defined
-in number of frames. For a value of 'n', every nth frame starting from the first key frame will be taken as a golden frame.
-For eg. for encoding sequence of 0, 1, 2, 3, 4, 5, 6, 7 where the golden frame refresh period is set as 4, the frames
-0, 4, 8 etc will be taken as the golden frames as frame 0 is always a key frame.</entry>
- </row>
-
- <row><entry></entry></row>
- <row id="v4l2-vpx-golden-frame-sel">
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL</constant></entry>
- <entry>enum v4l2_vp8_golden_frame_sel</entry>
- </row>
- <row><entry spanname="descr">Selects the golden frame for encoding.
-Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV</constant></entry>
- <entry>Use the (n-2)th frame as a golden frame, current frame index being 'n'.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD</constant></entry>
- <entry>Use the previous specific frame indicated by
-V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD as a golden frame.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_MIN_QP</constant></entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Minimum quantization parameter for VP8.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_MAX_QP</constant></entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Maximum quantization parameter for VP8.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Quantization parameter for an I frame for VP8.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Quantization parameter for a P frame for VP8.</entry>
- </row>
-
- <row><entry></entry></row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_MPEG_VIDEO_VPX_PROFILE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Select the desired profile for VPx encoder.
-Acceptable values are 0, 1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.</entry>
- </row>
-
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
- </section>
-
- <section id="camera-controls">
- <title>Camera Control Reference</title>
-
- <para>The Camera class includes controls for mechanical (or
-equivalent digital) features of a device such as controllable lenses
-or sensors.</para>
-
- <table pgwide="1" frame="none" id="camera-control-id">
- <title>Camera 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_CAMERA_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The Camera class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class.</entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-exposure-auto-type">
- <entry spanname="id"><constant>V4L2_CID_EXPOSURE_AUTO</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_exposure_auto_type</entry>
- </row><row><entry spanname="descr">Enables automatic
-adjustments of the exposure time and/or iris aperture. The effect of
-manual changes of the exposure time or iris aperture while these
-features are enabled is undefined, drivers should ignore such
-requests. Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_EXPOSURE_AUTO</constant>&nbsp;</entry>
- <entry>Automatic exposure time, automatic iris
-aperture.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_MANUAL</constant>&nbsp;</entry>
- <entry>Manual exposure time, manual iris.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_SHUTTER_PRIORITY</constant>&nbsp;</entry>
- <entry>Manual exposure time, auto iris.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_APERTURE_PRIORITY</constant>&nbsp;</entry>
- <entry>Auto exposure time, manual iris.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_EXPOSURE_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Determines the exposure
-time of the camera sensor. The exposure time is limited by the frame
-interval. Drivers should interpret the values as 100 &micro;s units,
-where the value 1 stands for 1/10000th of a second, 10000 for 1 second
-and 100000 for 10 seconds.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_EXPOSURE_AUTO_PRIORITY</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">When
-<constant>V4L2_CID_EXPOSURE_AUTO</constant> is set to
-<constant>AUTO</constant> or <constant>APERTURE_PRIORITY</constant>,
-this control determines if the device may dynamically vary the frame
-rate. By default this feature is disabled (0) and the frame rate must
-remain constant.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_EXPOSURE_BIAS</constant>&nbsp;</entry>
- <entry>integer menu</entry>
- </row><row><entry spanname="descr"> Determines the automatic
-exposure compensation, it is effective only when <constant>V4L2_CID_EXPOSURE_AUTO</constant>
-control is set to <constant>AUTO</constant>, <constant>SHUTTER_PRIORITY </constant>
-or <constant>APERTURE_PRIORITY</constant>.
-It is expressed in terms of EV, drivers should interpret the values as 0.001 EV
-units, where the value 1000 stands for +1 EV.
-<para>Increasing the exposure compensation value is equivalent to decreasing
-the exposure value (EV) and will increase the amount of light at the image
-sensor. The camera performs the exposure compensation by adjusting absolute
-exposure time and/or aperture.</para></entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-exposure-metering">
- <entry spanname="id"><constant>V4L2_CID_EXPOSURE_METERING</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_exposure_metering</entry>
- </row><row><entry spanname="descr">Determines how the camera measures
-the amount of light available for the frame exposure. Possible values are:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_EXPOSURE_METERING_AVERAGE</constant>&nbsp;</entry>
- <entry>Use the light information coming from the entire frame
-and average giving no weighting to any particular portion of the metered area.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_METERING_CENTER_WEIGHTED</constant>&nbsp;</entry>
- <entry>Average the light information coming from the entire frame
-giving priority to the center of the metered area.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_METERING_SPOT</constant>&nbsp;</entry>
- <entry>Measure only very small area at the center of the frame.</entry>
- </row>
- <row>
- <entry><constant>V4L2_EXPOSURE_METERING_MATRIX</constant>&nbsp;</entry>
- <entry>A multi-zone metering. The light intensity is measured
-in several points of the frame and the results are combined. The
-algorithm of the zones selection and their significance in calculating the
-final value is device dependent.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_PAN_RELATIVE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control turns the
-camera horizontally by the specified amount. The unit is undefined. A
-positive value moves the camera to the right (clockwise when viewed
-from above), a negative value to the left. A value of zero does not
-cause motion. This is a write-only control.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_TILT_RELATIVE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control turns the
-camera vertically by the specified amount. The unit is undefined. A
-positive value moves the camera up, a negative value down. A value of
-zero does not cause motion. This is a write-only control.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_PAN_RESET</constant>&nbsp;</entry>
- <entry>button</entry>
- </row><row><entry spanname="descr">When this control is set,
-the camera moves horizontally to the default position.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_TILT_RESET</constant>&nbsp;</entry>
- <entry>button</entry>
- </row><row><entry spanname="descr">When this control is set,
-the camera moves vertically to the default position.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_PAN_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control
-turns the camera horizontally to the specified position. Positive
-values move the camera to the right (clockwise when viewed from above),
-negative values to the left. Drivers should interpret the values as arc
-seconds, with valid values between -180 * 3600 and +180 * 3600
-inclusive.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_TILT_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control
-turns the camera vertically to the specified position. Positive values
-move the camera up, negative values down. Drivers should interpret the
-values as arc seconds, with valid values between -180 * 3600 and +180
-* 3600 inclusive.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_FOCUS_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control sets the
-focal point of the camera to the specified position. The unit is
-undefined. Positive values set the focus closer to the camera,
-negative values towards infinity.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_FOCUS_RELATIVE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control moves the
-focal point of the camera by the specified amount. The unit is
-undefined. Positive values move the focus closer to the camera,
-negative values towards infinity. This is a write-only control.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_FOCUS_AUTO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Enables continuous automatic
-focus adjustments. The effect of manual focus adjustments while this feature
-is enabled is undefined, drivers should ignore such requests.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_START</constant>&nbsp;</entry>
- <entry>button</entry>
- </row><row><entry spanname="descr">Starts single auto focus process.
-The effect of setting this control when <constant>V4L2_CID_FOCUS_AUTO</constant>
-is set to <constant>TRUE</constant> (1) is undefined, drivers should ignore
-such requests.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUTO_FOCUS_STOP</constant>&nbsp;</entry>
- <entry>button</entry>
- </row><row><entry spanname="descr">Aborts automatic focusing
-started with <constant>V4L2_CID_AUTO_FOCUS_START</constant> control. It is
-effective only when the continuous autofocus is disabled, that is when
-<constant>V4L2_CID_FOCUS_AUTO</constant> control is set to <constant>FALSE
-</constant> (0).</entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-auto-focus-status">
- <entry spanname="id">
- <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>&nbsp;</entry>
- <entry>bitmask</entry>
- </row>
- <row><entry spanname="descr">The automatic focus status. This is a read-only
- control.</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_STATUS_IDLE</constant>&nbsp;</entry>
- <entry>Automatic focus is not active.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_STATUS_BUSY</constant>&nbsp;</entry>
- <entry>Automatic focusing is in progress.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_STATUS_REACHED</constant>&nbsp;</entry>
- <entry>Focus has been reached.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_STATUS_FAILED</constant>&nbsp;</entry>
- <entry>Automatic focus has failed, the driver will not
- transition from this state until another action is
- performed by an application.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry spanname="descr">
-Setting <constant>V4L2_LOCK_FOCUS</constant> lock bit of the <constant>V4L2_CID_3A_LOCK
-</constant> control may stop updates of the <constant>V4L2_CID_AUTO_FOCUS_STATUS</constant>
-control value.</entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-auto-focus-range">
- <entry spanname="id">
- <constant>V4L2_CID_AUTO_FOCUS_RANGE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_auto_focus_range</entry>
- </row>
- <row><entry spanname="descr">Determines auto focus distance range
-for which lens may be adjusted. </entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_RANGE_AUTO</constant>&nbsp;</entry>
- <entry>The camera automatically selects the focus range.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_RANGE_NORMAL</constant>&nbsp;</entry>
- <entry>Normal distance range, limited for best automatic focus
-performance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_RANGE_MACRO</constant>&nbsp;</entry>
- <entry>Macro (close-up) auto focus. The camera will
-use its minimum possible distance for auto focus.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUTO_FOCUS_RANGE_INFINITY</constant>&nbsp;</entry>
- <entry>The lens is set to focus on an object at infinite distance.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_ZOOM_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Specify the objective lens
-focal length as an absolute value. The zoom unit is driver-specific and its
-value should be a positive integer.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_ZOOM_RELATIVE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Specify the objective lens
-focal length relatively to the current value. Positive values move the zoom
-lens group towards the telephoto direction, negative values towards the
-wide-angle direction. The zoom unit is driver-specific. This is a write-only control.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_ZOOM_CONTINUOUS</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Move the objective lens group
-at the specified speed until it reaches physical device limits or until an
-explicit request to stop the movement. A positive value moves the zoom lens
-group towards the telephoto direction. A value of zero stops the zoom lens
-group movement. A negative value moves the zoom lens group towards the
-wide-angle direction. The zoom speed unit is driver-specific.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_IRIS_ABSOLUTE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control sets the
-camera's aperture to the specified value. The unit is undefined.
-Larger values open the iris wider, smaller values close it.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_IRIS_RELATIVE</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control modifies the
-camera's aperture by the specified amount. The unit is undefined.
-Positive values open the iris one step further, negative values close
-it one step further. This is a write-only control.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_PRIVACY</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Prevent video from being acquired
-by the camera. When this control is set to <constant>TRUE</constant> (1), no
-image can be captured by the camera. Common means to enforce privacy are
-mechanical obturation of the sensor and firmware image processing, but the
-device is not restricted to these methods. Devices that implement the privacy
-control must support read access and may support write access.</entry>
- </row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_BAND_STOP_FILTER</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">Switch the band-stop filter of a
-camera sensor on or off, or specify its strength. Such band-stop filters can
-be used, for example, to filter out the fluorescent light component.</entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-auto-n-preset-white-balance">
- <entry spanname="id"><constant>V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_auto_n_preset_white_balance</entry>
- </row><row><entry spanname="descr">Sets white balance to automatic,
-manual or a preset. The presets determine color temperature of the light as
-a hint to the camera for white balance adjustments resulting in most accurate
-color representation. The following white balance presets are listed in order
-of increasing color temperature.</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_MANUAL</constant>&nbsp;</entry>
- <entry>Manual white balance.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_AUTO</constant>&nbsp;</entry>
- <entry>Automatic white balance adjustments.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_INCANDESCENT</constant>&nbsp;</entry>
- <entry>White balance setting for incandescent (tungsten) lighting.
-It generally cools down the colors and corresponds approximately to 2500...3500 K
-color temperature range.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_FLUORESCENT</constant>&nbsp;</entry>
- <entry>White balance preset for fluorescent lighting.
-It corresponds approximately to 4000...5000 K color temperature.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_FLUORESCENT_H</constant>&nbsp;</entry>
- <entry>With this setting the camera will compensate for
-fluorescent H lighting.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_HORIZON</constant>&nbsp;</entry>
- <entry>White balance setting for horizon daylight.
-It corresponds approximately to 5000 K color temperature.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_DAYLIGHT</constant>&nbsp;</entry>
- <entry>White balance preset for daylight (with clear sky).
-It corresponds approximately to 5000...6500 K color temperature.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_FLASH</constant>&nbsp;</entry>
- <entry>With this setting the camera will compensate for the flash
-light. It slightly warms up the colors and corresponds roughly to 5000...5500 K
-color temperature.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_CLOUDY</constant>&nbsp;</entry>
- <entry>White balance preset for moderately overcast sky.
-This option corresponds approximately to 6500...8000 K color temperature
-range.</entry>
- </row>
- <row>
- <entry><constant>V4L2_WHITE_BALANCE_SHADE</constant>&nbsp;</entry>
- <entry>White balance preset for shade or heavily overcast
-sky. It corresponds approximately to 9000...10000 K color temperature.
-</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-wide-dynamic-range">
- <entry spanname="id"><constant>V4L2_CID_WIDE_DYNAMIC_RANGE</constant></entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables or disables the camera's wide dynamic
-range feature. This feature allows to obtain clear images in situations where
-intensity of the illumination varies significantly throughout the scene, i.e.
-there are simultaneously very dark and very bright areas. It is most commonly
-realized in cameras by combining two subsequent frames with different exposure
-times. <footnote id="ctypeconv"><para> This control may be changed to a menu
-control in the future, if more options are required.</para></footnote></entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-image-stabilization">
- <entry spanname="id"><constant>V4L2_CID_IMAGE_STABILIZATION</constant></entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables or disables image stabilization.
- <footnoteref linkend="ctypeconv"/></entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_ISO_SENSITIVITY</constant>&nbsp;</entry>
- <entry>integer menu</entry>
- </row><row><entry spanname="descr">Determines ISO equivalent of an
-image sensor indicating the sensor's sensitivity to light. The numbers are
-expressed in arithmetic scale, as per <xref linkend="iso12232" /> standard,
-where doubling the sensor sensitivity is represented by doubling the numerical
-ISO value. Applications should interpret the values as standard ISO values
-multiplied by 1000, e.g. control value 800 stands for ISO 0.8. Drivers will
-usually support only a subset of standard ISO values. The effect of setting
-this control while the <constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>
-control is set to a value other than <constant>V4L2_CID_ISO_SENSITIVITY_MANUAL
-</constant> is undefined, drivers should ignore such requests.</entry>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-iso-sensitivity-auto-type">
- <entry spanname="id"><constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_iso_sensitivity_type</entry>
- </row><row><entry spanname="descr">Enables or disables automatic ISO
-sensitivity adjustments.</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CID_ISO_SENSITIVITY_MANUAL</constant>&nbsp;</entry>
- <entry>Manual ISO sensitivity.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CID_ISO_SENSITIVITY_AUTO</constant>&nbsp;</entry>
- <entry>Automatic ISO sensitivity adjustments.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row id="v4l2-scene-mode">
- <entry spanname="id"><constant>V4L2_CID_SCENE_MODE</constant>&nbsp;</entry>
- <entry>enum&nbsp;v4l2_scene_mode</entry>
- </row><row><entry spanname="descr">This control allows to select
-scene programs as the camera automatic modes optimized for common shooting
-scenes. Within these modes the camera determines best exposure, aperture,
-focusing, light metering, white balance and equivalent sensitivity. The
-controls of those parameters are influenced by the scene mode control.
-An exact behavior in each mode is subject to the camera specification.
-
-<para>When the scene mode feature is not used, this control should be set to
-<constant>V4L2_SCENE_MODE_NONE</constant> to make sure the other possibly
-related controls are accessible. The following scene programs are defined:
-</para>
-</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_SCENE_MODE_NONE</constant>&nbsp;</entry>
- <entry>The scene mode feature is disabled.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_BACKLIGHT</constant>&nbsp;</entry>
- <entry>Backlight. Compensates for dark shadows when light is
- coming from behind a subject, also by automatically turning
- on the flash.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_BEACH_SNOW</constant>&nbsp;</entry>
- <entry>Beach and snow. This mode compensates for all-white or
-bright scenes, which tend to look gray and low contrast, when camera's automatic
-exposure is based on an average scene brightness. To compensate, this mode
-automatically slightly overexposes the frames. The white balance may also be
-adjusted to compensate for the fact that reflected snow looks bluish rather
-than white.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_CANDLELIGHT</constant>&nbsp;</entry>
- <entry>Candle light. The camera generally raises the ISO
-sensitivity and lowers the shutter speed. This mode compensates for relatively
-close subject in the scene. The flash is disabled in order to preserve the
-ambiance of the light.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_DAWN_DUSK</constant>&nbsp;</entry>
- <entry>Dawn and dusk. Preserves the colors seen in low
-natural light before dusk and after down. The camera may turn off the flash,
-and automatically focus at infinity. It will usually boost saturation and
-lower the shutter speed.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_FALL_COLORS</constant>&nbsp;</entry>
- <entry>Fall colors. Increases saturation and adjusts white
-balance for color enhancement. Pictures of autumn leaves get saturated reds
-and yellows.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_FIREWORKS</constant>&nbsp;</entry>
- <entry>Fireworks. Long exposure times are used to capture
-the expanding burst of light from a firework. The camera may invoke image
-stabilization.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_LANDSCAPE</constant>&nbsp;</entry>
- <entry>Landscape. The camera may choose a small aperture to
-provide deep depth of field and long exposure duration to help capture detail
-in dim light conditions. The focus is fixed at infinity. Suitable for distant
-and wide scenery.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_NIGHT</constant>&nbsp;</entry>
- <entry>Night, also known as Night Landscape. Designed for low
-light conditions, it preserves detail in the dark areas without blowing out bright
-objects. The camera generally sets itself to a medium-to-high ISO sensitivity,
-with a relatively long exposure time, and turns flash off. As such, there will be
-increased image noise and the possibility of blurred image.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_PARTY_INDOOR</constant>&nbsp;</entry>
- <entry>Party and indoor. Designed to capture indoor scenes
-that are lit by indoor background lighting as well as the flash. The camera
-usually increases ISO sensitivity, and adjusts exposure for the low light
-conditions.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_PORTRAIT</constant>&nbsp;</entry>
- <entry>Portrait. The camera adjusts the aperture so that the
-depth of field is reduced, which helps to isolate the subject against a smooth
-background. Most cameras recognize the presence of faces in the scene and focus
-on them. The color hue is adjusted to enhance skin tones. The intensity of the
-flash is often reduced.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_SPORTS</constant>&nbsp;</entry>
- <entry>Sports. Significantly increases ISO and uses a fast
-shutter speed to freeze motion of rapidly-moving subjects. Increased image
-noise may be seen in this mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_SUNSET</constant>&nbsp;</entry>
- <entry>Sunset. Preserves deep hues seen in sunsets and
-sunrises. It bumps up the saturation.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SCENE_MODE_TEXT</constant>&nbsp;</entry>
- <entry>Text. It applies extra contrast and sharpness, it is
-typically a black-and-white mode optimized for readability. Automatic focus
-may be switched to close-up mode and this setting may also involve some
-lens-distortion correction.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_3A_LOCK</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">This control locks or unlocks the automatic
-focus, exposure and white balance. The automatic adjustments can be paused
-independently by setting the corresponding lock bit to 1. The camera then retains
-the settings until the lock bit is cleared. The following lock bits are defined:
-</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_LOCK_EXPOSURE</constant></entry>
- <entry>Automatic exposure adjustments lock.</entry>
- </row>
- <row>
- <entry><constant>V4L2_LOCK_WHITE_BALANCE</constant></entry>
- <entry>Automatic white balance adjustments lock.</entry>
- </row>
- <row>
- <entry><constant>V4L2_LOCK_FOCUS</constant></entry>
- <entry>Automatic focus lock.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry spanname="descr">
-When a given algorithm is not enabled, drivers should ignore requests
-to lock it and should return no error. An example might be an application
-setting bit <constant>V4L2_LOCK_WHITE_BALANCE</constant> when the
-<constant>V4L2_CID_AUTO_WHITE_BALANCE</constant> control is set to
-<constant>FALSE</constant>. The value of this control may be changed
-by exposure, white balance or focus controls.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_PAN_SPEED</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control turns the
-camera horizontally at the specific speed. The unit is undefined. A
-positive value moves the camera to the right (clockwise when viewed
-from above), a negative value to the left. A value of zero stops the motion
-if one is in progress and has no effect otherwise.</entry>
- </row>
- <row><entry></entry></row>
-
- <row>
- <entry spanname="id"><constant>V4L2_CID_TILT_SPEED</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row><row><entry spanname="descr">This control turns the
-camera vertically at the specified speed. The unit is undefined. A
-positive value moves the camera up, a negative value down. A value of zero
-stops the motion if one is in progress and has no effect otherwise.</entry>
- </row>
- <row><entry></entry></row>
-
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="fm-tx-controls">
- <title>FM Transmitter Control Reference</title>
-
- <para>The FM Transmitter (FM_TX) class includes controls for common features of
-FM transmissions capable devices. Currently this class includes parameters for audio
-compression, pilot tone generation, audio deviation limiter, RDS transmission and
-tuning power features.</para>
-
- <table pgwide="1" frame="none" id="fm-tx-control-id">
- <title>FM_TX 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_FM_TX_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The FM_TX class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_DEVIATION</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Configures RDS signal frequency deviation level in Hz.
-The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_PI</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the RDS Programme Identification field
-for transmission.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_PTY</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the RDS Programme Type field for transmission.
-This encodes up to 31 pre-defined programme types.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_PS_NAME</constant>&nbsp;</entry>
- <entry>string</entry>
- </row>
- <row><entry spanname="descr">Sets the Programme Service name (PS_NAME) for transmission.
-It is intended for static display on a receiver. It is the primary aid to listeners in programme service
-identification and selection. In Annex E of <xref linkend="iec62106" />, the RDS specification,
-there is a full description of the correct character encoding for Programme Service name strings.
-Also from RDS specification, PS is usually a single eight character text. However, it is also possible
-to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
-with steps of 8 characters. The result is it must always contain a string with size multiple of 8.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_RADIO_TEXT</constant>&nbsp;</entry>
- <entry>string</entry>
- </row>
- <row><entry spanname="descr">Sets the Radio Text info for transmission. It is a textual description of
-what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
-programme-related information or any other text. In these cases, RadioText should be used in addition to
-<constant>V4L2_CID_RDS_TX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
-in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
-used to transmit it, either 32 (2A block) or 64 (2B block). However, it is also possible
-to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
-with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_MONO_STEREO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Sets the Mono/Stereo bit of the Decoder Identification code. If set,
-then the audio was recorded as stereo.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_ARTIFICIAL_HEAD</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Sets the
-<ulink url="http://en.wikipedia.org/wiki/Artificial_head">Artificial Head</ulink> bit of the Decoder
-Identification code. If set, then the audio was recorded using an artificial head.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_COMPRESSED</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Sets the Compressed bit of the Decoder Identification code. If set,
-then the audio is compressed.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_DYNAMIC_PTY</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Sets the Dynamic PTY bit of the Decoder Identification code. If set,
-then the PTY code is dynamically switched.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_MUSIC_SPEECH</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
-broadcasts speech. If the transmitter doesn't make this distinction, then it should be set.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS_ENABLE</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then transmit alternate frequencies.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_TX_ALT_FREQS</constant>&nbsp;</entry>
- <entry>__u32 array</entry>
- </row>
- <row><entry spanname="descr">The alternate frequencies in kHz units. The RDS standard allows
-for up to 25 frequencies to be defined. Drivers may support fewer frequencies so check
-the array size.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_LIMITER_ENABLED</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables or disables the audio deviation limiter feature.
-The limiter is useful when trying to maximize the audio volume, minimize receiver-generated
-distortion and prevent overmodulation.
-</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_LIMITER_RELEASE_TIME</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the audio deviation limiter feature release time.
-Unit is in useconds. Step and range are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_LIMITER_DEVIATION</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Configures audio frequency deviation level in Hz.
-The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_COMPRESSION_ENABLED</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables or disables the audio compression feature.
-This feature amplifies signals below the threshold by a fixed gain and compresses audio
-signals above the threshold by the ratio of Threshold/(Gain + Threshold).</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_COMPRESSION_GAIN</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the gain for audio compression feature. It is
-a dB value. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_COMPRESSION_THRESHOLD</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the threshold level for audio compression freature.
-It is a dB value. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the attack time for audio compression feature.
-It is a useconds value. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the release time for audio compression feature.
-It is a useconds value. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_PILOT_TONE_ENABLED</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">Enables or disables the pilot tone generation feature.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_PILOT_TONE_DEVIATION</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Configures pilot tone frequency deviation level. Unit is
-in Hz. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_PILOT_TONE_FREQUENCY</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Configures pilot tone frequency value. Unit is
-in Hz. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TUNE_PREEMPHASIS</constant>&nbsp;</entry>
- <entry>enum v4l2_preemphasis</entry>
- </row>
- <row id="v4l2-preemphasis"><entry spanname="descr">Configures the pre-emphasis value for broadcasting.
-A pre-emphasis filter is applied to the broadcast to accentuate the high audio frequencies.
-Depending on the region, a time constant of either 50 or 75 useconds is used. The enum&nbsp;v4l2_preemphasis
-defines possible values for pre-emphasis. Here they are:</entry>
- </row><row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_PREEMPHASIS_DISABLED</constant>&nbsp;</entry>
- <entry>No pre-emphasis is applied.</entry>
- </row>
- <row>
- <entry><constant>V4L2_PREEMPHASIS_50_uS</constant>&nbsp;</entry>
- <entry>A pre-emphasis of 50 uS is used.</entry>
- </row>
- <row>
- <entry><constant>V4L2_PREEMPHASIS_75_uS</constant>&nbsp;</entry>
- <entry>A pre-emphasis of 75 uS is used.</entry>
- </row>
- </tbody>
- </entrytbl>
-
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TUNE_POWER_LEVEL</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the output power level for signal transmission.
-Unit is in dBuV. Range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TUNE_ANTENNA_CAPACITOR</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">This selects the value of antenna tuning capacitor
-manually or automatically if set to zero. Unit, range and step are driver-specific.</entry>
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
-
-<para>For more details about RDS specification, refer to
-<xref linkend="iec62106" /> document, from CENELEC.</para>
- </section>
-
- <section id="flash-controls">
- <title>Flash Control Reference</title>
-
- <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>
-
-
- <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>
- <row>
- <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
- <entry>Current in the LED power supply has exceeded the limit
- specific to the flash controller.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
- <entry>The flash controller has detected a short or open
- circuit condition on the indicator LED.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FLASH_FAULT_UNDER_VOLTAGE</constant></entry>
- <entry>Flash controller voltage to the flash LED
- has been below the minimum limit specific to the flash
- controller.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FLASH_FAULT_INPUT_VOLTAGE</constant></entry>
- <entry>The input voltage of the flash controller is below
- the limit under which strobing the flash at full current
- will not be possible.The condition persists until this flag
- is no longer set.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FLASH_FAULT_LED_OVER_TEMPERATURE</constant></entry>
- <entry>The temperature of the LED has exceeded its
- allowed upper limit.</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>
- </section>
-
- <section id="jpeg-controls">
- <title>JPEG Control Reference</title>
- <para>The JPEG class includes controls for common features of JPEG
- encoders and decoders. Currently it includes features for codecs
- implementing progressive baseline DCT compression process with
- Huffman entrophy coding.</para>
- <table pgwide="1" frame="none" id="jpeg-control-id">
- <title>JPEG 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_JPEG_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The JPEG class descriptor. Calling
- &VIDIOC-QUERYCTRL; for this control will return a description of this
- control class.
-
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_JPEG_CHROMA_SUBSAMPLING</constant></entry>
- <entry>menu</entry>
- </row>
- <row id="v4l2-jpeg-chroma-subsampling">
- <entry spanname="descr">The chroma subsampling factors describe how
- each component of an input image is sampled, in respect to maximum
- sample rate in each spatial dimension. See <xref linkend="itu-t81"/>,
- clause A.1.1. for more details. The <constant>
- V4L2_CID_JPEG_CHROMA_SUBSAMPLING</constant> control determines how
- Cb and Cr components are downsampled after coverting an input image
- from RGB to Y'CbCr color space.
- </entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_444</constant>
- </entry><entry>No chroma subsampling, each pixel has
- Y, Cr and Cb values.</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_422</constant>
- </entry><entry>Horizontally subsample Cr, Cb components
- by a factor of 2.</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_420</constant>
- </entry><entry>Subsample Cr, Cb components horizontally
- and vertically by 2.</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_411</constant>
- </entry><entry>Horizontally subsample Cr, Cb components
- by a factor of 4.</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_410</constant>
- </entry><entry>Subsample Cr, Cb components horizontally
- by 4 and vertically by 2.</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY</constant>
- </entry><entry>Use only luminance component.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_JPEG_RESTART_INTERVAL</constant>
- </entry><entry>integer</entry>
- </row>
- <row><entry spanname="descr">
- The restart interval determines an interval of inserting RSTm
- markers (m = 0..7). The purpose of these markers is to additionally
- reinitialize the encoder process, in order to process blocks of
- an image independently.
- For the lossy compression processes the restart interval unit is
- MCU (Minimum Coded Unit) and its value is contained in DRI
- (Define Restart Interval) marker. If <constant>
- V4L2_CID_JPEG_RESTART_INTERVAL</constant> control is set to 0,
- DRI and RSTm markers will not be inserted.
- </entry>
- </row>
- <row id="jpeg-quality-control">
- <entry spanname="id"><constant>V4L2_CID_JPEG_COMPRESSION_QUALITY</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">
- <constant>V4L2_CID_JPEG_COMPRESSION_QUALITY</constant> control
- determines trade-off between image quality and size.
- It provides simpler method for applications to control image quality,
- without a need for direct reconfiguration of luminance and chrominance
- quantization tables.
-
- In cases where a driver uses quantization tables configured directly
- by an application, using interfaces defined elsewhere, <constant>
- V4L2_CID_JPEG_COMPRESSION_QUALITY</constant> control should be set
- by driver to 0.
-
- <para>The value range of this control is driver-specific. Only
- positive, non-zero values are meaningful. The recommended range
- is 1 - 100, where larger values correspond to better image quality.
- </para>
- </entry>
- </row>
- <row id="jpeg-active-marker-control">
- <entry spanname="id"><constant>V4L2_CID_JPEG_ACTIVE_MARKER</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">Specify which JPEG markers are included
- in compressed stream. This control is valid only for encoders.
- </entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_JPEG_ACTIVE_MARKER_APP0</constant></entry>
- <entry>Application data segment APP<subscript>0</subscript>.</entry>
- </row><row>
- <entry><constant>V4L2_JPEG_ACTIVE_MARKER_APP1</constant></entry>
- <entry>Application data segment APP<subscript>1</subscript>.</entry>
- </row><row>
- <entry><constant>V4L2_JPEG_ACTIVE_MARKER_COM</constant></entry>
- <entry>Comment segment.</entry>
- </row><row>
- <entry><constant>V4L2_JPEG_ACTIVE_MARKER_DQT</constant></entry>
- <entry>Quantization tables segment.</entry>
- </row><row>
- <entry><constant>V4L2_JPEG_ACTIVE_MARKER_DHT</constant></entry>
- <entry>Huffman tables segment.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
- <para>For more details about JPEG specification, refer
- to <xref linkend="itu-t81"/>, <xref linkend="jfif"/>,
- <xref linkend="w3c-jpeg-jfif"/>.</para>
- </section>
-
- <section id="image-source-controls">
- <title>Image Source Control Reference</title>
-
- <para>
- The Image Source control class is intended for low-level
- control of image source devices such as image sensors. The
- devices feature an analogue to digital converter and a bus
- transmitter to transmit the image data out of the device.
- </para>
-
- <table pgwide="1" frame="none" id="image-source-control-id">
- <title>Image Source 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_IMAGE_SOURCE_CLASS</constant></entry>
- <entry>class</entry>
- </row>
- <row>
- <entry spanname="descr">The IMAGE_SOURCE class descriptor.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_VBLANK</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Vertical blanking. The idle period
- after every frame during which no image data is produced.
- The unit of vertical blanking is a line. Every line has
- length of the image width plus horizontal blanking at the
- pixel rate defined by
- <constant>V4L2_CID_PIXEL_RATE</constant> control in the
- same sub-device.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_HBLANK</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Horizontal blanking. The idle
- period after every line of image data during which no
- image data is produced. The unit of horizontal blanking is
- pixels.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_ANALOGUE_GAIN</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Analogue gain is gain affecting
- all colour components in the pixel matrix. The gain
- operation is performed in the analogue domain before A/D
- conversion.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_RED</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Test pattern red colour component.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENR</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Test pattern green (next to red)
- colour component.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_BLUE</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Test pattern blue colour component.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN_GREENB</constant></entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Test pattern green (next to blue)
- colour component.
- </entry>
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section id="image-process-controls">
- <title>Image Process Control Reference</title>
-
- <para>
- The Image Process control class is intended for low-level control of
- image processing functions. Unlike
- <constant>V4L2_CID_IMAGE_SOURCE_CLASS</constant>, the controls in
- this class affect processing the image, and do not control capturing
- of it.
- </para>
-
- <table pgwide="1" frame="none" id="image-process-control-id">
- <title>Image Process 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_IMAGE_PROC_CLASS</constant></entry>
- <entry>class</entry>
- </row>
- <row>
- <entry spanname="descr">The IMAGE_PROC class descriptor.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_LINK_FREQ</constant></entry>
- <entry>integer menu</entry>
- </row>
- <row>
- <entry spanname="descr">Data bus frequency. Together with the
- media bus pixel code, bus type (clock cycles per sample), the
- data bus frequency defines the pixel rate
- (<constant>V4L2_CID_PIXEL_RATE</constant>) in the
- pixel array (or possibly elsewhere, if the device is not an
- image sensor). The frame rate can be calculated from the pixel
- clock, image width and height and horizontal and vertical
- blanking. While the pixel rate control may be defined elsewhere
- than in the subdev containing the pixel array, the frame rate
- cannot be obtained from that information. This is because only
- on the pixel array it can be assumed that the vertical and
- horizontal blanking information is exact: no other blanking is
- allowed in the pixel array. The selection of frame rate is
- performed by selecting the desired horizontal and vertical
- blanking. The unit of this control is Hz. </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_PIXEL_RATE</constant></entry>
- <entry>64-bit integer</entry>
- </row>
- <row>
- <entry spanname="descr">Pixel rate in the source pads of
- the subdev. This control is read-only and its unit is
- pixels / second.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN</constant></entry>
- <entry>menu</entry>
- </row>
- <row id="v4l2-test-pattern">
- <entry spanname="descr"> Some capture/display/sensor devices have
- the capability to generate test pattern images. These hardware
- specific test patterns can be used to test if a device is working
- properly.</entry>
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section id="dv-controls">
- <title>Digital Video Control Reference</title>
-
- <para>
- The Digital Video control class is intended to control receivers
- and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>,
- <ulink url="http://en.wikipedia.org/wiki/Digital_Visual_Interface">DVI</ulink>
- (Digital Visual Interface), HDMI (<xref linkend="hdmi" />) and DisplayPort (<xref linkend="dp" />).
- These controls are generally expected to be private to the receiver or transmitter
- subdevice that implements them, so they are only exposed on the
- <filename>/dev/v4l-subdev*</filename> device node.
- </para>
-
- <para>Note that these devices can have multiple input or output pads which are
- hooked up to e.g. HDMI connectors. Even though the subdevice will receive or
- transmit video from/to only one of those pads, the other pads can still be
- active when it comes to EDID (Extended Display Identification Data,
- <xref linkend="vesaedid" />) and HDCP (High-bandwidth Digital Content
- Protection System, <xref linkend="hdcp" />) processing, allowing the device
- to do the fairly slow EDID/HDCP handling in advance. This allows for quick
- switching between connectors.</para>
-
- <para>These pads appear in several of the controls in this section as
- bitmasks, one bit for each pad. Bit 0 corresponds to pad 0, bit 1 to pad 1,
- etc. The maximum value of the control is the set of valid pads.</para>
-
- <table pgwide="1" frame="none" id="dv-control-id">
- <title>Digital Video 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_DV_CLASS</constant></entry>
- <entry>class</entry>
- </row>
- <row>
- <entry spanname="descr">The Digital Video class descriptor.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_HOTPLUG</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">Many connectors have a hotplug pin which is high
- if EDID information is available from the source. This control shows the
- state of the hotplug pin as seen by the transmitter.
- Each bit corresponds to an output pad on the transmitter. If an output pad
- does not have an associated hotplug pin, then the bit for that pad will be 0.
- This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_RXSENSE</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">Rx Sense is the detection of pull-ups on the TMDS
- clock lines. This normally means that the sink has left/entered standby (i.e.
- the transmitter can sense that the receiver is ready to receive video).
- Each bit corresponds to an output pad on the transmitter. If an output pad
- does not have an associated Rx Sense, then the bit for that pad will be 0.
- This read-only control is applicable to DVI-D and HDMI devices.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_EDID_PRESENT</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">When the transmitter sees the hotplug signal from the
- receiver it will attempt to read the EDID. If set, then the transmitter has read
- at least the first block (= 128 bytes).
- Each bit corresponds to an output pad on the transmitter. If an output pad
- does not support EDIDs, then the bit for that pad will be 0.
- This read-only control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_MODE</constant></entry>
- <entry id="v4l2-dv-tx-mode">enum v4l2_dv_tx_mode</entry>
- </row>
- <row>
- <entry spanname="descr">HDMI transmitters can transmit in DVI-D mode (just video)
- or in HDMI mode (video + audio + auxiliary data). This control selects which mode
- to use: V4L2_DV_TX_MODE_DVI_D or V4L2_DV_TX_MODE_HDMI.
- This control is applicable to HDMI connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_RGB_RANGE</constant></entry>
- <entry id="v4l2-dv-rgb-range">enum v4l2_dv_rgb_range</entry>
- </row>
- <row>
- <entry spanname="descr">Select the quantization range for RGB output. V4L2_DV_RANGE_AUTO
- follows the RGB quantization range specified in the standard for the video interface
- (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
- to be compatible with sinks that have not implemented the standard correctly
- (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
- used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
- where N is the number of bits per component.
- This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_TX_IT_CONTENT_TYPE</constant></entry>
- <entry id="v4l2-dv-content-type">enum v4l2_dv_it_content_type</entry>
- </row>
- <row><entry spanname="descr">Configures the IT Content Type
- of the transmitted video. This information is sent over HDMI and DisplayPort connectors
- as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates
- from a computer as opposed to content from a TV broadcast or an analog source. The
- enum&nbsp;v4l2_dv_it_content_type defines the possible content types:</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_DV_IT_CONTENT_TYPE_GRAPHICS</constant>&nbsp;</entry>
- <entry>Graphics content. Pixel data should be passed unfiltered and without
- analog reconstruction.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DV_IT_CONTENT_TYPE_PHOTO</constant>&nbsp;</entry>
- <entry>Photo content. The content is derived from digital still pictures.
- The content should be passed through with minimal scaling and picture
- enhancements.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DV_IT_CONTENT_TYPE_CINEMA</constant>&nbsp;</entry>
- <entry>Cinema content.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DV_IT_CONTENT_TYPE_GAME</constant>&nbsp;</entry>
- <entry>Game content. Audio and video latency should be minimized.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DV_IT_CONTENT_TYPE_NO_ITC</constant>&nbsp;</entry>
- <entry>No IT Content information is available and the ITC bit in the AVI
- InfoFrame is set to 0.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_RX_POWER_PRESENT</constant></entry>
- <entry>bitmask</entry>
- </row>
- <row>
- <entry spanname="descr">Detects whether the receiver receives power from the source
- (e.g. HDMI carries 5V on one of the pins). This is often used to power an eeprom
- which contains EDID information, such that the source can read the EDID even if
- the sink is in standby/power off.
- Each bit corresponds to an input pad on the transmitter. If an input pad
- cannot detect whether power is present, then the bit for that pad will be 0.
- This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_RX_RGB_RANGE</constant></entry>
- <entry>enum v4l2_dv_rgb_range</entry>
- </row>
- <row>
- <entry spanname="descr">Select the quantization range for RGB input. V4L2_DV_RANGE_AUTO
- follows the RGB quantization range specified in the standard for the video interface
- (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
- to be compatible with sources that have not implemented the standard correctly
- (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
- used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
- where N is the number of bits per component.
- This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
- </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DV_RX_IT_CONTENT_TYPE</constant></entry>
- <entry>enum v4l2_dv_it_content_type</entry>
- </row>
- <row><entry spanname="descr">Reads the IT Content Type
- of the received video. This information is sent over HDMI and DisplayPort connectors
- as part of the AVI InfoFrame. The term 'IT Content' is used for content that originates
- from a computer as opposed to content from a TV broadcast or an analog source. See
- <constant>V4L2_CID_DV_TX_IT_CONTENT_TYPE</constant> for the available content types.</entry>
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section id="fm-rx-controls">
- <title>FM Receiver Control Reference</title>
-
- <para>The FM Receiver (FM_RX) class includes controls for common features of
- FM Reception capable devices.</para>
-
- <table pgwide="1" frame="none" id="fm-rx-control-id">
- <title>FM_RX 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_FM_RX_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The FM_RX class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RECEPTION</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row><row><entry spanname="descr">Enables/disables RDS
- reception by the radio tuner</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_PTY</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Gets RDS Programme Type field.
-This encodes up to 31 pre-defined programme types.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_PS_NAME</constant>&nbsp;</entry>
- <entry>string</entry>
- </row>
- <row><entry spanname="descr">Gets the Programme Service name (PS_NAME).
-It is intended for static display on a receiver. It is the primary aid to listeners in programme service
-identification and selection. In Annex E of <xref linkend="iec62106" />, the RDS specification,
-there is a full description of the correct character encoding for Programme Service name strings.
-Also from RDS specification, PS is usually a single eight character text. However, it is also possible
-to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
-with steps of 8 characters. The result is it must always contain a string with size multiple of 8.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_RADIO_TEXT</constant>&nbsp;</entry>
- <entry>string</entry>
- </row>
- <row><entry spanname="descr">Gets the Radio Text info. It is a textual description of
-what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
-programme-related information or any other text. In these cases, RadioText can be used in addition to
-<constant>V4L2_CID_RDS_RX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
-in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
-used to transmit it, either 32 (2A block) or 64 (2B block). However, it is also possible
-to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
-with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_ANNOUNCEMENT</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then a traffic announcement is in progress.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_TRAFFIC_PROGRAM</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then the tuned programme carries traffic announcements.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RDS_RX_MUSIC_SPEECH</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row><entry spanname="descr">If set, then this channel broadcasts music. If cleared, then it
-broadcasts speech. If the transmitter doesn't make this distinction, then it will be set.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_TUNE_DEEMPHASIS</constant>&nbsp;</entry>
- <entry>enum v4l2_deemphasis</entry>
- </row>
- <row id="v4l2-deemphasis"><entry spanname="descr">Configures the de-emphasis value for reception.
-A de-emphasis filter is applied to the broadcast to accentuate the high audio frequencies.
-Depending on the region, a time constant of either 50 or 75 useconds is used. The enum&nbsp;v4l2_deemphasis
-defines possible values for de-emphasis. Here they are:</entry>
- </row><row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_DEEMPHASIS_DISABLED</constant>&nbsp;</entry>
- <entry>No de-emphasis is applied.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DEEMPHASIS_50_uS</constant>&nbsp;</entry>
- <entry>A de-emphasis of 50 uS is used.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DEEMPHASIS_75_uS</constant>&nbsp;</entry>
- <entry>A de-emphasis of 75 uS is used.</entry>
- </row>
- </tbody>
- </entrytbl>
-
- </row>
- <row><entry></entry></row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="detect-controls">
- <title>Detect Control Reference</title>
-
- <para>The Detect class includes controls for common features of
- various motion or object detection capable devices.</para>
-
- <table pgwide="1" frame="none" id="detect-control-id">
- <title>Detect 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_DETECT_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The Detect class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DETECT_MD_MODE</constant>&nbsp;</entry>
- <entry>menu</entry>
- </row><row><entry spanname="descr">Sets the motion detection mode.</entry>
- </row>
- <row>
- <entrytbl spanname="descr" cols="2">
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_DETECT_MD_MODE_DISABLED</constant>
- </entry><entry>Disable motion detection.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DETECT_MD_MODE_GLOBAL</constant>
- </entry><entry>Use a single motion detection threshold.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
- </entry><entry>The image is divided into a grid, each cell with its own
- motion detection threshold. These thresholds are set through the
- <constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant> matrix control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
- </entry><entry>The image is divided into a grid, each cell with its own
- region value that specifies which per-region motion detection thresholds
- should be used. Each region has its own thresholds. How these per-region
- thresholds are set up is driver-specific. The region values for the grid are set
- through the <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> matrix
- control.</entry>
- </row>
- </tbody>
- </entrytbl>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row><entry spanname="descr">Sets the global motion detection threshold to be
- used with the <constant>V4L2_DETECT_MD_MODE_GLOBAL</constant> motion detection mode.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant>&nbsp;</entry>
- <entry>__u16 matrix</entry>
- </row>
- <row><entry spanname="descr">Sets the motion detection thresholds for each cell in the grid.
- To be used with the <constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
- motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
- grid.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_DETECT_MD_REGION_GRID</constant>&nbsp;</entry>
- <entry>__u8 matrix</entry>
- </row>
- <row><entry spanname="descr">Sets the motion detection region value for each cell in the grid.
- To be used with the <constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
- motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
- grid.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section id="rf-tuner-controls">
- <title>RF Tuner Control Reference</title>
-
- <para>
-The RF Tuner (RF_TUNER) class includes controls for common features of devices
-having RF tuner.
- </para>
- <para>
-In this context, RF tuner is radio receiver circuit between antenna and
-demodulator. It receives radio frequency (RF) from the antenna and converts that
-received signal to lower intermediate frequency (IF) or baseband frequency (BB).
-Tuners that could do baseband output are often called Zero-IF tuners. Older
-tuners were typically simple PLL tuners inside a metal box, whilst newer ones
-are highly integrated chips without a metal box "silicon tuners". These controls
-are mostly applicable for new feature rich silicon tuners, just because older
-tuners does not have much adjustable features.
- </para>
- <para>
-For more information about RF tuners see
-<ulink url="http://en.wikipedia.org/wiki/Tuner_%28radio%29">Tuner (radio)</ulink>
-and
-<ulink url="http://en.wikipedia.org/wiki/RF_front_end">RF front end</ulink>
-from Wikipedia.
- </para>
-
- <table pgwide="1" frame="none" id="rf-tuner-control-id">
- <title>RF_TUNER 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_RF_TUNER_CLASS</constant>&nbsp;</entry>
- <entry>class</entry>
- </row><row><entry spanname="descr">The RF_TUNER class
-descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
-description of this control class.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_BANDWIDTH_AUTO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables/disables tuner radio channel
-bandwidth configuration. In automatic mode bandwidth configuration is performed
-by the driver.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_BANDWIDTH</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Filter(s) on tuner signal path are used to
-filter signal according to receiving party needs. Driver configures filters to
-fulfill desired bandwidth requirement. Used when V4L2_CID_RF_TUNER_BANDWIDTH_AUTO is not
-set. Unit is in Hz. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_LNA_GAIN_AUTO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables/disables LNA automatic gain control (AGC)</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables/disables mixer automatic gain control (AGC)</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_IF_GAIN_AUTO</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Enables/disables IF automatic gain control (AGC)</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_RF_GAIN</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">The RF amplifier is the very first
-amplifier on the receiver signal path, just right after the antenna input.
-The difference between the LNA gain and the RF gain in this document is that
-the LNA gain is integrated in the tuner chip while the RF gain is a separate
-chip. There may be both RF and LNA gain controls in the same device.
-The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_LNA_GAIN</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">LNA (low noise amplifier) gain is first
-gain stage on the RF tuner signal path. It is located very close to tuner
-antenna input. Used when <constant>V4L2_CID_RF_TUNER_LNA_GAIN_AUTO</constant> is not set.
-See <constant>V4L2_CID_RF_TUNER_RF_GAIN</constant> to understand how RF gain
-and LNA gain differs from the each others.
-The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_MIXER_GAIN</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">Mixer gain is second gain stage on the RF
-tuner signal path. It is located inside mixer block, where RF signal is
-down-converted by the mixer. Used when <constant>V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO</constant>
-is not set. The range and step are driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_IF_GAIN</constant>&nbsp;</entry>
- <entry>integer</entry>
- </row>
- <row>
- <entry spanname="descr">IF gain is last gain stage on the RF tuner
-signal path. It is located on output of RF tuner. It controls signal level of
-intermediate frequency output or baseband output. Used when
-<constant>V4L2_CID_RF_TUNER_IF_GAIN_AUTO</constant> is not set. The range and step are
-driver-specific.</entry>
- </row>
- <row>
- <entry spanname="id"><constant>V4L2_CID_RF_TUNER_PLL_LOCK</constant>&nbsp;</entry>
- <entry>boolean</entry>
- </row>
- <row>
- <entry spanname="descr">Is synthesizer PLL locked? RF tuner is
-receiving given frequency when that control is set. This is a read-only control.
-</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-</section>
diff --git a/Documentation/DocBook/media/v4l/crop.pdf b/Documentation/DocBook/media/v4l/crop.pdf
deleted file mode 100644
index c9fb81cd32f3..000000000000
--- a/Documentation/DocBook/media/v4l/crop.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/dev-capture.xml b/Documentation/DocBook/media/v4l/dev-capture.xml
deleted file mode 100644
index e1c5f9406d6a..000000000000
--- a/Documentation/DocBook/media/v4l/dev-capture.xml
+++ /dev/null
@@ -1,110 +0,0 @@
- <title>Video Capture Interface</title>
-
- <para>Video capture devices sample an analog video signal and store
-the digitized images in memory. Today nearly all devices can capture
-at full 25 or 30 frames/second. With this interface applications can
-control the capture process and move images from the driver into user
-space.</para>
-
- <para>Conventionally V4L2 video capture devices are accessed through
-character device special files named <filename>/dev/video</filename>
-and <filename>/dev/video0</filename> to
-<filename>/dev/video63</filename> with major number 81 and minor
-numbers 0 to 63. <filename>/dev/video</filename> is typically a
-symbolic link to the preferred video device. Note the same device
-files are used for video output devices.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the video capture interface set the
-<constant>V4L2_CAP_VIDEO_CAPTURE</constant> or
-<constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
-they may also support the <link linkend="overlay">video overlay</link>
-(<constant>V4L2_CAP_VIDEO_OVERLAY</constant>) and the <link
-linkend="raw-vbi">raw VBI capture</link>
-(<constant>V4L2_CAP_VBI_CAPTURE</constant>) interface. At least one of
-the read/write or streaming I/O methods must be supported. Tuners and
-audio inputs are optional.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>Video capture devices shall support <link
-linkend="audio">audio input</link>, <link
-linkend="tuner">tuner</link>, <link linkend="control">controls</link>,
-<link linkend="crop">cropping and scaling</link> and <link
-linkend="streaming-par">streaming parameter</link> ioctls as needed.
-The <link linkend="video">video input</link> and <link
-linkend="standard">video standard</link> ioctls must be supported by
-all video capture devices.</para>
- </section>
-
- <section>
- <title>Image Format Negotiation</title>
-
- <para>The result of a capture operation is determined by
-cropping and image format parameters. The former select an area of the
-video picture to capture, the latter how images are stored in memory,
-&ie; in RGB or YUV format, the number of bits per pixel or width and
-height. Together they also define how images are scaled in the
-process.</para>
-
- <para>As usual these parameters are <emphasis>not</emphasis> reset
-at &func-open; time to permit Unix tool chains, programming a device
-and then reading from it as if it was a plain file. Well written V4L2
-applications ensure they really get what they want, including cropping
-and scaling.</para>
-
- <para>Cropping initialization at minimum requires to reset the
-parameters to defaults. An example is given in <xref
-linkend="crop" />.</para>
-
- <para>To query the current image format applications set the
-<structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and call the
-&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-pix-format; <structfield>pix</structfield> or the
-&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
-<structfield>fmt</structfield> union.</para>
-
- <para>To request different parameters applications set the
-<structfield>type</structfield> field of a &v4l2-format; as above and
-initialize all fields of the &v4l2-pix-format;
-<structfield>vbi</structfield> member of the
-<structfield>fmt</structfield> union, or better just modify the
-results of <constant>VIDIOC_G_FMT</constant>, and call the
-&VIDIOC-S-FMT; ioctl with a pointer to this structure. Drivers may
-adjust the parameters and finally return the actual parameters as
-<constant>VIDIOC_G_FMT</constant> does.</para>
-
- <para>Like <constant>VIDIOC_S_FMT</constant> the
-&VIDIOC-TRY-FMT; ioctl can be used to learn about hardware limitations
-without disabling I/O or possibly time consuming hardware
-preparations.</para>
-
- <para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
-are discussed in <xref linkend="pixfmt" />. See also the specification of the
-<constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
-and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
-capture devices must implement both the
-<constant>VIDIOC_G_FMT</constant> and
-<constant>VIDIOC_S_FMT</constant> ioctl, even if
-<constant>VIDIOC_S_FMT</constant> ignores all requests and always
-returns default parameters as <constant>VIDIOC_G_FMT</constant> does.
-<constant>VIDIOC_TRY_FMT</constant> is optional.</para>
- </section>
-
- <section>
- <title>Reading Images</title>
-
- <para>A video capture device may support the <link
-linkend="rw">read() function</link> and/or streaming (<link
-linkend="mmap">memory mapping</link> or <link
-linkend="userp">user pointer</link>) I/O. See <xref
-linkend="io" /> for details.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-codec.xml b/Documentation/DocBook/media/v4l/dev-codec.xml
deleted file mode 100644
index ff44c16fc080..000000000000
--- a/Documentation/DocBook/media/v4l/dev-codec.xml
+++ /dev/null
@@ -1,27 +0,0 @@
- <title>Codec Interface</title>
-
- <para>A V4L2 codec can compress, decompress, transform, or otherwise
-convert video data from one format into another format, in memory. Typically
-such devices are memory-to-memory devices (i.e. devices with the
-<constant>V4L2_CAP_VIDEO_M2M</constant> or <constant>V4L2_CAP_VIDEO_M2M_MPLANE</constant>
-capability set).
-</para>
-
- <para>A memory-to-memory video node acts just like a normal video node, but it
-supports both output (sending frames from memory to the codec hardware) and
-capture (receiving the processed frames from the codec hardware into memory)
-stream I/O. An application will have to setup the stream
-I/O for both sides and finally call &VIDIOC-STREAMON; for both capture and output
-to start the codec.</para>
-
- <para>Video compression codecs use the MPEG controls to setup their codec parameters
-(note that the MPEG controls actually support many more codecs than just MPEG).
-See <xref linkend="mpeg-controls"></xref>.</para>
-
- <para>Memory-to-memory devices can often be used as a shared resource: you can
-open the video node multiple times, each application setting up their own codec properties
-that are local to the file handle, and each can use it independently from the others.
-The driver will arbitrate access to the codec and reprogram it whenever another file
-handler gets access. This is different from the usual video node behavior where the video properties
-are global to the device (i.e. changing something through one file handle is visible
-through another file handle).</para>
diff --git a/Documentation/DocBook/media/v4l/dev-effect.xml b/Documentation/DocBook/media/v4l/dev-effect.xml
deleted file mode 100644
index 2350a67c0710..000000000000
--- a/Documentation/DocBook/media/v4l/dev-effect.xml
+++ /dev/null
@@ -1,17 +0,0 @@
- <title>Effect Devices Interface</title>
-
- <note>
- <title>Suspended</title>
-
- <para>This interface has been be suspended from the V4L2 API
-implemented in Linux 2.6 until we have more experience with effect
-device interfaces.</para>
- </note>
-
- <para>A V4L2 video effect device can do image effects, filtering, or
-combine two or more images or image streams. For example video
-transitions or wipes. Applications send data to be processed and
-receive the result data either with &func-read; and &func-write;
-functions, or through the streaming I/O mechanism.</para>
-
- <para>[to do]</para>
diff --git a/Documentation/DocBook/media/v4l/dev-event.xml b/Documentation/DocBook/media/v4l/dev-event.xml
deleted file mode 100644
index 19f4becfae34..000000000000
--- a/Documentation/DocBook/media/v4l/dev-event.xml
+++ /dev/null
@@ -1,43 +0,0 @@
- <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>
diff --git a/Documentation/DocBook/media/v4l/dev-osd.xml b/Documentation/DocBook/media/v4l/dev-osd.xml
deleted file mode 100644
index 54853329140b..000000000000
--- a/Documentation/DocBook/media/v4l/dev-osd.xml
+++ /dev/null
@@ -1,149 +0,0 @@
- <title>Video Output Overlay Interface</title>
- <subtitle>Also known as On-Screen Display (OSD)</subtitle>
-
- <para>Some video output devices can overlay a framebuffer image onto
-the outgoing video signal. Applications can set up such an overlay
-using this interface, which borrows structures and ioctls of the <link
-linkend="overlay">Video Overlay</link> interface.</para>
-
- <para>The OSD function is accessible through the same character
-special file as the <link linkend="capture">Video Output</link> function.
-Note the default function of such a <filename>/dev/video</filename> device
-is video capturing or output. The OSD function is only available after
-calling the &VIDIOC-S-FMT; ioctl.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the <wordasword>Video Output
-Overlay</wordasword> interface set the
-<constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl.</para>
- </section>
-
- <section>
- <title>Framebuffer</title>
-
- <para>Contrary to the <wordasword>Video Overlay</wordasword>
-interface the framebuffer is normally implemented on the TV card and
-not the graphics card. On Linux it is accessible as a framebuffer
-device (<filename>/dev/fbN</filename>). Given a V4L2 device,
-applications can find the corresponding framebuffer device by calling
-the &VIDIOC-G-FBUF; ioctl. It returns, amongst other information, the
-physical address of the framebuffer in the
-<structfield>base</structfield> field of &v4l2-framebuffer;. The
-framebuffer device ioctl <constant>FBIOGET_FSCREENINFO</constant>
-returns the same address in the <structfield>smem_start</structfield>
-field of struct <structname>fb_fix_screeninfo</structname>. The
-<constant>FBIOGET_FSCREENINFO</constant> ioctl and struct
-<structname>fb_fix_screeninfo</structname> are defined in the
-<filename>linux/fb.h</filename> header file.</para>
-
- <para>The width and height of the framebuffer depends on the
-current video standard. A V4L2 driver may reject attempts to change
-the video standard (or any other ioctl which would imply a framebuffer
-size change) with an &EBUSY; until all applications closed the
-framebuffer device.</para>
-
- <example>
- <title>Finding a framebuffer device for OSD</title>
-
- <programlisting>
-#include &lt;linux/fb.h&gt;
-
-&v4l2-framebuffer; fbuf;
-unsigned int i;
-int fb_fd;
-
-if (-1 == ioctl(fd, VIDIOC_G_FBUF, &amp;fbuf)) {
- perror("VIDIOC_G_FBUF");
- exit(EXIT_FAILURE);
-}
-
-for (i = 0; i &lt; 30; i++) {
- char dev_name[16];
- struct fb_fix_screeninfo si;
-
- snprintf(dev_name, sizeof(dev_name), "/dev/fb%u", i);
-
- fb_fd = open(dev_name, O_RDWR);
- if (-1 == fb_fd) {
- switch (errno) {
- case ENOENT: /* no such file */
- case ENXIO: /* no driver */
- continue;
-
- default:
- perror("open");
- exit(EXIT_FAILURE);
- }
- }
-
- if (0 == ioctl(fb_fd, FBIOGET_FSCREENINFO, &amp;si)) {
- if (si.smem_start == (unsigned long)fbuf.base)
- break;
- } else {
- /* Apparently not a framebuffer device. */
- }
-
- close(fb_fd);
- fb_fd = -1;
-}
-
-/* fb_fd is the file descriptor of the framebuffer device
- for the video output overlay, or -1 if no device was found. */
-</programlisting>
- </example>
- </section>
-
- <section>
- <title>Overlay Window and Scaling</title>
-
- <para>The overlay is controlled by source and target rectangles.
-The source rectangle selects a subsection of the framebuffer image to
-be overlaid, the target rectangle an area in the outgoing video signal
-where the image will appear. Drivers may or may not support scaling,
-and arbitrary sizes and positions of these rectangles. Further drivers
-may support any (or none) of the clipping/blending methods defined for
-the <link linkend="overlay">Video Overlay</link> interface.</para>
-
- <para>A &v4l2-window; defines the size of the source rectangle,
-its position in the framebuffer and the clipping/blending method to be
-used for the overlay. To get the current parameters applications set
-the <structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant> and call the
-&VIDIOC-G-FMT; ioctl. The driver fills the
-<structname>v4l2_window</structname> substructure named
-<structfield>win</structfield>. It is not possible to retrieve a
-previously programmed clipping list or bitmap.</para>
-
- <para>To program the source rectangle applications set the
-<structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant>, initialize
-the <structfield>win</structfield> substructure and call the
-&VIDIOC-S-FMT; ioctl. The driver adjusts the parameters against
-hardware limits and returns the actual parameters as
-<constant>VIDIOC_G_FMT</constant> does. Like
-<constant>VIDIOC_S_FMT</constant>, the &VIDIOC-TRY-FMT; ioctl can be
-used to learn about driver capabilities without actually changing
-driver state. Unlike <constant>VIDIOC_S_FMT</constant> this also works
-after the overlay has been enabled.</para>
-
- <para>A &v4l2-crop; defines the size and position of the target
-rectangle. The scaling factor of the overlay is implied by the width
-and height given in &v4l2-window; and &v4l2-crop;. The cropping API
-applies to <wordasword>Video Output</wordasword> and <wordasword>Video
-Output Overlay</wordasword> devices in the same way as to
-<wordasword>Video Capture</wordasword> and <wordasword>Video
-Overlay</wordasword> devices, merely reversing the direction of the
-data flow. For more information see <xref linkend="crop" />.</para>
- </section>
-
- <section>
- <title>Enabling Overlay</title>
-
- <para>There is no V4L2 ioctl to enable or disable the overlay,
-however the framebuffer interface of the driver may support the
-<constant>FBIOBLANK</constant> ioctl.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-output.xml b/Documentation/DocBook/media/v4l/dev-output.xml
deleted file mode 100644
index 9130a3dc7880..000000000000
--- a/Documentation/DocBook/media/v4l/dev-output.xml
+++ /dev/null
@@ -1,106 +0,0 @@
- <title>Video Output Interface</title>
-
- <para>Video output devices encode stills or image sequences as
-analog video signal. With this interface applications can
-control the encoding process and move images from user space to
-the driver.</para>
-
- <para>Conventionally V4L2 video output devices are accessed through
-character device special files named <filename>/dev/video</filename>
-and <filename>/dev/video0</filename> to
-<filename>/dev/video63</filename> with major number 81 and minor
-numbers 0 to 63. <filename>/dev/video</filename> is typically a
-symbolic link to the preferred video device. Note the same device
-files are used for video capture devices.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the video output interface set the
-<constant>V4L2_CAP_VIDEO_OUTPUT</constant> or
-<constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
-they may also support the <link linkend="raw-vbi">raw VBI
-output</link> (<constant>V4L2_CAP_VBI_OUTPUT</constant>) interface. At
-least one of the read/write or streaming I/O methods must be
-supported. Modulators and audio outputs are optional.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>Video output devices shall support <link
-linkend="audio">audio output</link>, <link
-linkend="tuner">modulator</link>, <link linkend="control">controls</link>,
-<link linkend="crop">cropping and scaling</link> and <link
-linkend="streaming-par">streaming parameter</link> ioctls as needed.
-The <link linkend="video">video output</link> and <link
-linkend="standard">video standard</link> ioctls must be supported by
-all video output devices.</para>
- </section>
-
- <section>
- <title>Image Format Negotiation</title>
-
- <para>The output is determined by cropping and image format
-parameters. The former select an area of the video picture where the
-image will appear, the latter how images are stored in memory, &ie; in
-RGB or YUV format, the number of bits per pixel or width and height.
-Together they also define how images are scaled in the process.</para>
-
- <para>As usual these parameters are <emphasis>not</emphasis> reset
-at &func-open; time to permit Unix tool chains, programming a device
-and then writing to it as if it was a plain file. Well written V4L2
-applications ensure they really get what they want, including cropping
-and scaling.</para>
-
- <para>Cropping initialization at minimum requires to reset the
-parameters to defaults. An example is given in <xref
-linkend="crop" />.</para>
-
- <para>To query the current image format applications set the
-<structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> or
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and call the
-&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-pix-format; <structfield>pix</structfield> or the
-&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
-<structfield>fmt</structfield> union.</para>
-
- <para>To request different parameters applications set the
-<structfield>type</structfield> field of a &v4l2-format; as above and
-initialize all fields of the &v4l2-pix-format;
-<structfield>vbi</structfield> member of the
-<structfield>fmt</structfield> union, or better just modify the
-results of <constant>VIDIOC_G_FMT</constant>, and call the
-&VIDIOC-S-FMT; ioctl with a pointer to this structure. Drivers may
-adjust the parameters and finally return the actual parameters as
-<constant>VIDIOC_G_FMT</constant> does.</para>
-
- <para>Like <constant>VIDIOC_S_FMT</constant> the
-&VIDIOC-TRY-FMT; ioctl can be used to learn about hardware limitations
-without disabling I/O or possibly time consuming hardware
-preparations.</para>
-
- <para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
-are discussed in <xref linkend="pixfmt" />. See also the specification of the
-<constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
-and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
-output devices must implement both the
-<constant>VIDIOC_G_FMT</constant> and
-<constant>VIDIOC_S_FMT</constant> ioctl, even if
-<constant>VIDIOC_S_FMT</constant> ignores all requests and always
-returns default parameters as <constant>VIDIOC_G_FMT</constant> does.
-<constant>VIDIOC_TRY_FMT</constant> is optional.</para>
- </section>
-
- <section>
- <title>Writing Images</title>
-
- <para>A video output device may support the <link
-linkend="rw">write() function</link> and/or streaming (<link
-linkend="mmap">memory mapping</link> or <link
-linkend="userp">user pointer</link>) I/O. See <xref
-linkend="io" /> for details.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-overlay.xml b/Documentation/DocBook/media/v4l/dev-overlay.xml
deleted file mode 100644
index cc6e0c5c960c..000000000000
--- a/Documentation/DocBook/media/v4l/dev-overlay.xml
+++ /dev/null
@@ -1,368 +0,0 @@
- <title>Video Overlay Interface</title>
- <subtitle>Also known as Framebuffer Overlay or Previewing</subtitle>
-
- <para>Video overlay devices have the ability to genlock (TV-)video
-into the (VGA-)video signal of a graphics card, or to store captured
-images directly in video memory of a graphics card, typically with
-clipping. This can be considerable more efficient than capturing
-images and displaying them by other means. In the old days when only
-nuclear power plants needed cooling towers this used to be the only
-way to put live video into a window.</para>
-
- <para>Video overlay devices are accessed through the same character
-special files as <link linkend="capture">video capture</link> devices.
-Note the default function of a <filename>/dev/video</filename> device
-is video capturing. The overlay function is only available after
-calling the &VIDIOC-S-FMT; ioctl.</para>
-
- <para>The driver may support simultaneous overlay and capturing
-using the read/write and streaming I/O methods. If so, operation at
-the nominal frame rate of the video standard is not guaranteed. Frames
-may be directed away from overlay to capture, or one field may be used
-for overlay and the other for capture if the capture parameters permit
-this.</para>
-
- <para>Applications should use different file descriptors for
-capturing and overlay. This must be supported by all drivers capable
-of simultaneous capturing and overlay. Optionally these drivers may
-also permit capturing and overlay with a single file descriptor for
-compatibility with V4L and earlier versions of V4L2.<footnote>
- <para>A common application of two file descriptors is the
-XFree86 <link linkend="xvideo">Xv/V4L</link> interface driver and
-a V4L2 application. While the X server controls video overlay, the
-application can take advantage of memory mapping and DMA.</para>
- <para>In the opinion of the designers of this API, no driver
-writer taking the efforts to support simultaneous capturing and
-overlay will restrict this ability by requiring a single file
-descriptor, as in V4L and earlier versions of V4L2. Making this
-optional means applications depending on two file descriptors need
-backup routines to be compatible with all drivers, which is
-considerable more work than using two fds in applications which do
-not. Also two fd's fit the general concept of one file descriptor for
-each logical stream. Hence as a complexity trade-off drivers
-<emphasis>must</emphasis> support two file descriptors and
-<emphasis>may</emphasis> support single fd operation.</para>
- </footnote></para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the video overlay interface set the
-<constant>V4L2_CAP_VIDEO_OVERLAY</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. The overlay I/O method specified
-below must be supported. Tuners and audio inputs are optional.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>Video overlay devices shall support <link
-linkend="audio">audio input</link>, <link
-linkend="tuner">tuner</link>, <link linkend="control">controls</link>,
-<link linkend="crop">cropping and scaling</link> and <link
-linkend="streaming-par">streaming parameter</link> ioctls as needed.
-The <link linkend="video">video input</link> and <link
-linkend="standard">video standard</link> ioctls must be supported by
-all video overlay devices.</para>
- </section>
-
- <section>
- <title>Setup</title>
-
- <para>Before overlay can commence applications must program the
-driver with frame buffer parameters, namely the address and size of
-the frame buffer and the image format, for example RGB 5:6:5. The
-&VIDIOC-G-FBUF; and &VIDIOC-S-FBUF; ioctls are available to get
-and set these parameters, respectively. The
-<constant>VIDIOC_S_FBUF</constant> ioctl is privileged because it
-allows to set up DMA into physical memory, bypassing the memory
-protection mechanisms of the kernel. Only the superuser can change the
-frame buffer address and size. Users are not supposed to run TV
-applications as root or with SUID bit set. A small helper application
-with suitable privileges should query the graphics system and program
-the V4L2 driver at the appropriate time.</para>
-
- <para>Some devices add the video overlay to the output signal
-of the graphics card. In this case the frame buffer is not modified by
-the video device, and the frame buffer address and pixel format are
-not needed by the driver. The <constant>VIDIOC_S_FBUF</constant> ioctl
-is not privileged. An application can check for this type of device by
-calling the <constant>VIDIOC_G_FBUF</constant> ioctl.</para>
-
- <para>A driver may support any (or none) of five clipping/blending
-methods:<orderedlist>
- <listitem>
- <para>Chroma-keying displays the overlaid image only where
-pixels in the primary graphics surface assume a certain color.</para>
- </listitem>
- <listitem>
- <para>A bitmap can be specified where each bit corresponds
-to a pixel in the overlaid image. When the bit is set, the
-corresponding video pixel is displayed, otherwise a pixel of the
-graphics surface.</para>
- </listitem>
- <listitem>
- <para>A list of clipping rectangles can be specified. In
-these regions <emphasis>no</emphasis> video is displayed, so the
-graphics surface can be seen here.</para>
- </listitem>
- <listitem>
- <para>The framebuffer has an alpha channel that can be used
-to clip or blend the framebuffer with the video.</para>
- </listitem>
- <listitem>
- <para>A global alpha value can be specified to blend the
-framebuffer contents with video images.</para>
- </listitem>
- </orderedlist></para>
-
- <para>When simultaneous capturing and overlay is supported and
-the hardware prohibits different image and frame buffer formats, the
-format requested first takes precedence. The attempt to capture
-(&VIDIOC-S-FMT;) or overlay (&VIDIOC-S-FBUF;) may fail with an
-&EBUSY; or return accordingly modified parameters..</para>
- </section>
-
- <section>
- <title>Overlay Window</title>
-
- <para>The overlaid image is determined by cropping and overlay
-window parameters. The former select an area of the video picture to
-capture, the latter how images are overlaid and clipped. Cropping
-initialization at minimum requires to reset the parameters to
-defaults. An example is given in <xref linkend="crop" />.</para>
-
- <para>The overlay window is described by a &v4l2-window;. It
-defines the size of the image, its position over the graphics surface
-and the clipping to be applied. To get the current parameters
-applications set the <structfield>type</structfield> field of a
-&v4l2-format; to <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant> and
-call the &VIDIOC-G-FMT; ioctl. The driver fills the
-<structname>v4l2_window</structname> substructure named
-<structfield>win</structfield>. It is not possible to retrieve a
-previously programmed clipping list or bitmap.</para>
-
- <para>To program the overlay window applications set the
-<structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, initialize the
-<structfield>win</structfield> substructure and call the
-&VIDIOC-S-FMT; ioctl. The driver adjusts the parameters against
-hardware limits and returns the actual parameters as
-<constant>VIDIOC_G_FMT</constant> does. Like
-<constant>VIDIOC_S_FMT</constant>, the &VIDIOC-TRY-FMT; ioctl can be
-used to learn about driver capabilities without actually changing
-driver state. Unlike <constant>VIDIOC_S_FMT</constant> this also works
-after the overlay has been enabled.</para>
-
- <para>The scaling factor of the overlaid image is implied by the
-width and height given in &v4l2-window; and the size of the cropping
-rectangle. For more information see <xref linkend="crop" />.</para>
-
- <para>When simultaneous capturing and overlay is supported and
-the hardware prohibits different image and window sizes, the size
-requested first takes precedence. The attempt to capture or overlay as
-well (&VIDIOC-S-FMT;) may fail with an &EBUSY; or return accordingly
-modified parameters.</para>
-
- <table pgwide="1" frame="none" id="v4l2-window">
- <title>struct <structname>v4l2_window</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>w</structfield></entry>
- <entry>Size and position of the window relative to the
-top, left corner of the frame buffer defined with &VIDIOC-S-FBUF;. The
-window can extend the frame buffer width and height, the
-<structfield>x</structfield> and <structfield>y</structfield>
-coordinates can be negative, and it can lie completely outside the
-frame buffer. The driver clips the window accordingly, or if that is
-not possible, modifies its size and/or position.</entry>
- </row>
- <row>
- <entry>&v4l2-field;</entry>
- <entry><structfield>field</structfield></entry>
- <entry>Applications set this field to determine which
-video field shall be overlaid, typically one of
-<constant>V4L2_FIELD_ANY</constant> (0),
-<constant>V4L2_FIELD_TOP</constant>,
-<constant>V4L2_FIELD_BOTTOM</constant> or
-<constant>V4L2_FIELD_INTERLACED</constant>. Drivers may have to choose
-a different field order and return the actual setting here.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>chromakey</structfield></entry>
- <entry>When chroma-keying has been negotiated with
-&VIDIOC-S-FBUF; applications set this field to the desired pixel value
-for the chroma key. The format is the same as the pixel format of the
-framebuffer (&v4l2-framebuffer;
-<structfield>fmt.pixelformat</structfield> field), with bytes in host
-order. E.&nbsp;g. for <link
-linkend="V4L2-PIX-FMT-BGR32"><constant>V4L2_PIX_FMT_BGR24</constant></link>
-the value should be 0xRRGGBB on a little endian, 0xBBGGRR on a big
-endian host.</entry>
- </row>
- <row>
- <entry>&v4l2-clip; *</entry>
- <entry><structfield>clips</structfield></entry>
- <entry>When chroma-keying has <emphasis>not</emphasis>
-been negotiated and &VIDIOC-G-FBUF; indicated this capability,
-applications can set this field to point to an array of
-clipping rectangles.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Like the window coordinates
-<structfield>w</structfield>, clipping rectangles are defined relative
-to the top, left corner of the frame buffer. However clipping
-rectangles must not extend the frame buffer width and height, and they
-must not overlap. If possible applications should merge adjacent
-rectangles. Whether this must create x-y or y-x bands, or the order of
-rectangles, is not defined. When clip lists are not supported the
-driver ignores this field. Its contents after calling &VIDIOC-S-FMT;
-are undefined.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>clipcount</structfield></entry>
- <entry>When the application set the
-<structfield>clips</structfield> field, this field must contain the
-number of clipping rectangles in the list. When clip lists are not
-supported the driver ignores this field, its contents after calling
-<constant>VIDIOC_S_FMT</constant> are undefined. When clip lists are
-supported but no clipping is desired this field must be set to
-zero.</entry>
- </row>
- <row>
- <entry>void *</entry>
- <entry><structfield>bitmap</structfield></entry>
- <entry>When chroma-keying has
-<emphasis>not</emphasis> been negotiated and &VIDIOC-G-FBUF; indicated
-this capability, applications can set this field to point to a
-clipping bit mask.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>It must be of the same size
-as the window, <structfield>w.width</structfield> and
-<structfield>w.height</structfield>. Each bit corresponds to a pixel
-in the overlaid image, which is displayed only when the bit is
-<emphasis>set</emphasis>. Pixel coordinates translate to bits like:
-<programlisting>
-((__u8 *) <structfield>bitmap</structfield>)[<structfield>w.width</structfield> * y + x / 8] &amp; (1 &lt;&lt; (x &amp; 7))</programlisting></para><para>where <structfield>0</structfield> &le; x &lt;
-<structfield>w.width</structfield> and <structfield>0</structfield> &le;
-y &lt;<structfield>w.height</structfield>.<footnote>
- <para>Should we require
- <structfield>w.width</structfield> to be a multiple of
- eight?</para>
- </footnote></para><para>When a clipping
-bit mask is not supported the driver ignores this field, its contents
-after calling &VIDIOC-S-FMT; are undefined. When a bit mask is supported
-but no clipping is desired this field must be set to
-<constant>NULL</constant>.</para><para>Applications need not create a
-clip list or bit mask. When they pass both, or despite negotiating
-chroma-keying, the results are undefined. Regardless of the chosen
-method, the clipping abilities of the hardware may be limited in
-quantity or quality. The results when these limits are exceeded are
-undefined.<footnote>
- <para>When the image is written into frame buffer
-memory it will be undesirable if the driver clips out less pixels
-than expected, because the application and graphics system are not
-aware these regions need to be refreshed. The driver should clip out
-more pixels or not write the image at all.</para>
- </footnote></para></entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>global_alpha</structfield></entry>
- <entry>The global alpha value used to blend the
-framebuffer with video images, if global alpha blending has been
-negotiated (<constant>V4L2_FBUF_FLAG_GLOBAL_ALPHA</constant>, see
-&VIDIOC-S-FBUF;, <xref linkend="framebuffer-flags" />).</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Note this field was added in Linux 2.6.23, extending the structure. However
-the <link linkend="vidioc-g-fmt">VIDIOC_G/S/TRY_FMT</link> ioctls,
-which take a pointer to a <link
-linkend="v4l2-format">v4l2_format</link> parent structure with padding
-bytes at the end, are not affected.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-clip">
- <title>struct <structname>v4l2_clip</structname><footnote>
- <para>The X Window system defines "regions" which are
-vectors of struct BoxRec { short x1, y1, x2, y2; } with width = x2 -
-x1 and height = y2 - y1, so one cannot pass X11 clip lists
-directly.</para>
- </footnote></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>c</structfield></entry>
- <entry>Coordinates of the clipping rectangle, relative to
-the top, left corner of the frame buffer. Only window pixels
-<emphasis>outside</emphasis> all clipping rectangles are
-displayed.</entry>
- </row>
- <row>
- <entry>&v4l2-clip; *</entry>
- <entry><structfield>next</structfield></entry>
- <entry>Pointer to the next clipping rectangle, NULL when
-this is the last rectangle. Drivers ignore this field, it cannot be
-used to pass a linked list of clipping rectangles.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- NB for easier reading this table is duplicated
- in the vidioc-cropcap chapter.-->
-
- <table pgwide="1" frame="none" id="v4l2-rect">
- <title>struct <structname>v4l2_rect</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__s32</entry>
- <entry><structfield>left</structfield></entry>
- <entry>Horizontal offset of the top, left corner of the
-rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>top</structfield></entry>
- <entry>Vertical offset of the top, left corner of the
-rectangle, in pixels. Offsets increase to the right and down.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Width of the rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Height of the rectangle, in pixels.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Enabling Overlay</title>
-
- <para>To start or stop the frame buffer overlay applications call
-the &VIDIOC-OVERLAY; ioctl.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-radio.xml b/Documentation/DocBook/media/v4l/dev-radio.xml
deleted file mode 100644
index 3e6ac73b36af..000000000000
--- a/Documentation/DocBook/media/v4l/dev-radio.xml
+++ /dev/null
@@ -1,49 +0,0 @@
- <title>Radio Interface</title>
-
- <para>This interface is intended for AM and FM (analog) radio
-receivers and transmitters.</para>
-
- <para>Conventionally V4L2 radio devices are accessed through
-character device special files named <filename>/dev/radio</filename>
-and <filename>/dev/radio0</filename> to
-<filename>/dev/radio63</filename> with major number 81 and minor
-numbers 64 to 127.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the radio interface set the
-<constant>V4L2_CAP_RADIO</constant> and
-<constant>V4L2_CAP_TUNER</constant> or
-<constant>V4L2_CAP_MODULATOR</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. Other combinations of
-capability flags are reserved for future extensions.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>Radio devices can support <link
-linkend="control">controls</link>, and must support the <link
-linkend="tuner">tuner or modulator</link> ioctls.</para>
-
- <para>They do not support the video input or output, audio input
-or output, video standard, cropping and scaling, compression and
-streaming parameter, or overlay ioctls. All other ioctls and I/O
-methods are reserved for future extensions.</para>
- </section>
-
- <section>
- <title>Programming</title>
-
- <para>Radio devices may have a couple audio controls (as discussed
-in <xref linkend="control" />) such as a volume control, possibly custom
-controls. Further all radio devices have one tuner or modulator (these are
-discussed in <xref linkend="tuner" />) with index number zero to select
-the radio frequency and to determine if a monaural or FM stereo
-program is received/emitted. Drivers switch automatically between AM and FM
-depending on the selected frequency. The &VIDIOC-G-TUNER; or
-&VIDIOC-G-MODULATOR; ioctl
-reports the supported frequency range.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml b/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
deleted file mode 100644
index 78599bbd58f7..000000000000
--- a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
+++ /dev/null
@@ -1,345 +0,0 @@
- <title>Raw VBI Data Interface</title>
-
- <para>VBI is an abbreviation of Vertical Blanking Interval, a gap
-in the sequence of lines of an analog video signal. During VBI
-no picture information is transmitted, allowing some time while the
-electron beam of a cathode ray tube TV returns to the top of the
-screen. Using an oscilloscope you will find here the vertical
-synchronization pulses and short data packages ASK
-modulated<footnote><para>ASK: Amplitude-Shift Keying. A high signal
-level represents a '1' bit, a low level a '0' bit.</para></footnote>
-onto the video signal. These are transmissions of services such as
-Teletext or Closed Caption.</para>
-
- <para>Subject of this interface type is raw VBI data, as sampled off
-a video signal, or to be added to a signal for output.
-The data format is similar to uncompressed video images, a number of
-lines times a number of samples per line, we call this a VBI image.</para>
-
- <para>Conventionally V4L2 VBI devices are accessed through character
-device special files named <filename>/dev/vbi</filename> and
-<filename>/dev/vbi0</filename> to <filename>/dev/vbi31</filename> with
-major number 81 and minor numbers 224 to 255.
-<filename>/dev/vbi</filename> is typically a symbolic link to the
-preferred VBI device. This convention applies to both input and output
-devices.</para>
-
- <para>To address the problems of finding related video and VBI
-devices VBI capturing and output is also available as device function
-under <filename>/dev/video</filename>. To capture or output raw VBI
-data with these devices applications must call the &VIDIOC-S-FMT;
-ioctl. Accessed as <filename>/dev/vbi</filename>, raw VBI capturing
-or output is the default device function.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the raw VBI capturing or output API set
-the <constant>V4L2_CAP_VBI_CAPTURE</constant> or
-<constant>V4L2_CAP_VBI_OUTPUT</constant> flags, respectively, in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. At least one of the
-read/write, streaming or asynchronous I/O methods must be
-supported. VBI devices may or may not have a tuner or modulator.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>VBI devices shall support <link linkend="video">video
-input or output</link>, <link linkend="tuner">tuner or
-modulator</link>, and <link linkend="control">controls</link> ioctls
-as needed. The <link linkend="standard">video standard</link> ioctls provide
-information vital to program a VBI device, therefore must be
-supported.</para>
- </section>
-
- <section>
- <title>Raw VBI Format Negotiation</title>
-
- <para>Raw VBI sampling abilities can vary, in particular the
-sampling frequency. To properly interpret the data V4L2 specifies an
-ioctl to query the sampling parameters. Moreover, to allow for some
-flexibility applications can also suggest different parameters.</para>
-
- <para>As usual these parameters are <emphasis>not</emphasis>
-reset at &func-open; time to permit Unix tool chains, programming a
-device and then reading from it as if it was a plain file. Well
-written V4L2 applications should always ensure they really get what
-they want, requesting reasonable parameters and then checking if the
-actual parameters are suitable.</para>
-
- <para>To query the current raw VBI capture parameters
-applications set the <structfield>type</structfield> field of a
-&v4l2-format; to <constant>V4L2_BUF_TYPE_VBI_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>, and call the
-&VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-vbi-format; <structfield>vbi</structfield> member of the
-<structfield>fmt</structfield> union.</para>
-
- <para>To request different parameters applications set the
-<structfield>type</structfield> field of a &v4l2-format; as above and
-initialize all fields of the &v4l2-vbi-format;
-<structfield>vbi</structfield> member of the
-<structfield>fmt</structfield> union, or better just modify the
-results of <constant>VIDIOC_G_FMT</constant>, and call the
-&VIDIOC-S-FMT; ioctl with a pointer to this structure. Drivers return
-an &EINVAL; only when the given parameters are ambiguous, otherwise
-they modify the parameters according to the hardware capabilities and
-return the actual parameters. When the driver allocates resources at
-this point, it may return an &EBUSY; to indicate the returned
-parameters are valid but the required resources are currently not
-available. That may happen for instance when the video and VBI areas
-to capture would overlap, or when the driver supports multiple opens
-and another process already requested VBI capturing or output. Anyway,
-applications must expect other resource allocation points which may
-return <errorcode>EBUSY</errorcode>, at the &VIDIOC-STREAMON; ioctl
-and the first read(), write() and select() call.</para>
-
- <para>VBI devices must implement both the
-<constant>VIDIOC_G_FMT</constant> and
-<constant>VIDIOC_S_FMT</constant> ioctl, even if
-<constant>VIDIOC_S_FMT</constant> ignores all requests and always
-returns default parameters as <constant>VIDIOC_G_FMT</constant> does.
-<constant>VIDIOC_TRY_FMT</constant> is optional.</para>
-
- <table pgwide="1" frame="none" id="v4l2-vbi-format">
- <title>struct <structname>v4l2_vbi_format</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>sampling_rate</structfield></entry>
- <entry>Samples per second, i.&nbsp;e. unit 1 Hz.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>offset</structfield></entry>
- <entry><para>Horizontal offset of the VBI image,
-relative to the leading edge of the line synchronization pulse and
-counted in samples: The first sample in the VBI image will be located
-<structfield>offset</structfield> /
-<structfield>sampling_rate</structfield> seconds following the leading
-edge. See also <xref linkend="vbi-hsync" />.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>samples_per_line</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sample_format</structfield></entry>
- <entry><para>Defines the sample format as in <xref
-linkend="pixfmt" />, a four-character-code.<footnote>
- <para>A few devices may be unable to
-sample VBI data at all but can extend the video capture window to the
-VBI region.</para>
- </footnote> Usually this is
-<constant>V4L2_PIX_FMT_GREY</constant>, i.&nbsp;e. each sample
-consists of 8 bits with lower values oriented towards the black level.
-Do not assume any other correlation of values with the signal level.
-For example, the MSB does not necessarily indicate if the signal is
-'high' or 'low' because 128 may not be the mean value of the
-signal. Drivers shall not convert the sample format by software.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>start</structfield>[2]</entry>
- <entry>This is the scanning system line number
-associated with the first line of the VBI image, of the first and the
-second field respectively. See <xref linkend="vbi-525" /> and
-<xref linkend="vbi-625" /> for valid values.
-The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
-<constant>V4L2_VBI_ITU_525_F2_START</constant>,
-<constant>V4L2_VBI_ITU_625_F1_START</constant> and
-<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start line
-numbers for each field for each 525 or 625 line format as a convenience.
-Don't forget that ITU line numbering starts at 1, not 0.
-VBI input drivers can return start values 0 if the hardware cannot
-reliable identify scanning lines, VBI acquisition may not require this
-information.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>count</structfield>[2]</entry>
- <entry>The number of lines in the first and second
-field image, respectively.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>Drivers should be as
-flexibility as possible. For example, it may be possible to extend or
-move the VBI capture window down to the picture area, implementing a
-'full field mode' to capture data service transmissions embedded in
-the picture.</para><para>An application can set the first or second
-<structfield>count</structfield> value to zero if no data is required
-from the respective field; <structfield>count</structfield>[1] if the
-scanning system is progressive, &ie; not interlaced. The
-corresponding start value shall be ignored by the application and
-driver. Anyway, drivers may not support single field capturing and
-return both count values non-zero.</para><para>Both
-<structfield>count</structfield> values set to zero, or line numbers
-outside the bounds depicted in <xref linkend="vbi-525" /> and <xref
- linkend="vbi-625" />, or a field image covering
-lines of two fields, are invalid and shall not be returned by the
-driver.</para><para>To initialize the <structfield>start</structfield>
-and <structfield>count</structfield> fields, applications must first
-determine the current video standard selection. The &v4l2-std-id; or
-the <structfield>framelines</structfield> field of &v4l2-standard; can
-be evaluated for this purpose.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>See <xref linkend="vbifmt-flags" /> below. Currently
-only drivers set flags, applications must set this field to
-zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>This array is reserved for future extensions.
-Drivers and applications must set it to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="vbifmt-flags">
- <title>Raw VBI Format Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_VBI_UNSYNC</constant></entry>
- <entry>0x0001</entry>
- <entry><para>This flag indicates hardware which does not
-properly distinguish between fields. Normally the VBI image stores the
-first field (lower scanning line numbers) first in memory. This may be
-a top or bottom field depending on the video standard. When this flag
-is set the first or second field may be stored first, however the
-fields are still in correct temporal order with the older field first
-in memory.<footnote>
- <para>Most VBI services transmit on both fields, but
-some have different semantics depending on the field number. These
-cannot be reliable decoded or encoded when
-<constant>V4L2_VBI_UNSYNC</constant> is set.</para>
- </footnote></para></entry>
- </row>
- <row>
- <entry><constant>V4L2_VBI_INTERLACED</constant></entry>
- <entry>0x0002</entry>
- <entry>By default the two field images will be passed
-sequentially; all lines of the first field followed by all lines of
-the second field (compare <xref linkend="field-order" />
-<constant>V4L2_FIELD_SEQ_TB</constant> and
-<constant>V4L2_FIELD_SEQ_BT</constant>, whether the top or bottom
-field is first in memory depends on the video standard). When this
-flag is set, the two fields are interlaced (cf.
-<constant>V4L2_FIELD_INTERLACED</constant>). The first line of the
-first field followed by the first line of the second field, then the
-two second lines, and so on. Such a layout may be necessary when the
-hardware has been programmed to capture or output interlaced video
-images and is unable to separate the fields for VBI capturing at
-the same time. For simplicity setting this flag implies that both
-<structfield>count</structfield> values are equal and non-zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <figure id="vbi-hsync">
- <title>Line synchronization</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="vbi_hsync.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="vbi_hsync.gif" format="GIF" />
- </imageobject>
- <textobject>
- <phrase>Line synchronization diagram</phrase>
- </textobject>
- </mediaobject>
- </figure>
-
- <figure id="vbi-525">
- <title>ITU-R 525 line numbering (M/NTSC and M/PAL)</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="vbi_525.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="vbi_525.gif" format="GIF" />
- </imageobject>
- <textobject>
- <phrase>NTSC field synchronization diagram</phrase>
- </textobject>
- <caption>
- <para>(1) For the purpose of this specification field 2
-starts in line 264 and not 263.5 because half line capturing is not
-supported.</para>
- </caption>
- </mediaobject>
- </figure>
-
- <figure id="vbi-625">
- <title>ITU-R 625 line numbering</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="vbi_625.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="vbi_625.gif" format="GIF" />
- </imageobject>
- <textobject>
- <phrase>PAL/SECAM field synchronization diagram</phrase>
- </textobject>
- <caption>
- <para>(1) For the purpose of this specification field 2
-starts in line 314 and not 313.5 because half line capturing is not
-supported.</para>
- </caption>
- </mediaobject>
- </figure>
-
- <para>Remember the VBI image format depends on the selected
-video standard, therefore the application must choose a new standard or
-query the current standard first. Attempts to read or write data ahead
-of format negotiation, or after switching the video standard which may
-invalidate the negotiated VBI parameters, should be refused by the
-driver. A format change during active I/O is not permitted.</para>
- </section>
-
- <section>
- <title>Reading and writing VBI images</title>
-
- <para>To assure synchronization with the field number and easier
-implementation, the smallest unit of data passed at a time is one
-frame, consisting of two fields of VBI images immediately following in
-memory.</para>
-
- <para>The total size of a frame computes as follows:</para>
-
- <programlisting>
-(<structfield>count</structfield>[0] + <structfield>count</structfield>[1]) *
-<structfield>samples_per_line</structfield> * sample size in bytes</programlisting>
-
- <para>The sample size is most likely always one byte,
-applications must check the <structfield>sample_format</structfield>
-field though, to function properly with other drivers.</para>
-
- <para>A VBI device may support <link
- linkend="rw">read/write</link> and/or streaming (<link
- linkend="mmap">memory mapping</link> or <link
- linkend="userp">user pointer</link>) I/O. The latter bears the
-possibility of synchronizing video and
-VBI data by using buffer timestamps.</para>
-
- <para>Remember the &VIDIOC-STREAMON; ioctl and the first read(),
-write() and select() call can be resource allocation points returning
-an &EBUSY; if the required hardware resources are temporarily
-unavailable, for example the device is already in use by another
-process.</para>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-rds.xml b/Documentation/DocBook/media/v4l/dev-rds.xml
deleted file mode 100644
index be2f33737323..000000000000
--- a/Documentation/DocBook/media/v4l/dev-rds.xml
+++ /dev/null
@@ -1,196 +0,0 @@
- <title>RDS Interface</title>
-
- <para>The Radio Data System transmits supplementary
-information in binary format, for example the station name or travel
-information, on an inaudible audio subcarrier of a radio program. This
-interface is aimed at devices capable of receiving and/or transmitting RDS
-information.</para>
-
- <para>For more information see the core RDS standard <xref linkend="iec62106" />
-and the RBDS standard <xref linkend="nrsc4" />.</para>
-
- <para>Note that the RBDS standard as is used in the USA is almost identical
-to the RDS standard. Any RDS decoder/encoder can also handle RBDS. Only some of the
-fields have slightly different meanings. See the RBDS standard for more
-information.</para>
-
- <para>The RBDS standard also specifies support for MMBS (Modified Mobile Search).
-This is a proprietary format which seems to be discontinued. The RDS interface does not
-support this format. Should support for MMBS (or the so-called 'E blocks' in general)
-be needed, then please contact the linux-media mailing list: &v4l-ml;.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the RDS capturing API set
-the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
-the <structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. Any tuner that supports RDS
-will set the <constant>V4L2_TUNER_CAP_RDS</constant> flag in
-the <structfield>capability</structfield> field of &v4l2-tuner;. If
-the driver only passes RDS blocks without interpreting the data
-the <constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant> flag has to be
-set, see <link linkend="reading-rds-data">Reading RDS data</link>.
-For future use the
-flag <constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant> has also been
-defined. However, a driver for a radio tuner with this capability does
-not yet exist, so if you are planning to write such a driver you
-should discuss this on the linux-media mailing list: &v4l-ml;.</para>
-
- <para> Whether an RDS signal is present can be detected by looking
-at the <structfield>rxsubchans</structfield> field of &v4l2-tuner;:
-the <constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data
-was detected.</para>
-
- <para>Devices supporting the RDS output API
-set the <constant>V4L2_CAP_RDS_OUTPUT</constant> flag in
-the <structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl.
-Any modulator that supports RDS will set the
-<constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
-field of &v4l2-modulator;.
-In order to enable the RDS transmission one must set the <constant>V4L2_TUNER_SUB_RDS</constant>
-bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.
-If the driver only passes RDS blocks without interpreting the data
-the <constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant> flag has to be set. If the
-tuner is capable of handling RDS entities like program identification codes and radio
-text, the flag <constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant> should be set,
-see <link linkend="writing-rds-data">Writing RDS data</link> and
-<link linkend="fm-tx-controls">FM Transmitter Control Reference</link>.</para>
- </section>
-
- <section id="reading-rds-data">
- <title>Reading RDS data</title>
-
- <para>RDS data can be read from the radio device
-with the &func-read; function. The data is packed in groups of three bytes.</para>
- </section>
-
- <section id="writing-rds-data">
- <title>Writing RDS data</title>
-
- <para>RDS data can be written to the radio device
-with the &func-write; function. The data is packed in groups of three bytes,
-as follows:</para>
- </section>
-
- <section>
- <title>RDS datastructures</title>
- <table frame="none" pgwide="1" id="v4l2-rds-data">
- <title>struct
-<structname>v4l2_rds_data</structname></title>
- <tgroup cols="3">
- <colspec colname="c1" colwidth="1*" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colname="c3" colwidth="5*" />
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>lsb</structfield></entry>
- <entry>Least Significant Byte of RDS Block</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>msb</structfield></entry>
- <entry>Most Significant Byte of RDS Block</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>block</structfield></entry>
- <entry>Block description</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table frame="none" pgwide="1" id="v4l2-rds-block">
- <title>Block description</title>
- <tgroup cols="2">
- <colspec colname="c1" colwidth="1*" />
- <colspec colname="c2" colwidth="5*" />
- <tbody valign="top">
- <row>
- <entry>Bits 0-2</entry>
- <entry>Block (aka offset) of the received data.</entry>
- </row>
- <row>
- <entry>Bits 3-5</entry>
- <entry>Deprecated. Currently identical to bits 0-2. Do not use these bits.</entry>
- </row>
- <row>
- <entry>Bit 6</entry>
- <entry>Corrected bit. Indicates that an error was corrected for this data block.</entry>
- </row>
- <row>
- <entry>Bit 7</entry>
- <entry>Error bit. Indicates that an uncorrectable error occurred during reception of this block.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-rds-block-codes">
- <title>Block defines</title>
- <tgroup cols="4">
- <colspec colname="c1" colwidth="1*" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colname="c3" colwidth="1*" />
- <colspec colname="c4" colwidth="5*" />
- <tbody valign="top">
- <row>
- <entry>V4L2_RDS_BLOCK_MSK</entry>
- <entry> </entry>
- <entry>7</entry>
- <entry>Mask for bits 0-2 to get the block ID.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_A</entry>
- <entry> </entry>
- <entry>0</entry>
- <entry>Block A.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_B</entry>
- <entry> </entry>
- <entry>1</entry>
- <entry>Block B.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_C</entry>
- <entry> </entry>
- <entry>2</entry>
- <entry>Block C.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_D</entry>
- <entry> </entry>
- <entry>3</entry>
- <entry>Block D.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_C_ALT</entry>
- <entry> </entry>
- <entry>4</entry>
- <entry>Block C'.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_INVALID</entry>
- <entry>read-only</entry>
- <entry>7</entry>
- <entry>An invalid block.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_CORRECTED</entry>
- <entry>read-only</entry>
- <entry>0x40</entry>
- <entry>A bit error was detected but corrected.</entry>
- </row>
- <row>
- <entry>V4L2_RDS_BLOCK_ERROR</entry>
- <entry>read-only</entry>
- <entry>0x80</entry>
- <entry>An uncorrectable error occurred.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml
deleted file mode 100644
index 6da1157fb5bd..000000000000
--- a/Documentation/DocBook/media/v4l/dev-sdr.xml
+++ /dev/null
@@ -1,126 +0,0 @@
- <title>Software Defined Radio Interface (SDR)</title>
-
- <para>
-SDR is an abbreviation of Software Defined Radio, the radio device
-which uses application software for modulation or demodulation. This interface
-is intended for controlling and data streaming of such devices.
- </para>
-
- <para>
-SDR devices are accessed through character device special files named
-<filename>/dev/swradio0</filename> to <filename>/dev/swradio255</filename>
-with major number 81 and dynamically allocated minor numbers 0 to 255.
- </para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>
-Devices supporting the SDR receiver interface set the
-<constant>V4L2_CAP_SDR_CAPTURE</constant> and
-<constant>V4L2_CAP_TUNER</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. That flag means the device has an
-Analog to Digital Converter (ADC), which is a mandatory element for the SDR receiver.
- </para>
- <para>
-Devices supporting the SDR transmitter interface set the
-<constant>V4L2_CAP_SDR_OUTPUT</constant> and
-<constant>V4L2_CAP_MODULATOR</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. That flag means the device has an
-Digital to Analog Converter (DAC), which is a mandatory element for the SDR transmitter.
- </para>
- <para>
-At least one of the read/write, streaming or asynchronous I/O methods must
-be supported.
- </para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>
-SDR devices can support <link linkend="control">controls</link>, and must
-support the <link linkend="tuner">tuner</link> ioctls. Tuner ioctls are used
-for setting the ADC/DAC sampling rate (sampling frequency) and the possible
-radio frequency (RF).
- </para>
-
- <para>
-The <constant>V4L2_TUNER_SDR</constant> tuner type is used for setting SDR
-device ADC/DAC frequency, and the <constant>V4L2_TUNER_RF</constant>
-tuner type is used for setting radio frequency.
-The tuner index of the RF tuner (if any) must always follow the SDR tuner index.
-Normally the SDR tuner is #0 and the RF tuner is #1.
- </para>
-
- <para>
-The &VIDIOC-S-HW-FREQ-SEEK; ioctl is not supported.
- </para>
- </section>
-
- <section>
- <title>Data Format Negotiation</title>
-
- <para>
-The SDR device uses the <link linkend="format">format</link> ioctls to
-select the capture and output format. Both the sampling resolution and the data
-streaming format are bound to that selectable format. In addition to the basic
-<link linkend="format">format</link> ioctls, the &VIDIOC-ENUM-FMT; ioctl
-must be supported as well.
- </para>
-
- <para>
-To use the <link linkend="format">format</link> ioctls applications set the
-<structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_SDR_OUTPUT</constant> and use the &v4l2-sdr-format;
-<structfield>sdr</structfield> member of the <structfield>fmt</structfield>
-union as needed per the desired operation.
-Currently there is two fields, <structfield>pixelformat</structfield> and
-<structfield>buffersize</structfield>, of struct &v4l2-sdr-format; which are
-used. Content of the <structfield>pixelformat</structfield> is V4L2 FourCC
-code of the data format. The <structfield>buffersize</structfield> field is
-maximum buffer size in bytes required for data transfer, set by the driver in
-order to inform application.
- </para>
-
- <table pgwide="1" frame="none" id="v4l2-sdr-format">
- <title>struct <structname>v4l2_sdr_format</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixelformat</structfield></entry>
- <entry>
-The data format or type of compression, set by the application. This is a
-little endian <link linkend="v4l2-fourcc">four character code</link>.
-V4L2 defines SDR formats in <xref linkend="sdr-formats" />.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>buffersize</structfield></entry>
- <entry>
-Maximum size in bytes required for data. Value is set by the driver.
- </entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>reserved[24]</structfield></entry>
- <entry>This array is reserved for future extensions.
-Drivers and applications must set it to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
-An SDR device may support <link linkend="rw">read/write</link>
-and/or streaming (<link linkend="mmap">memory mapping</link>
-or <link linkend="userp">user pointer</link>) I/O.
- </para>
-
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml b/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
deleted file mode 100644
index 0aec62ed2bf8..000000000000
--- a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
+++ /dev/null
@@ -1,706 +0,0 @@
- <title>Sliced VBI Data Interface</title>
-
- <para>VBI stands for Vertical Blanking Interval, a gap in the
-sequence of lines of an analog video signal. During VBI no picture
-information is transmitted, allowing some time while the electron beam
-of a cathode ray tube TV returns to the top of the screen.</para>
-
- <para>Sliced VBI devices use hardware to demodulate data transmitted
-in the VBI. V4L2 drivers shall <emphasis>not</emphasis> do this by
-software, see also the <link linkend="raw-vbi">raw VBI
-interface</link>. The data is passed as short packets of fixed size,
-covering one scan line each. The number of packets per video frame is
-variable.</para>
-
- <para>Sliced VBI capture and output devices are accessed through the
-same character special files as raw VBI devices. When a driver
-supports both interfaces, the default function of a
-<filename>/dev/vbi</filename> device is <emphasis>raw</emphasis> VBI
-capturing or output, and the sliced VBI function is only available
-after calling the &VIDIOC-S-FMT; ioctl as defined below. Likewise a
-<filename>/dev/video</filename> device may support the sliced VBI API,
-however the default function here is video capturing or output.
-Different file descriptors must be used to pass raw and sliced VBI
-data simultaneously, if this is supported by the driver.</para>
-
- <section>
- <title>Querying Capabilities</title>
-
- <para>Devices supporting the sliced VBI capturing or output API
-set the <constant>V4L2_CAP_SLICED_VBI_CAPTURE</constant> or
-<constant>V4L2_CAP_SLICED_VBI_OUTPUT</constant> flag respectively, in
-the <structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl. At least one of the
-read/write, streaming or asynchronous <link linkend="io">I/O
-methods</link> must be supported. Sliced VBI devices may have a tuner
-or modulator.</para>
- </section>
-
- <section>
- <title>Supplemental Functions</title>
-
- <para>Sliced VBI devices shall support <link linkend="video">video
-input or output</link> and <link linkend="tuner">tuner or
-modulator</link> ioctls if they have these capabilities, and they may
-support <link linkend="control">control</link> ioctls. The <link
-linkend="standard">video standard</link> ioctls provide information
-vital to program a sliced VBI device, therefore must be
-supported.</para>
- </section>
-
- <section id="sliced-vbi-format-negotitation">
- <title>Sliced VBI Format Negotiation</title>
-
- <para>To find out which data services are supported by the
-hardware applications can call the &VIDIOC-G-SLICED-VBI-CAP; ioctl.
-All drivers implementing the sliced VBI interface must support this
-ioctl. The results may differ from those of the &VIDIOC-S-FMT; ioctl
-when the number of VBI lines the hardware can capture or output per
-frame, or the number of services it can identify on a given line are
-limited. For example on PAL line 16 the hardware may be able to look
-for a VPS or Teletext signal, but not both at the same time.</para>
-
- <para>To determine the currently selected services applications
-set the <structfield>type </structfield> field of &v4l2-format; to
-<constant> V4L2_BUF_TYPE_SLICED_VBI_CAPTURE</constant> or <constant>
-V4L2_BUF_TYPE_SLICED_VBI_OUTPUT</constant>, and the &VIDIOC-G-FMT;
-ioctl fills the <structfield>fmt.sliced</structfield> member, a
-&v4l2-sliced-vbi-format;.</para>
-
- <para>Applications can request different parameters by
-initializing or modifying the <structfield>fmt.sliced</structfield>
-member and calling the &VIDIOC-S-FMT; ioctl with a pointer to the
-<structname>v4l2_format</structname> structure.</para>
-
- <para>The sliced VBI API is more complicated than the raw VBI API
-because the hardware must be told which VBI service to expect on each
-scan line. Not all services may be supported by the hardware on all
-lines (this is especially true for VBI output where Teletext is often
-unsupported and other services can only be inserted in one specific
-line). In many cases, however, it is sufficient to just set the
-<structfield>service_set</structfield> field to the required services
-and let the driver fill the <structfield>service_lines</structfield>
-array according to hardware capabilities. Only if more precise control
-is needed should the programmer set the
-<structfield>service_lines</structfield> array explicitly.</para>
-
- <para>The &VIDIOC-S-FMT; ioctl modifies the parameters
-according to hardware capabilities. When the driver allocates
-resources at this point, it may return an &EBUSY; if the required
-resources are temporarily unavailable. Other resource allocation
-points which may return <errorcode>EBUSY</errorcode> can be the
-&VIDIOC-STREAMON; ioctl and the first &func-read;, &func-write; and
-&func-select; call.</para>
-
- <table frame="none" pgwide="1" id="v4l2-sliced-vbi-format">
- <title>struct
-<structname>v4l2_sliced_vbi_format</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" colwidth="3*" />
- <colspec colname="c2" colwidth="3*" />
- <colspec colname="c3" colwidth="2*" />
- <colspec colname="c4" colwidth="2*" />
- <colspec colname="c5" colwidth="2*" />
- <spanspec namest="c3" nameend="c5" spanname="hspan" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>service_set</structfield></entry>
- <entry spanname="hspan"><para>If
-<structfield>service_set</structfield> is non-zero when passed with
-&VIDIOC-S-FMT; or &VIDIOC-TRY-FMT;, the
-<structfield>service_lines</structfield> array will be filled by the
-driver according to the services specified in this field. For example,
-if <structfield>service_set</structfield> is initialized with
-<constant>V4L2_SLICED_TELETEXT_B | V4L2_SLICED_WSS_625</constant>, a
-driver for the cx25840 video decoder sets lines 7-22 of both
-fields<footnote><para>According to <link
-linkend="ets300706">ETS&nbsp;300&nbsp;706</link> lines 6-22 of the
-first field and lines 5-22 of the second field may carry Teletext
-data.</para></footnote> to <constant>V4L2_SLICED_TELETEXT_B</constant>
-and line 23 of the first field to
-<constant>V4L2_SLICED_WSS_625</constant>. If
-<structfield>service_set</structfield> is set to zero, then the values
-of <structfield>service_lines</structfield> will be used instead.
-</para><para>On return the driver sets this field to the union of all
-elements of the returned <structfield>service_lines</structfield>
-array. It may contain less services than requested, perhaps just one,
-if the hardware cannot handle more services simultaneously. It may be
-empty (zero) if none of the requested services are supported by the
-hardware.</para></entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>service_lines</structfield>[2][24]</entry>
- <entry spanname="hspan"><para>Applications initialize this
-array with sets of data services the driver shall look for or insert
-on the respective scan line. Subject to hardware capabilities drivers
-return the requested set, a subset, which may be just a single
-service, or an empty set. When the hardware cannot handle multiple
-services on the same line the driver shall choose one. No assumptions
-can be made on which service the driver chooses.</para><para>Data
-services are defined in <xref linkend="vbi-services2" />. Array indices
-map to ITU-R line numbers (see also <xref linkend="vbi-525" /> and <xref
- linkend="vbi-625" />) as follows: <!-- No nested
-tables, sigh. --></para></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Element</entry>
- <entry>525 line systems</entry>
- <entry>625 line systems</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[0][1]</entry>
- <entry align="center">1</entry>
- <entry align="center">1</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[0][23]</entry>
- <entry align="center">23</entry>
- <entry align="center">23</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[1][1]</entry>
- <entry align="center">264</entry>
- <entry align="center">314</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[1][23]</entry>
- <entry align="center">286</entry>
- <entry align="center">336</entry>
- </row>
- <!-- End of line numbers table. -->
- <row>
- <entry></entry>
- <entry></entry>
- <entry spanname="hspan">Drivers must set
-<structfield>service_lines</structfield>[0][0] and
-<structfield>service_lines</structfield>[1][0] to zero.
-The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
-<constant>V4L2_VBI_ITU_525_F2_START</constant>,
-<constant>V4L2_VBI_ITU_625_F1_START</constant> and
-<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start
-line numbers for each field for each 525 or 625 line format as a
-convenience. Don't forget that ITU line numbering starts at 1, not 0.
-</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>io_size</structfield></entry>
- <entry spanname="hspan">Maximum number of bytes passed by
-one &func-read; or &func-write; call, and the buffer size in bytes for
-the &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl. Drivers set this field to
-the size of &v4l2-sliced-vbi-data; times the number of non-zero
-elements in the returned <structfield>service_lines</structfield>
-array (that is the number of lines potentially carrying data).</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry spanname="hspan">This array is reserved for future
-extensions. Applications and drivers must set it to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- See also vidioc-g-sliced-vbi-cap.sgml -->
- <table frame="none" pgwide="1" id="vbi-services2">
- <title>Sliced VBI services</title>
- <tgroup cols="5">
- <colspec colname="c1" colwidth="2*" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colname="c3" colwidth="1*" />
- <colspec colname="c4" colwidth="2*" />
- <colspec colname="c5" colwidth="2*" />
- <spanspec namest="c3" nameend="c5" spanname="rlp" />
- <thead>
- <row>
- <entry>Symbol</entry>
- <entry>Value</entry>
- <entry>Reference</entry>
- <entry>Lines, usually</entry>
- <entry>Payload</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_SLICED_TELETEXT_B</constant>
-(Teletext System B)</entry>
- <entry>0x0001</entry>
- <entry><xref linkend="ets300706" />, <xref linkend="itu653" /></entry>
- <entry>PAL/SECAM line 7-22, 320-335 (second field 7-22)</entry>
- <entry>Last 42 of the 45 byte Teletext packet, that is
-without clock run-in and framing code, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VPS</constant></entry>
- <entry>0x0400</entry>
- <entry><xref linkend="ets300231" /></entry>
- <entry>PAL line 16</entry>
- <entry>Byte number 3 to 15 according to Figure 9 of
-ETS&nbsp;300&nbsp;231, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_CAPTION_525</constant></entry>
- <entry>0x1000</entry>
- <entry><xref linkend="cea608" /></entry>
- <entry>NTSC line 21, 284 (second field 21)</entry>
- <entry>Two bytes in transmission order, including parity
-bit, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_WSS_625</constant></entry>
- <entry>0x4000</entry>
- <entry><xref linkend="itu1119" />, <xref linkend="en300294" /></entry>
- <entry>PAL/SECAM line 23</entry>
- <entry><screen>
-Byte 0 1
- msb lsb msb lsb
- Bit 7 6 5 4 3 2 1 0 x x 13 12 11 10 9
-</screen></entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VBI_525</constant></entry>
- <entry>0x1000</entry>
- <entry spanname="rlp">Set of services applicable to 525
-line systems.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VBI_625</constant></entry>
- <entry>0x4401</entry>
- <entry spanname="rlp">Set of services applicable to 625
-line systems.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Drivers may return an &EINVAL; when applications attempt to
-read or write data without prior format negotiation, after switching
-the video standard (which may invalidate the negotiated VBI
-parameters) and after switching the video input (which may change the
-video standard as a side effect). The &VIDIOC-S-FMT; ioctl may return
-an &EBUSY; when applications attempt to change the format while i/o is
-in progress (between a &VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; call,
-and after the first &func-read; or &func-write; call).</para>
- </section>
-
- <section>
- <title>Reading and writing sliced VBI data</title>
-
- <para>A single &func-read; or &func-write; call must pass all data
-belonging to one video frame. That is an array of
-<structname>v4l2_sliced_vbi_data</structname> structures with one or
-more elements and a total size not exceeding
-<structfield>io_size</structfield> bytes. Likewise in streaming I/O
-mode one buffer of <structfield>io_size</structfield> bytes must
-contain data of one video frame. The <structfield>id</structfield> of
-unused <structname>v4l2_sliced_vbi_data</structname> elements must be
-zero.</para>
-
- <table frame="none" pgwide="1" id="v4l2-sliced-vbi-data">
- <title>struct
-<structname>v4l2_sliced_vbi_data</structname></title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry>A flag from <xref linkend="vbi-services" />
-identifying the type of data in this packet. Only a single bit must be
-set. When the <structfield>id</structfield> of a captured packet is
-zero, the packet is empty and the contents of other fields are
-undefined. Applications shall ignore empty packets. When the
-<structfield>id</structfield> of a packet for output is zero the
-contents of the <structfield>data</structfield> field are undefined
-and the driver must no longer insert data on the requested
-<structfield>field</structfield> and
-<structfield>line</structfield>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>field</structfield></entry>
- <entry>The video field number this data has been captured
-from, or shall be inserted at. <constant>0</constant> for the first
-field, <constant>1</constant> for the second field.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>line</structfield></entry>
- <entry>The field (as opposed to frame) line number this
-data has been captured from, or shall be inserted at. See <xref
- linkend="vbi-525" /> and <xref linkend="vbi-625" /> for valid
-values. Sliced VBI capture devices can set the line number of all
-packets to <constant>0</constant> if the hardware cannot reliably
-identify scan lines. The field number must always be valid.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield></entry>
- <entry>This field is reserved for future extensions.
-Applications and drivers must set it to zero.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>data</structfield>[48]</entry>
- <entry>The packet payload. See <xref
- linkend="vbi-services" /> for the contents and number of
-bytes passed for each data type. The contents of padding bytes at the
-end of this array are undefined, drivers and applications shall ignore
-them.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Packets are always passed in ascending line number order,
-without duplicate line numbers. The &func-write; function and the
-&VIDIOC-QBUF; ioctl must return an &EINVAL; when applications violate
-this rule. They must also return an &EINVAL; when applications pass an
-incorrect field or line number, or a combination of
-<structfield>field</structfield>, <structfield>line</structfield> and
-<structfield>id</structfield> which has not been negotiated with the
-&VIDIOC-G-FMT; or &VIDIOC-S-FMT; ioctl. When the line numbers are
-unknown the driver must pass the packets in transmitted order. The
-driver can insert empty packets with <structfield>id</structfield> set
-to zero anywhere in the packet array.</para>
-
- <para>To assure synchronization and to distinguish from frame
-dropping, when a captured frame does not carry any of the requested
-data services drivers must pass one or more empty packets. When an
-application fails to pass VBI data in time for output, the driver
-must output the last VPS and WSS packet again, and disable the output
-of Closed Caption and Teletext data, or output data which is ignored
-by Closed Caption and Teletext decoders.</para>
-
- <para>A sliced VBI device may support <link
-linkend="rw">read/write</link> and/or streaming (<link
-linkend="mmap">memory mapping</link> and/or <link linkend="userp">user
-pointer</link>) I/O. The latter bears the possibility of synchronizing
-video and VBI data by using buffer timestamps.</para>
-
- </section>
-
- <section>
- <title>Sliced VBI Data in MPEG Streams</title>
-
- <para>If a device can produce an MPEG output stream, it may be
-capable of providing <link
-linkend="sliced-vbi-format-negotitation">negotiated sliced VBI
-services</link> as data embedded in the MPEG stream. Users or
-applications control this sliced VBI data insertion with the <link
-linkend="v4l2-mpeg-stream-vbi-fmt">V4L2_CID_MPEG_STREAM_VBI_FMT</link>
-control.</para>
-
- <para>If the driver does not provide the <link
-linkend="v4l2-mpeg-stream-vbi-fmt">V4L2_CID_MPEG_STREAM_VBI_FMT</link>
-control, or only allows that control to be set to <link
-linkend="v4l2-mpeg-stream-vbi-fmt"><constant>
-V4L2_MPEG_STREAM_VBI_FMT_NONE</constant></link>, then the device
-cannot embed sliced VBI data in the MPEG stream.</para>
-
- <para>The <link linkend="v4l2-mpeg-stream-vbi-fmt">
-V4L2_CID_MPEG_STREAM_VBI_FMT</link> control does not implicitly set
-the device driver to capture nor cease capturing sliced VBI data. The
-control only indicates to embed sliced VBI data in the MPEG stream, if
-an application has negotiated sliced VBI service be captured.</para>
-
- <para>It may also be the case that a device can embed sliced VBI
-data in only certain types of MPEG streams: for example in an MPEG-2
-PS but not an MPEG-2 TS. In this situation, if sliced VBI data
-insertion is requested, the sliced VBI data will be embedded in MPEG
-stream types when supported, and silently omitted from MPEG stream
-types where sliced VBI data insertion is not supported by the device.
-</para>
-
- <para>The following subsections specify the format of the
-embedded sliced VBI data.</para>
-
- <section>
- <title>MPEG Stream Embedded, Sliced VBI Data Format: NONE</title>
- <para>The <link linkend="v4l2-mpeg-stream-vbi-fmt"><constant>
-V4L2_MPEG_STREAM_VBI_FMT_NONE</constant></link> embedded sliced VBI
-format shall be interpreted by drivers as a control to cease
-embedding sliced VBI data in MPEG streams. Neither the device nor
-driver shall insert "empty" embedded sliced VBI data packets in the
-MPEG stream when this format is set. No MPEG stream data structures
-are specified for this format.</para>
- </section>
-
- <section>
- <title>MPEG Stream Embedded, Sliced VBI Data Format: IVTV</title>
- <para>The <link linkend="v4l2-mpeg-stream-vbi-fmt"><constant>
-V4L2_MPEG_STREAM_VBI_FMT_IVTV</constant></link> embedded sliced VBI
-format, when supported, indicates to the driver to embed up to 36
-lines of sliced VBI data per frame in an MPEG-2 <emphasis>Private
-Stream 1 PES</emphasis> packet encapsulated in an MPEG-2 <emphasis>
-Program Pack</emphasis> in the MPEG stream.</para>
-
- <para><emphasis>Historical context</emphasis>: This format
-specification originates from a custom, embedded, sliced VBI data
-format used by the <filename>ivtv</filename> driver. This format
-has already been informally specified in the kernel sources in the
-file <filename>Documentation/video4linux/cx2341x/README.vbi</filename>
-. The maximum size of the payload and other aspects of this format
-are driven by the CX23415 MPEG decoder's capabilities and limitations
-with respect to extracting, decoding, and displaying sliced VBI data
-embedded within an MPEG stream.</para>
-
- <para>This format's use is <emphasis>not</emphasis> exclusive to
-the <filename>ivtv</filename> driver <emphasis>nor</emphasis>
-exclusive to CX2341x devices, as the sliced VBI data packet insertion
-into the MPEG stream is implemented in driver software. At least the
-<filename>cx18</filename> driver provides sliced VBI data insertion
-into an MPEG-2 PS in this format as well.</para>
-
- <para>The following definitions specify the payload of the
-MPEG-2 <emphasis>Private Stream 1 PES</emphasis> packets that contain
-sliced VBI data when <link linkend="v4l2-mpeg-stream-vbi-fmt">
-<constant>V4L2_MPEG_STREAM_VBI_FMT_IVTV</constant></link> is set.
-(The MPEG-2 <emphasis>Private Stream 1 PES</emphasis> packet header
-and encapsulating MPEG-2 <emphasis>Program Pack</emphasis> header are
-not detailed here. Please refer to the MPEG-2 specifications for
-details on those packet headers.)</para>
-
- <para>The payload of the MPEG-2 <emphasis>Private Stream 1 PES
-</emphasis> packets that contain sliced VBI data is specified by
-&v4l2-mpeg-vbi-fmt-ivtv;. The payload is variable
-length, depending on the actual number of lines of sliced VBI data
-present in a video frame. The payload may be padded at the end with
-unspecified fill bytes to align the end of the payload to a 4-byte
-boundary. The payload shall never exceed 1552 bytes (2 fields with
-18 lines/field with 43 bytes of data/line and a 4 byte magic number).
-</para>
-
- <table frame="none" pgwide="1" id="v4l2-mpeg-vbi-fmt-ivtv">
- <title>struct <structname>v4l2_mpeg_vbi_fmt_ivtv</structname>
- </title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>magic</structfield>[4]</entry>
- <entry></entry>
- <entry>A "magic" constant from <xref
- linkend="v4l2-mpeg-vbi-fmt-ivtv-magic" /> that indicates
-this is a valid sliced VBI data payload and also indicates which
-member of the anonymous union, <structfield>itv0</structfield> or
-<structfield>ITV0</structfield>, to use for the payload data.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct <link linkend="v4l2-mpeg-vbi-itv0">
- <structname>v4l2_mpeg_vbi_itv0</structname></link>
- </entry>
- <entry><structfield>itv0</structfield></entry>
- <entry>The primary form of the sliced VBI data payload
-that contains anywhere from 1 to 35 lines of sliced VBI data.
-Line masks are provided in this form of the payload indicating
-which VBI lines are provided.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct <link linkend="v4l2-mpeg-vbi-itv0-1">
- <structname>v4l2_mpeg_vbi_ITV0</structname></link>
- </entry>
- <entry><structfield>ITV0</structfield></entry>
- <entry>An alternate form of the sliced VBI data payload
-used when 36 lines of sliced VBI data are present. No line masks are
-provided in this form of the payload; all valid line mask bits are
-implcitly set.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-mpeg-vbi-fmt-ivtv-magic">
- <title>Magic Constants for &v4l2-mpeg-vbi-fmt-ivtv;
- <structfield>magic</structfield> field</title>
- <tgroup cols="3">
- &cs-def;
- <thead>
- <row>
- <entry align="left">Defined Symbol</entry>
- <entry align="left">Value</entry>
- <entry align="left">Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_MAGIC0</constant>
- </entry>
- <entry>"itv0"</entry>
- <entry>Indicates the <structfield>itv0</structfield>
-member of the union in &v4l2-mpeg-vbi-fmt-ivtv; is valid.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_MAGIC1</constant>
- </entry>
- <entry>"ITV0"</entry>
- <entry>Indicates the <structfield>ITV0</structfield>
-member of the union in &v4l2-mpeg-vbi-fmt-ivtv; is valid and
-that 36 lines of sliced VBI data are present.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-mpeg-vbi-itv0">
- <title>struct <structname>v4l2_mpeg_vbi_itv0</structname>
- </title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__le32</entry>
- <entry><structfield>linemask</structfield>[2]</entry>
- <entry><para>Bitmasks indicating the VBI service lines
-present. These <structfield>linemask</structfield> values are stored
-in little endian byte order in the MPEG stream. Some reference
-<structfield>linemask</structfield> bit positions with their
-corresponding VBI line number and video field are given below.
-b<subscript>0</subscript> indicates the least significant bit of a
-<structfield>linemask</structfield> value:<screen>
-<structfield>linemask</structfield>[0] b<subscript>0</subscript>: line 6 first field
-<structfield>linemask</structfield>[0] b<subscript>17</subscript>: line 23 first field
-<structfield>linemask</structfield>[0] b<subscript>18</subscript>: line 6 second field
-<structfield>linemask</structfield>[0] b<subscript>31</subscript>: line 19 second field
-<structfield>linemask</structfield>[1] b<subscript>0</subscript>: line 20 second field
-<structfield>linemask</structfield>[1] b<subscript>3</subscript>: line 23 second field
-<structfield>linemask</structfield>[1] b<subscript>4</subscript>-b<subscript>31</subscript>: unused and set to 0</screen></para></entry>
- </row>
- <row>
- <entry>struct <link linkend="v4l2-mpeg-vbi-itv0-line">
- <structname>v4l2_mpeg_vbi_itv0_line</structname></link>
- </entry>
- <entry><structfield>line</structfield>[35]</entry>
- <entry>This is a variable length array that holds from 1
-to 35 lines of sliced VBI data. The sliced VBI data lines present
-correspond to the bits set in the <structfield>linemask</structfield>
-array, starting from b<subscript>0</subscript> of <structfield>
-linemask</structfield>[0] up through b<subscript>31</subscript> of
-<structfield>linemask</structfield>[0], and from b<subscript>0
-</subscript> of <structfield>linemask</structfield>[1] up through b
-<subscript>3</subscript> of <structfield>linemask</structfield>[1].
-<structfield>line</structfield>[0] corresponds to the first bit
-found set in the <structfield>linemask</structfield> array,
-<structfield>line</structfield>[1] corresponds to the second bit
-found set in the <structfield>linemask</structfield> array, etc.
-If no <structfield>linemask</structfield> array bits are set, then
-<structfield>line</structfield>[0] may contain one line of
-unspecified data that should be ignored by applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-mpeg-vbi-itv0-1">
- <title>struct <structname>v4l2_mpeg_vbi_ITV0</structname>
- </title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>struct <link linkend="v4l2-mpeg-vbi-itv0-line">
- <structname>v4l2_mpeg_vbi_itv0_line</structname></link>
- </entry>
- <entry><structfield>line</structfield>[36]</entry>
- <entry>A fixed length array of 36 lines of sliced VBI
-data. <structfield>line</structfield>[0] through <structfield>line
-</structfield>[17] correspond to lines 6 through 23 of the
-first field. <structfield>line</structfield>[18] through
-<structfield>line</structfield>[35] corresponds to lines 6
-through 23 of the second field.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-mpeg-vbi-itv0-line">
- <title>struct <structname>v4l2_mpeg_vbi_itv0_line</structname>
- </title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>id</structfield></entry>
- <entry>A line identifier value from
-<xref linkend="ITV0-Line-Identifier-Constants" /> that indicates
-the type of sliced VBI data stored on this line.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>data</structfield>[42]</entry>
- <entry>The sliced VBI data for the line.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="ITV0-Line-Identifier-Constants">
- <title>Line Identifiers for struct <link
- linkend="v4l2-mpeg-vbi-itv0-line"><structname>
-v4l2_mpeg_vbi_itv0_line</structname></link> <structfield>id
-</structfield> field</title>
- <tgroup cols="3">
- &cs-def;
- <thead>
- <row>
- <entry align="left">Defined Symbol</entry>
- <entry align="left">Value</entry>
- <entry align="left">Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_TELETEXT_B</constant>
- </entry>
- <entry>1</entry>
- <entry>Refer to <link linkend="vbi-services2">
-Sliced VBI services</link> for a description of the line payload.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_CAPTION_525</constant>
- </entry>
- <entry>4</entry>
- <entry>Refer to <link linkend="vbi-services2">
-Sliced VBI services</link> for a description of the line payload.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_WSS_625</constant>
- </entry>
- <entry>5</entry>
- <entry>Refer to <link linkend="vbi-services2">
-Sliced VBI services</link> for a description of the line payload.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MPEG_VBI_IVTV_VPS</constant>
- </entry>
- <entry>7</entry>
- <entry>Refer to <link linkend="vbi-services2">
-Sliced VBI services</link> for a description of the line payload.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
- </section>
diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml
deleted file mode 100644
index f4bc27af83eb..000000000000
--- a/Documentation/DocBook/media/v4l/dev-subdev.xml
+++ /dev/null
@@ -1,478 +0,0 @@
- <title>Sub-device Interface</title>
-
- <para>The complex nature of V4L2 devices, where hardware is often made of
- several integrated circuits that need to interact with each other in a
- controlled way, leads to complex V4L2 drivers. The drivers usually reflect
- the hardware model in software, and model the different hardware components
- as software blocks called sub-devices.</para>
-
- <para>V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver
- implements the media device API, they will automatically inherit from media
- entities. Applications will be able to enumerate the sub-devices and discover
- the hardware topology using the media entities, pads and links enumeration
- API.</para>
-
- <para>In addition to make sub-devices discoverable, drivers can also choose
- to make them directly configurable by applications. When both the sub-device
- driver and the V4L2 device driver support this, sub-devices will feature a
- character device node on which ioctls can be called to
- <itemizedlist>
- <listitem><para>query, read and write sub-devices controls</para></listitem>
- <listitem><para>subscribe and unsubscribe to events and retrieve them</para></listitem>
- <listitem><para>negotiate image formats on individual pads</para></listitem>
- </itemizedlist>
- </para>
-
- <para>Sub-device character device nodes, conventionally named
- <filename>/dev/v4l-subdev*</filename>, use major number 81.</para>
-
- <section>
- <title>Controls</title>
- <para>Most V4L2 controls are implemented by sub-device hardware. Drivers
- usually merge all controls and expose them through video device nodes.
- Applications can control all sub-devices through a single interface.</para>
-
- <para>Complex devices sometimes implement the same control in different
- pieces of hardware. This situation is common in embedded platforms, where
- both sensors and image processing hardware implement identical functions,
- such as contrast adjustment, white balance or faulty pixels correction. As
- the V4L2 controls API doesn't support several identical controls in a single
- device, all but one of the identical controls are hidden.</para>
-
- <para>Applications can access those hidden controls through the sub-device
- node with the V4L2 control API described in <xref linkend="control" />. The
- ioctls behave identically as when issued on V4L2 device nodes, with the
- exception that they deal only with controls implemented in the sub-device.
- </para>
-
- <para>Depending on the driver, those controls might also be exposed through
- one (or several) V4L2 device nodes.</para>
- </section>
-
- <section>
- <title>Events</title>
- <para>V4L2 sub-devices can notify applications of events as described in
- <xref linkend="event" />. The API behaves identically as when used on V4L2
- device nodes, with the exception that it only deals with events generated by
- the sub-device. Depending on the driver, those events might also be reported
- on one (or several) V4L2 device nodes.</para>
- </section>
-
- <section id="pad-level-formats">
- <title>Pad-level Formats</title>
-
- <warning><para>Pad-level formats are only applicable to very complex device that
- need to expose low-level format configuration to user space. Generic V4L2
- applications do <emphasis>not</emphasis> need to use the API described in
- this section.</para></warning>
-
- <note><para>For the purpose of this section, the term
- <wordasword>format</wordasword> means the combination of media bus data
- format, frame width and frame height.</para></note>
-
- <para>Image formats are typically negotiated on video capture and
- output devices using the format and <link
- linkend="vidioc-subdev-g-selection">selection</link> ioctls. The
- driver is responsible for configuring every block in the video
- pipeline according to the requested format at the pipeline input
- and/or output.</para>
-
- <para>For complex devices, such as often found in embedded systems,
- identical image sizes at the output of a pipeline can be achieved using
- different hardware configurations. One such example is shown on
- <xref linkend="pipeline-scaling" />, where
- image scaling can be performed on both the video sensor and the host image
- processing hardware.</para>
-
- <figure id="pipeline-scaling">
- <title>Image Format Negotiation on Pipelines</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="pipeline.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="pipeline.png" format="PNG" />
- </imageobject>
- <textobject>
- <phrase>High quality and high speed pipeline configuration</phrase>
- </textobject>
- </mediaobject>
- </figure>
-
- <para>The sensor scaler is usually of less quality than the host scaler, but
- scaling on the sensor is required to achieve higher frame rates. Depending
- on the use case (quality vs. speed), the pipeline must be configured
- differently. Applications need to configure the formats at every point in
- the pipeline explicitly.</para>
-
- <para>Drivers that implement the <link linkend="media-controller-intro">media
- API</link> can expose pad-level image format configuration to applications.
- When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and
- &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis.</para>
-
- <para>Applications are responsible for configuring coherent parameters on
- the whole pipeline and making sure that connected pads have compatible
- formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON;
- time, and an &EPIPE; is then returned if the configuration is
- invalid.</para>
-
- <para>Pad-level image format configuration support can be tested by calling
- the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL;
- pad-level format configuration is not supported by the sub-device.</para>
-
- <section>
- <title>Format Negotiation</title>
-
- <para>Acceptable formats on pads can (and usually do) depend on a number
- of external parameters, such as formats on other pads, active links, or
- even controls. Finding a combination of formats on all pads in a video
- pipeline, acceptable to both application and driver, can't rely on formats
- enumeration only. A format negotiation mechanism is required.</para>
-
- <para>Central to the format negotiation mechanism are the get/set format
- operations. When called with the <structfield>which</structfield> argument
- set to <constant>V4L2_SUBDEV_FORMAT_TRY</constant>, the
- &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of
- formats parameters that are not connected to the hardware configuration.
- Modifying those 'try' formats leaves the device state untouched (this
- applies to both the software state stored in the driver and the hardware
- state stored in the device itself).</para>
-
- <para>While not kept as part of the device state, try formats are stored
- in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return
- the last try format set <emphasis>on the same sub-device file
- handle</emphasis>. Several applications querying the same sub-device at
- the same time will thus not interact with each other.</para>
-
- <para>To find out whether a particular format is supported by the device,
- applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if
- needed, change the requested <structfield>format</structfield> based on
- device requirements and return the possibly modified value. Applications
- can then choose to try a different format or accept the returned value and
- continue.</para>
-
- <para>Formats returned by the driver during a negotiation iteration are
- guaranteed to be supported by the device. In particular, drivers guarantee
- that a returned format will not be further changed if passed to an
- &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as
- formats on other pads or links' configuration are not changed).</para>
-
- <para>Drivers automatically propagate formats inside sub-devices. When a
- try or active format is set on a pad, corresponding formats on other pads
- of the same sub-device can be modified by the driver. Drivers are free to
- modify formats as required by the device. However, they should comply with
- the following rules when possible:
- <itemizedlist>
- <listitem><para>Formats should be propagated from sink pads to source pads.
- Modifying a format on a source pad should not modify the format on any
- sink pad.</para></listitem>
- <listitem><para>Sub-devices that scale frames using variable scaling factors
- should reset the scale factors to default values when sink pads formats
- are modified. If the 1:1 scaling ratio is supported, this means that
- source pads formats should be reset to the sink pads formats.</para></listitem>
- </itemizedlist>
- </para>
-
- <para>Formats are not propagated across links, as that would involve
- propagating them from one sub-device file handle to another. Applications
- must then take care to configure both ends of every link explicitly with
- compatible formats. Identical formats on the two ends of a link are
- guaranteed to be compatible. Drivers are free to accept different formats
- matching device requirements as being compatible.</para>
-
- <para><xref linkend="sample-pipeline-config" />
- shows a sample configuration sequence for the pipeline described in
- <xref linkend="pipeline-scaling" /> (table
- columns list entity names and pad numbers).</para>
-
- <table pgwide="0" frame="none" id="sample-pipeline-config">
- <title>Sample Pipeline Configuration</title>
- <tgroup cols="3">
- <colspec colname="what"/>
- <colspec colname="sensor-0 format" />
- <colspec colname="frontend-0 format" />
- <colspec colname="frontend-1 format" />
- <colspec colname="scaler-0 format" />
- <colspec colname="scaler-0 compose" />
- <colspec colname="scaler-1 format" />
- <thead>
- <row>
- <entry></entry>
- <entry>Sensor/0 format</entry>
- <entry>Frontend/0 format</entry>
- <entry>Frontend/1 format</entry>
- <entry>Scaler/0 format</entry>
- <entry>Scaler/0 compose selection rectangle</entry>
- <entry>Scaler/1 format</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Initial state</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- </row>
- <row>
- <entry>Configure frontend sink format</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry><emphasis>2048x1536/SGRBG8_1X8</emphasis></entry>
- <entry><emphasis>2046x1534/SGRBG8_1X8</emphasis></entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- <entry>(default)</entry>
- </row>
- <row>
- <entry>Configure scaler sink format</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry>2046x1534/SGRBG8_1X8</entry>
- <entry><emphasis>2046x1534/SGRBG8_1X8</emphasis></entry>
- <entry><emphasis>0,0/2046x1534</emphasis></entry>
- <entry><emphasis>2046x1534/SGRBG8_1X8</emphasis></entry>
- </row>
- <row>
- <entry>Configure scaler sink compose selection</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry>2048x1536/SGRBG8_1X8</entry>
- <entry>2046x1534/SGRBG8_1X8</entry>
- <entry>2046x1534/SGRBG8_1X8</entry>
- <entry><emphasis>0,0/1280x960</emphasis></entry>
- <entry><emphasis>1280x960/SGRBG8_1X8</emphasis></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- <orderedlist>
- <listitem><para>Initial state. The sensor source pad format is
- set to its native 3MP size and V4L2_MBUS_FMT_SGRBG8_1X8
- media bus code. Formats on the host frontend and scaler sink
- and source pads have the default values, as well as the
- compose rectangle on the scaler's sink pad.</para></listitem>
-
- <listitem><para>The application configures the frontend sink
- pad format's size to 2048x1536 and its media bus code to
- V4L2_MBUS_FMT_SGRBG_1X8. The driver propagates the format to
- the frontend source pad.</para></listitem>
-
- <listitem><para>The application configures the scaler sink pad
- format's size to 2046x1534 and the media bus code to
- V4L2_MBUS_FMT_SGRBG_1X8 to match the frontend source size and
- media bus code. The media bus code on the sink pad is set to
- V4L2_MBUS_FMT_SGRBG_1X8. The driver propagates the size to the
- compose selection rectangle on the scaler's sink pad, and the
- format to the scaler source pad.</para></listitem>
-
- <listitem><para>The application configures the size of the compose
- selection rectangle of the scaler's sink pad 1280x960. The driver
- propagates the size to the scaler's source pad
- format.</para></listitem>
-
- </orderedlist>
- </para>
-
- <para>When satisfied with the try results, applications can set the active
- formats by setting the <structfield>which</structfield> argument to
- <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. Active formats are changed
- exactly as try formats by drivers. To avoid modifying the hardware state
- during format negotiation, applications should negotiate try formats first
- and then modify the active settings using the try formats returned during
- the last negotiation iteration. This guarantees that the active format
- will be applied as-is by the driver without being modified.
- </para>
- </section>
-
- <section id="v4l2-subdev-selections">
- <title>Selections: cropping, scaling and composition</title>
-
- <para>Many sub-devices support cropping frames on their input or output
- pads (or possible even on both). Cropping is used to select the area of
- interest in an image, typically on an image sensor or a video decoder. It can
- also be used as part of digital zoom implementations to select the area of
- the image that will be scaled up.</para>
-
- <para>Crop settings are defined by a crop rectangle and represented in a
- &v4l2-rect; by the coordinates of the top left corner and the rectangle
- size. Both the coordinates and sizes are expressed in pixels.</para>
-
- <para>As for pad formats, drivers store try and active
- rectangles for the selection targets <xref
- linkend="v4l2-selections-common" />.</para>
-
- <para>On sink pads, cropping is applied relative to the
- current pad format. The pad format represents the image size as
- received by the sub-device from the previous block in the
- pipeline, and the crop rectangle represents the sub-image that
- will be transmitted further inside the sub-device for
- processing.</para>
-
- <para>The scaling operation changes the size of the image by
- scaling it to new dimensions. The scaling ratio isn't specified
- explicitly, but is implied from the original and scaled image
- sizes. Both sizes are represented by &v4l2-rect;.</para>
-
- <para>Scaling support is optional. When supported by a subdev,
- the crop rectangle on the subdev's sink pad is scaled to the
- size configured using the &VIDIOC-SUBDEV-S-SELECTION; IOCTL
- using <constant>V4L2_SEL_TGT_COMPOSE</constant>
- selection target on the same pad. If the subdev supports scaling
- but not composing, the top and left values are not used and must
- always be set to zero.</para>
-
- <para>On source pads, cropping is similar to sink pads, with the
- exception that the source size from which the cropping is
- performed, is the COMPOSE rectangle on the sink pad. In both
- sink and source pads, the crop rectangle must be entirely
- contained inside the source image size for the crop
- operation.</para>
-
- <para>The drivers should always use the closest possible
- rectangle the user requests on all selection targets, unless
- specifically told otherwise.
- <constant>V4L2_SEL_FLAG_GE</constant> and
- <constant>V4L2_SEL_FLAG_LE</constant> flags may be
- used to round the image size either up or down. <xref
- linkend="v4l2-selection-flags" /></para>
- </section>
-
- <section>
- <title>Types of selection targets</title>
-
- <section>
- <title>Actual targets</title>
-
- <para>Actual targets (without a postfix) reflect the actual
- hardware configuration at any point of time. There is a BOUNDS
- target corresponding to every actual target.</para>
- </section>
-
- <section>
- <title>BOUNDS targets</title>
-
- <para>BOUNDS targets is the smallest rectangle that contains all
- valid actual rectangles. It may not be possible to set the actual
- rectangle as large as the BOUNDS rectangle, however. This may be
- because e.g. a sensor's pixel array is not rectangular but
- cross-shaped or round. The maximum size may also be smaller than the
- BOUNDS rectangle.</para>
- </section>
-
- </section>
-
- <section>
- <title>Order of configuration and format propagation</title>
-
- <para>Inside subdevs, the order of image processing steps will
- always be from the sink pad towards the source pad. This is also
- reflected in the order in which the configuration must be
- performed by the user: the changes made will be propagated to
- any subsequent stages. If this behaviour is not desired, the
- user must set
- <constant>V4L2_SEL_FLAG_KEEP_CONFIG</constant> flag. This
- flag causes no propagation of the changes are allowed in any
- circumstances. This may also cause the accessed rectangle to be
- adjusted by the driver, depending on the properties of the
- underlying hardware.</para>
-
- <para>The coordinates to a step always refer to the actual size
- of the previous step. The exception to this rule is the source
- compose rectangle, which refers to the sink compose bounds
- rectangle --- if it is supported by the hardware.</para>
-
- <orderedlist>
- <listitem><para>Sink pad format. The user configures the sink pad
- format. This format defines the parameters of the image the
- entity receives through the pad for further processing.</para></listitem>
-
- <listitem><para>Sink pad actual crop selection. The sink pad crop
- defines the crop performed to the sink pad format.</para></listitem>
-
- <listitem><para>Sink pad actual compose selection. The size of the
- sink pad compose rectangle defines the scaling ratio compared
- to the size of the sink pad crop rectangle. The location of
- the compose rectangle specifies the location of the actual
- sink compose rectangle in the sink compose bounds
- rectangle.</para></listitem>
-
- <listitem><para>Source pad actual crop selection. Crop on the source
- pad defines crop performed to the image in the sink compose
- bounds rectangle.</para></listitem>
-
- <listitem><para>Source pad format. The source pad format defines the
- output pixel format of the subdev, as well as the other
- parameters with the exception of the image width and height.
- Width and height are defined by the size of the source pad
- actual crop selection.</para></listitem>
- </orderedlist>
-
- <para>Accessing any of the above rectangles not supported by the
- subdev will return <constant>EINVAL</constant>. Any rectangle
- referring to a previous unsupported rectangle coordinates will
- instead refer to the previous supported rectangle. For example,
- if sink crop is not supported, the compose selection will refer
- to the sink pad format dimensions instead.</para>
-
- <figure id="subdev-image-processing-crop">
- <title>Image processing in subdevs: simple crop example</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="subdev-image-processing-crop.svg"
- format="SVG" scale="200" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>In the above example, the subdev supports cropping on its
- sink pad. To configure it, the user sets the media bus format on
- the subdev's sink pad. Now the actual crop rectangle can be set
- on the sink pad --- the location and size of this rectangle
- reflect the location and size of a rectangle to be cropped from
- the sink format. The size of the sink crop rectangle will also
- be the size of the format of the subdev's source pad.</para>
-
- <figure id="subdev-image-processing-scaling-multi-source">
- <title>Image processing in subdevs: scaling with multiple sources</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="subdev-image-processing-scaling-multi-source.svg"
- format="SVG" scale="200" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>In this example, the subdev is capable of first cropping,
- then scaling and finally cropping for two source pads
- individually from the resulting scaled image. The location of
- the scaled image in the cropped image is ignored in sink compose
- target. Both of the locations of the source crop rectangles
- refer to the sink scaling rectangle, independently cropping an
- area at location specified by the source crop rectangle from
- it.</para>
-
- <figure id="subdev-image-processing-full">
- <title>Image processing in subdevs: scaling and composition
- with multiple sinks and sources</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="subdev-image-processing-full.svg"
- format="SVG" scale="200" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>The subdev driver supports two sink pads and two source
- pads. The images from both of the sink pads are individually
- cropped, then scaled and further composed on the composition
- bounds rectangle. From that, two independent streams are cropped
- and sent out of the subdev from the source pads.</para>
-
- </section>
-
- </section>
-
- &sub-subdev-formats;
diff --git a/Documentation/DocBook/media/v4l/dev-teletext.xml b/Documentation/DocBook/media/v4l/dev-teletext.xml
deleted file mode 100644
index bd21c64d70f3..000000000000
--- a/Documentation/DocBook/media/v4l/dev-teletext.xml
+++ /dev/null
@@ -1,29 +0,0 @@
- <title>Teletext Interface</title>
-
- <para>This interface was aimed at devices receiving and demodulating
-Teletext data [<xref linkend="ets300706" />, <xref linkend="itu653" />], evaluating the
-Teletext packages and storing formatted pages in cache memory. Such
-devices are usually implemented as microcontrollers with serial
-interface (I<superscript>2</superscript>C) and could be found on old
-TV cards, dedicated Teletext decoding cards and home-brew devices
-connected to the PC parallel port.</para>
-
- <para>The Teletext API was designed by Martin Buck. It was defined in
-the kernel header file <filename>linux/videotext.h</filename>, the
-specification is available from <ulink url="ftp://ftp.gwdg.de/pub/linux/misc/videotext/">
-ftp://ftp.gwdg.de/pub/linux/misc/videotext/</ulink>. (Videotext is the name of
-the German public television Teletext service.)</para>
-
- <para>Eventually the Teletext API was integrated into the V4L API
-with character device file names <filename>/dev/vtx0</filename> to
-<filename>/dev/vtx31</filename>, device major number 81, minor numbers
-192 to 223.</para>
-
- <para>However, teletext decoders were quickly replaced by more
-generic VBI demodulators and those dedicated teletext decoders no longer exist.
-For many years the vtx devices were still around, even though nobody used
-them. So the decision was made to finally remove support for the Teletext API in
-kernel 2.6.37.</para>
-
- <para>Modern devices all use the <link linkend="raw-vbi">raw</link> or
-<link linkend="sliced">sliced</link> VBI API.</para>
diff --git a/Documentation/DocBook/media/v4l/driver.xml b/Documentation/DocBook/media/v4l/driver.xml
deleted file mode 100644
index 7c6638bacedb..000000000000
--- a/Documentation/DocBook/media/v4l/driver.xml
+++ /dev/null
@@ -1,200 +0,0 @@
- <title>V4L2 Driver Programming</title>
-
- <!-- This part defines the interface between the "videodev"
- module and individual drivers. -->
-
- <para>to do</para>
-<!--
- <para>V4L2 is a two-layer driver system. The top layer is the "videodev"
-kernel module. When videodev initializes it registers as character device
-with major number 81, and it registers a set of file operations. All V4L2
-drivers are really clients of videodev, which calls V4L2 drivers through
-driver method functions. V4L2 drivers are also written as kernel modules.
-After probing the hardware they register one or more devices with
-videodev.</para>
-
- <section id="driver-modules">
- <title>Driver Modules</title>
-
- <para>V4L2 driver modules must have an initialization function which is
-called after the module was loaded into kernel, an exit function whis is
-called before the module is removed. When the driver is compiled into the
-kernel these functions called at system boot and shutdown time.</para>
-
- <informalexample>
- <programlisting>
-#include &lt;linux/module.h&gt;
-
-/* Export information about this module. For details and other useful
- macros see <filename>linux/module.h</filename>. */
-MODULE_DESCRIPTION("my - driver for my hardware");
-MODULE_AUTHOR("Your name here");
-MODULE_LICENSE("GPL");
-
-static void
-my_module_exit (void)
-{
- /* Free all resources allocated by my_module_init(). */
-}
-
-static int
-my_module_init (void)
-{
- /* Bind the driver to the supported hardware, see
- <link linkend="driver-pci"> and
- <link linkend="driver-usb"> for examples. */
-
- return 0; /* a negative value on error, 0 on success. */
-}
-
-/* Export module functions. */
-module_init (my_module_init);
-module_exit (my_module_exit);
-</programlisting>
- </informalexample>
-
- <para>Users can add parameters when kernel modules are inserted:</para>
-
- <informalexample>
- <programlisting>
-include &lt;linux/moduleparam.h&gt;
-
-static int my_option = 123;
-static int my_option_array[47];
-
-/* Export the symbol, an int, with access permissions 0664.
- See <filename>linux/moduleparam.h</filename> for other types. */
-module_param (my_option, int, 0644);
-module_param_array (my_option_array, int, NULL, 0644);
-
-MODULE_PARM_DESC (my_option, "Does magic things, default 123");
-</programlisting>
- </informalexample>
-
- <para>One parameter should be supported by all V4L2 drivers, the minor
-number of the device it will register. Purpose is to predictably link V4L2
-drivers to device nodes if more than one video device is installed. Use the
-name of the device node followed by a "_nr" suffix, for example "video_nr"
-for <filename>/dev/video</filename>.</para>
-
- <informalexample>
- <programlisting>
-/* Minor number of the device, -1 to allocate the first unused. */
-static int video_nr = -1;
-
-module_param (video_nr, int, 0444);
-</programlisting>
- </informalexample>
- </section>
-
- <section id="driver-pci">
- <title>PCI Devices</title>
-
- <para>PCI devices are initialized like this:</para>
-
- <informalexample>
- <programlisting>
-typedef struct {
- /* State of one physical device. */
-} my_device;
-
-static int
-my_resume (struct pci_dev * pci_dev)
-{
- /* Restore the suspended device to working state. */
-}
-
-static int
-my_suspend (struct pci_dev * pci_dev,
- pm_message_t state)
-{
- /* This function is called before the system goes to sleep.
- Stop all DMAs and disable interrupts, then put the device
- into a low power state. For details see the kernel
- sources under <filename>Documentation/power</filename>. */
-
- return 0; /* a negative value on error, 0 on success. */
-}
-
-static void
-my_remove (struct pci_dev * pci_dev)
-{
- my_device *my = pci_get_drvdata (pci_dev);
-
- /* Describe me. */
-}
-
-static int
-my_probe (struct pci_dev * pci_dev,
- const struct pci_device_id * pci_id)
-{
- my_device *my;
-
- /* Describe me. */
-
- /* You can allocate per-device data here and store a pointer
- to it in the pci_dev structure. */
- my = ...;
- pci_set_drvdata (pci_dev, my);
-
- return 0; /* a negative value on error, 0 on success. */
-}
-
-/* A list of supported PCI devices. */
-static struct pci_device_id
-my_pci_device_ids [] = {
- { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0 } /* end of list */
-};
-
-/* Load our module if supported PCI devices are installed. */
-MODULE_DEVICE_TABLE (pci, my_pci_device_ids);
-
-static struct pci_driver
-my_pci_driver = {
- .name = "my",
- .id_table = my_pci_device_ids,
-
- .probe = my_probe,
- .remove = my_remove,
-
- /* Power management functions. */
- .suspend = my_suspend,
- .resume = my_resume,
-};
-
-static void
-my_module_exit (void)
-{
- pci_unregister_driver (&my_pci_driver);
-}
-
-static int
-my_module_init (void)
-{
- return pci_register_driver (&my_pci_driver);
-}
-</programlisting>
- </informalexample>
- </section>
-
- <section id="driver-usb">
- <title>USB Devices</title>
- <para>to do</para>
- </section>
- <section id="driver-registering">
- <title>Registering V4L2 Drivers</title>
-
- <para>After a V4L2 driver probed the hardware it registers one or more
-devices with the videodev module.</para>
- </section>
- <section id="driver-file-ops">
- <title>File Operations</title>
- <para>to do</para>
- </section>
- <section id="driver-internal-api">
- <title>Internal API</title>
- <para>to do</para>
- </section>
--->
diff --git a/Documentation/DocBook/media/v4l/fdl-appendix.xml b/Documentation/DocBook/media/v4l/fdl-appendix.xml
deleted file mode 100644
index 71299a3897c4..000000000000
--- a/Documentation/DocBook/media/v4l/fdl-appendix.xml
+++ /dev/null
@@ -1,671 +0,0 @@
-<!--
- The GNU Free Documentation License 1.1 in DocBook
- Markup by Eric Baudais <baudais@okstate.edu>
- Maintained by the GNOME Documentation Project
- http://live.gnome.org/DocumentationProject
- Version: 1.0.1
- Last Modified: Nov 16, 2000
--->
-
-<appendix id="fdl">
- <appendixinfo>
- <releaseinfo>
- Version 1.1, March 2000
- </releaseinfo>
- <copyright>
- <year>2000</year><holder>Free Software Foundation, Inc.</holder>
- </copyright>
- <legalnotice id="fdl-legalnotice">
- <para>
- <address>Free Software Foundation, Inc. <street>59 Temple Place,
- Suite 330</street>, <city>Boston</city>, <state>MA</state>
- <postcode>02111-1307</postcode> <country>USA</country></address>
- Everyone is permitted to copy and distribute verbatim copies of this
- license document, but changing it is not allowed.
- </para>
- </legalnotice>
- </appendixinfo>
- <title>GNU Free Documentation License</title>
-
- <sect1 id="fdl-preamble">
- <title>0. PREAMBLE</title>
- <para>
- The purpose of this License is to make a manual, textbook, or
- other written document <quote>free</quote> in the sense of
- freedom: to assure everyone the effective freedom to copy and
- redistribute it, with or without modifying it, either
- commercially or noncommercially. Secondarily, this License
- preserves for the author and publisher a way to get credit for
- their work, while not being considered responsible for
- modifications made by others.
- </para>
-
- <para>
- This License is a kind of <quote>copyleft</quote>, which means
- that derivative works of the document must themselves be free in
- the same sense. It complements the GNU General Public License,
- which is a copyleft license designed for free software.
- </para>
-
- <para>
- We have designed this License in order to use it for manuals for
- free software, because free software needs free documentation: a
- free program should come with manuals providing the same
- freedoms that the software does. But this License is not limited
- to software manuals; it can be used for any textual work,
- regardless of subject matter or whether it is published as a
- printed book. We recommend this License principally for works
- whose purpose is instruction or reference.
- </para>
- </sect1>
- <sect1 id="fdl-section1">
- <title>1. APPLICABILITY AND DEFINITIONS</title>
- <para id="fdl-document">
- This License applies to any manual or other work that contains a
- notice placed by the copyright holder saying it can be
- distributed under the terms of this License. The
- <quote>Document</quote>, below, refers to any such manual or
- work. Any member of the public is a licensee, and is addressed
- as <quote>you</quote>.
- </para>
-
- <para id="fdl-modified">
- A <quote>Modified Version</quote> of the Document means any work
- containing the Document or a portion of it, either copied
- verbatim, or with modifications and/or translated into another
- language.
- </para>
-
- <para id="fdl-secondary">
- A <quote>Secondary Section</quote> is a named appendix or a
- front-matter section of the <link
- linkend="fdl-document">Document</link> that deals exclusively
- with the relationship of the publishers or authors of the
- Document to the Document's overall subject (or to related
- matters) and contains nothing that could fall directly within
- that overall subject. (For example, if the Document is in part a
- textbook of mathematics, a Secondary Section may not explain any
- mathematics.) The relationship could be a matter of historical
- connection with the subject or with related matters, or of
- legal, commercial, philosophical, ethical or political position
- regarding them.
- </para>
-
- <para id="fdl-invariant">
- The <quote>Invariant Sections</quote> are certain <link
- linkend="fdl-secondary"> Secondary Sections</link> whose titles
- are designated, as being those of Invariant Sections, in the
- notice that says that the <link
- linkend="fdl-document">Document</link> is released under this
- License.
- </para>
-
- <para id="fdl-cover-texts">
- The <quote>Cover Texts</quote> are certain short passages of
- text that are listed, as Front-Cover Texts or Back-Cover Texts,
- in the notice that says that the <link
- linkend="fdl-document">Document</link> is released under this
- License.
- </para>
-
- <para id="fdl-transparent">
- A <quote>Transparent</quote> copy of the <link
- linkend="fdl-document"> Document</link> means a machine-readable
- copy, represented in a format whose specification is available
- to the general public, whose contents can be viewed and edited
- directly and straightforwardly with generic text editors or (for
- images composed of pixels) generic paint programs or (for
- drawings) some widely available drawing editor, and that is
- suitable for input to text formatters or for automatic
- translation to a variety of formats suitable for input to text
- formatters. A copy made in an otherwise Transparent file format
- whose markup has been designed to thwart or discourage
- subsequent modification by readers is not Transparent. A copy
- that is not <quote>Transparent</quote> is called
- <quote>Opaque</quote>.
- </para>
-
- <para>
- Examples of suitable formats for Transparent copies include
- plain ASCII without markup, Texinfo input format, LaTeX input
- format, SGML or XML using a publicly available DTD, and
- standard-conforming simple HTML designed for human
- modification. Opaque formats include PostScript, PDF,
- proprietary formats that can be read and edited only by
- proprietary word processors, SGML or XML for which the DTD
- and/or processing tools are not generally available, and the
- machine-generated HTML produced by some word processors for
- output purposes only.
- </para>
-
- <para id="fdl-title-page">
- The <quote>Title Page</quote> means, for a printed book, the
- title page itself, plus such following pages as are needed to
- hold, legibly, the material this License requires to appear in
- the title page. For works in formats which do not have any title
- page as such, <quote>Title Page</quote> means the text near the
- most prominent appearance of the work's title, preceding the
- beginning of the body of the text.
- </para>
- </sect1>
-
- <sect1 id="fdl-section2">
- <title>2. VERBATIM COPYING</title>
- <para>
- You may copy and distribute the <link
- linkend="fdl-document">Document</link> in any medium, either
- commercially or noncommercially, provided that this License, the
- copyright notices, and the license notice saying this License
- applies to the Document are reproduced in all copies, and that
- you add no other conditions whatsoever to those of this
- License. You may not use technical measures to obstruct or
- control the reading or further copying of the copies you make or
- distribute. However, you may accept compensation in exchange for
- copies. If you distribute a large enough number of copies you
- must also follow the conditions in <link
- linkend="fdl-section3">section 3</link>.
- </para>
-
- <para>
- You may also lend copies, under the same conditions stated
- above, and you may publicly display copies.
- </para>
- </sect1>
-
- <sect1 id="fdl-section3">
- <title>3. COPYING IN QUANTITY</title>
- <para>
- If you publish printed copies of the <link
- linkend="fdl-document">Document</link> numbering more than 100,
- and the Document's license notice requires <link
- linkend="fdl-cover-texts">Cover Texts</link>, you must enclose
- the copies in covers that carry, clearly and legibly, all these
- Cover Texts: Front-Cover Texts on the front cover, and
- Back-Cover Texts on the back cover. Both covers must also
- clearly and legibly identify you as the publisher of these
- copies. The front cover must present the full title with all
- words of the title equally prominent and visible. You may add
- other material on the covers in addition. Copying with changes
- limited to the covers, as long as they preserve the title of the
- <link linkend="fdl-document">Document</link> and satisfy these
- conditions, can be treated as verbatim copying in other
- respects.
- </para>
-
- <para>
- If the required texts for either cover are too voluminous to fit
- legibly, you should put the first ones listed (as many as fit
- reasonably) on the actual cover, and continue the rest onto
- adjacent pages.
- </para>
-
- <para>
- If you publish or distribute <link
- linkend="fdl-transparent">Opaque</link> copies of the <link
- linkend="fdl-document">Document</link> numbering more than 100,
- you must either include a machine-readable <link
- linkend="fdl-transparent">Transparent</link> copy along with
- each Opaque copy, or state in or with each Opaque copy a
- publicly-accessible computer-network location containing a
- complete Transparent copy of the Document, free of added
- material, which the general network-using public has access to
- download anonymously at no charge using public-standard network
- protocols. If you use the latter option, you must take
- reasonably prudent steps, when you begin distribution of Opaque
- copies in quantity, to ensure that this Transparent copy will
- remain thus accessible at the stated location until at least one
- year after the last time you distribute an Opaque copy (directly
- or through your agents or retailers) of that edition to the
- public.
- </para>
-
- <para>
- It is requested, but not required, that you contact the authors
- of the <link linkend="fdl-document">Document</link> well before
- redistributing any large number of copies, to give them a chance
- to provide you with an updated version of the Document.
- </para>
- </sect1>
-
- <sect1 id="fdl-section4">
- <title>4. MODIFICATIONS</title>
- <para>
- You may copy and distribute a <link
- linkend="fdl-modified">Modified Version</link> of the <link
- linkend="fdl-document">Document</link> under the conditions of
- sections <link linkend="fdl-section2">2</link> and <link
- linkend="fdl-section3">3</link> above, provided that you release
- the Modified Version under precisely this License, with the
- Modified Version filling the role of the Document, thus
- licensing distribution and modification of the Modified Version
- to whoever possesses a copy of it. In addition, you must do
- these things in the Modified Version:
- </para>
-
- <itemizedlist mark="opencircle">
- <listitem>
- <formalpara>
- <title>A</title>
- <para>
- Use in the <link linkend="fdl-title-page">Title
- Page</link> (and on the covers, if any) a title distinct
- from that of the <link
- linkend="fdl-document">Document</link>, and from those of
- previous versions (which should, if there were any, be
- listed in the History section of the Document). You may
- use the same title as a previous version if the original
- publisher of that version gives permission.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>B</title>
- <para>
- List on the <link linkend="fdl-title-page">Title
- Page</link>, as authors, one or more persons or entities
- responsible for authorship of the modifications in the
- <link linkend="fdl-modified">Modified Version</link>,
- together with at least five of the principal authors of
- the <link linkend="fdl-document">Document</link> (all of
- its principal authors, if it has less than five).
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>C</title>
- <para>
- State on the <link linkend="fdl-title-page">Title
- Page</link> the name of the publisher of the <link
- linkend="fdl-modified">Modified Version</link>, as the
- publisher.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>D</title>
- <para>
- Preserve all the copyright notices of the <link
- linkend="fdl-document">Document</link>.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>E</title>
- <para>
- Add an appropriate copyright notice for your modifications
- adjacent to the other copyright notices.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>F</title>
- <para>
- Include, immediately after the copyright notices, a
- license notice giving the public permission to use the
- <link linkend="fdl-modified">Modified Version</link> under
- the terms of this License, in the form shown in the
- Addendum below.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>G</title>
- <para>
- Preserve in that license notice the full lists of <link
- linkend="fdl-invariant"> Invariant Sections</link> and
- required <link linkend="fdl-cover-texts">Cover
- Texts</link> given in the <link
- linkend="fdl-document">Document's</link> license notice.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>H</title>
- <para>
- Include an unaltered copy of this License.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>I</title>
- <para>
- Preserve the section entitled <quote>History</quote>, and
- its title, and add to it an item stating at least the
- title, year, new authors, and publisher of the <link
- linkend="fdl-modified">Modified Version </link>as given on
- the <link linkend="fdl-title-page">Title Page</link>. If
- there is no section entitled <quote>History</quote> in the
- <link linkend="fdl-document">Document</link>, create one
- stating the title, year, authors, and publisher of the
- Document as given on its Title Page, then add an item
- describing the Modified Version as stated in the previous
- sentence.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>J</title>
- <para>
- Preserve the network location, if any, given in the <link
- linkend="fdl-document">Document</link> for public access
- to a <link linkend="fdl-transparent">Transparent</link>
- copy of the Document, and likewise the network locations
- given in the Document for previous versions it was based
- on. These may be placed in the <quote>History</quote>
- section. You may omit a network location for a work that
- was published at least four years before the Document
- itself, or if the original publisher of the version it
- refers to gives permission.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>K</title>
- <para>
- In any section entitled <quote>Acknowledgements</quote> or
- <quote>Dedications</quote>, preserve the section's title,
- and preserve in the section all the substance and tone of
- each of the contributor acknowledgements and/or
- dedications given therein.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>L</title>
- <para>
- Preserve all the <link linkend="fdl-invariant">Invariant
- Sections</link> of the <link
- linkend="fdl-document">Document</link>, unaltered in their
- text and in their titles. Section numbers or the
- equivalent are not considered part of the section titles.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>M</title>
- <para>
- Delete any section entitled
- <quote>Endorsements</quote>. Such a section may not be
- included in the <link linkend="fdl-modified">Modified
- Version</link>.
- </para>
- </formalpara>
- </listitem>
-
- <listitem>
- <formalpara>
- <title>N</title>
- <para>
- Do not retitle any existing section as
- <quote>Endorsements</quote> or to conflict in title with
- any <link linkend="fdl-invariant">Invariant
- Section</link>.
- </para>
- </formalpara>
- </listitem>
- </itemizedlist>
-
- <para>
- If the <link linkend="fdl-modified">Modified Version</link>
- includes new front-matter sections or appendices that qualify as
- <link linkend="fdl-secondary">Secondary Sections</link> and
- contain no material copied from the Document, you may at your
- option designate some or all of these sections as invariant. To
- do this, add their titles to the list of <link
- linkend="fdl-invariant">Invariant Sections</link> in the
- Modified Version's license notice. These titles must be
- distinct from any other section titles.
- </para>
-
- <para>
- You may add a section entitled <quote>Endorsements</quote>,
- provided it contains nothing but endorsements of your <link
- linkend="fdl-modified">Modified Version</link> by various
- parties--for example, statements of peer review or that the text
- has been approved by an organization as the authoritative
- definition of a standard.
- </para>
-
- <para>
- You may add a passage of up to five words as a <link
- linkend="fdl-cover-texts">Front-Cover Text</link>, and a passage
- of up to 25 words as a <link
- linkend="fdl-cover-texts">Back-Cover Text</link>, to the end of
- the list of <link linkend="fdl-cover-texts">Cover Texts</link>
- in the <link linkend="fdl-modified">Modified Version</link>.
- Only one passage of Front-Cover Text and one of Back-Cover Text
- may be added by (or through arrangements made by) any one
- entity. If the <link linkend="fdl-document">Document</link>
- already includes a cover text for the same cover, previously
- added by you or by arrangement made by the same entity you are
- acting on behalf of, you may not add another; but you may
- replace the old one, on explicit permission from the previous
- publisher that added the old one.
- </para>
-
- <para>
- The author(s) and publisher(s) of the <link
- linkend="fdl-document">Document</link> do not by this License
- give permission to use their names for publicity for or to
- assert or imply endorsement of any <link
- linkend="fdl-modified">Modified Version </link>.
- </para>
- </sect1>
-
- <sect1 id="fdl-section5">
- <title>5. COMBINING DOCUMENTS</title>
- <para>
- You may combine the <link linkend="fdl-document">Document</link>
- with other documents released under this License, under the
- terms defined in <link linkend="fdl-section4">section 4</link>
- above for modified versions, provided that you include in the
- combination all of the <link linkend="fdl-invariant">Invariant
- Sections</link> of all of the original documents, unmodified,
- and list them all as Invariant Sections of your combined work in
- its license notice.
- </para>
-
- <para>
- The combined work need only contain one copy of this License,
- and multiple identical <link linkend="fdl-invariant">Invariant
- Sections</link> may be replaced with a single copy. If there are
- multiple Invariant Sections with the same name but different
- contents, make the title of each such section unique by adding
- at the end of it, in parentheses, the name of the original
- author or publisher of that section if known, or else a unique
- number. Make the same adjustment to the section titles in the
- list of Invariant Sections in the license notice of the combined
- work.
- </para>
-
- <para>
- In the combination, you must combine any sections entitled
- <quote>History</quote> in the various original documents,
- forming one section entitled <quote>History</quote>; likewise
- combine any sections entitled <quote>Acknowledgements</quote>,
- and any sections entitled <quote>Dedications</quote>. You must
- delete all sections entitled <quote>Endorsements.</quote>
- </para>
- </sect1>
-
- <sect1 id="fdl-section6">
- <title>6. COLLECTIONS OF DOCUMENTS</title>
- <para>
- You may make a collection consisting of the <link
- linkend="fdl-document">Document</link> and other documents
- released under this License, and replace the individual copies
- of this License in the various documents with a single copy that
- is included in the collection, provided that you follow the
- rules of this License for verbatim copying of each of the
- documents in all other respects.
- </para>
-
- <para>
- You may extract a single document from such a collection, and
- distribute it individually under this License, provided you
- insert a copy of this License into the extracted document, and
- follow this License in all other respects regarding verbatim
- copying of that document.
- </para>
- </sect1>
-
- <sect1 id="fdl-section7">
- <title>7. AGGREGATION WITH INDEPENDENT WORKS</title>
- <para>
- A compilation of the <link
- linkend="fdl-document">Document</link> or its derivatives with
- other separate and independent documents or works, in or on a
- volume of a storage or distribution medium, does not as a whole
- count as a <link linkend="fdl-modified">Modified Version</link>
- of the Document, provided no compilation copyright is claimed
- for the compilation. Such a compilation is called an
- <quote>aggregate</quote>, and this License does not apply to the
- other self-contained works thus compiled with the Document , on
- account of their being thus compiled, if they are not themselves
- derivative works of the Document. If the <link
- linkend="fdl-cover-texts">Cover Text</link> requirement of <link
- linkend="fdl-section3">section 3</link> is applicable to these
- copies of the Document, then if the Document is less than one
- quarter of the entire aggregate, the Document's Cover Texts may
- be placed on covers that surround only the Document within the
- aggregate. Otherwise they must appear on covers around the whole
- aggregate.
- </para>
- </sect1>
-
- <sect1 id="fdl-section8">
- <title>8. TRANSLATION</title>
- <para>
- Translation is considered a kind of modification, so you may
- distribute translations of the <link
- linkend="fdl-document">Document</link> under the terms of <link
- linkend="fdl-section4">section 4</link>. Replacing <link
- linkend="fdl-invariant"> Invariant Sections</link> with
- translations requires special permission from their copyright
- holders, but you may include translations of some or all
- Invariant Sections in addition to the original versions of these
- Invariant Sections. You may include a translation of this
- License provided that you also include the original English
- version of this License. In case of a disagreement between the
- translation and the original English version of this License,
- the original English version will prevail.
- </para>
- </sect1>
-
- <sect1 id="fdl-section9">
- <title>9. TERMINATION</title>
- <para>
- You may not copy, modify, sublicense, or distribute the <link
- linkend="fdl-document">Document</link> except as expressly
- provided for under this License. Any other attempt to copy,
- modify, sublicense or distribute the Document is void, and will
- automatically terminate your rights under this License. However,
- parties who have received copies, or rights, from you under this
- License will not have their licenses terminated so long as such
- parties remain in full compliance.
- </para>
- </sect1>
-
- <sect1 id="fdl-section10">
- <title>10. FUTURE REVISIONS OF THIS LICENSE</title>
- <para>
- The <ulink type="http"
- url="http://www.gnu.org/fsf/fsf.html">Free Software
- Foundation</ulink> may publish new, revised versions of the GNU
- Free Documentation License from time to time. Such new versions
- will be similar in spirit to the present version, but may differ
- in detail to address new problems or concerns. See <ulink
- type="http"
- url="http://www.gnu.org/copyleft">http://www.gnu.org/copyleft/</ulink>.
- </para>
-
- <para>
- Each version of the License is given a distinguishing version
- number. If the <link linkend="fdl-document">Document</link>
- specifies that a particular numbered version of this License
- <quote>or any later version</quote> applies to it, you have the
- option of following the terms and conditions either of that
- specified version or of any later version that has been
- published (not as a draft) by the Free Software Foundation. If
- the Document does not specify a version number of this License,
- you may choose any version ever published (not as a draft) by
- the Free Software Foundation.
- </para>
- </sect1>
-
- <sect1 id="fdl-using">
- <title>Addendum</title>
- <para>
- To use this License in a document you have written, include a copy of
- the License in the document and put the following copyright and
- license notices just after the title page:
- </para>
-
- <blockquote>
- <para>
- Copyright &copy; YEAR YOUR NAME.
- </para>
- <para>
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the GNU Free Documentation
- License, Version 1.1 or any later version published by the
- Free Software Foundation; with the <link
- linkend="fdl-invariant">Invariant Sections</link> being LIST
- THEIR TITLES, with the <link
- linkend="fdl-cover-texts">Front-Cover Texts</link> being LIST,
- and with the <link linkend="fdl-cover-texts">Back-Cover
- Texts</link> being LIST. A copy of the license is included in
- the section entitled <quote>GNU Free Documentation
- License</quote>.
- </para>
- </blockquote>
-
- <para>
- If you have no <link linkend="fdl-invariant">Invariant
- Sections</link>, write <quote>with no Invariant Sections</quote>
- instead of saying which ones are invariant. If you have no
- <link linkend="fdl-cover-texts">Front-Cover Texts</link>, write
- <quote>no Front-Cover Texts</quote> instead of
- <quote>Front-Cover Texts being LIST</quote>; likewise for <link
- linkend="fdl-cover-texts">Back-Cover Texts</link>.
- </para>
-
- <para>
- If your document contains nontrivial examples of program code,
- we recommend releasing these examples in parallel under your
- choice of free software license, such as the <ulink type="http"
- url="http://www.gnu.org/copyleft/gpl.html"> GNU General Public
- License</ulink>, to permit their use in free software.
- </para>
- </sect1>
-</appendix>
-
-
-
-
-
-
diff --git a/Documentation/DocBook/media/v4l/fieldseq_bt.pdf b/Documentation/DocBook/media/v4l/fieldseq_bt.pdf
deleted file mode 100644
index 26598b23f80d..000000000000
--- a/Documentation/DocBook/media/v4l/fieldseq_bt.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/fieldseq_tb.pdf b/Documentation/DocBook/media/v4l/fieldseq_tb.pdf
deleted file mode 100644
index 4965b22ddb3a..000000000000
--- a/Documentation/DocBook/media/v4l/fieldseq_tb.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/func-close.xml b/Documentation/DocBook/media/v4l/func-close.xml
deleted file mode 100644
index 232920d2f3c6..000000000000
--- a/Documentation/DocBook/media/v4l/func-close.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<refentry id="func-close">
- <refmeta>
- <refentrytitle>V4L2 close()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-close</refname>
- <refpurpose>Close a V4L2 device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>close</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Closes the device. Any I/O in progress is terminated and
-resources associated with the file descriptor are freed. However data
-format parameters, current input or output, control values or other
-properties remain unchanged.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>The function returns <returnvalue>0</returnvalue> on
-success, <returnvalue>-1</returnvalue> on failure and the
-<varname>errno</varname> is set appropriately. Possible error
-codes:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid open file
-descriptor.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-ioctl.xml b/Documentation/DocBook/media/v4l/func-ioctl.xml
deleted file mode 100644
index 4394184a1a6d..000000000000
--- a/Documentation/DocBook/media/v4l/func-ioctl.xml
+++ /dev/null
@@ -1,71 +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>
- &return-value;
- <para>When an ioctl that takes an output or read/write parameter fails,
- the parameter remains unmodified.</para>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-mmap.xml b/Documentation/DocBook/media/v4l/func-mmap.xml
deleted file mode 100644
index f31ad71bf301..000000000000
--- a/Documentation/DocBook/media/v4l/func-mmap.xml
+++ /dev/null
@@ -1,183 +0,0 @@
-<refentry id="func-mmap">
- <refmeta>
- <refentrytitle>V4L2 mmap()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-mmap</refname>
- <refpurpose>Map device memory into application address space</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;unistd.h&gt;
-#include &lt;sys/mman.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>void *<function>mmap</function></funcdef>
- <paramdef>void *<parameter>start</parameter></paramdef>
- <paramdef>size_t <parameter>length</parameter></paramdef>
- <paramdef>int <parameter>prot</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>off_t <parameter>offset</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>start</parameter></term>
- <listitem>
- <para>Map the buffer to this address in the
-application's address space. When the <constant>MAP_FIXED</constant>
-flag is specified, <parameter>start</parameter> must be a multiple of the
-pagesize and mmap will fail when the specified address
-cannot be used. Use of this option is discouraged; applications should
-just specify a <constant>NULL</constant> pointer here.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>length</parameter></term>
- <listitem>
- <para>Length of the memory area to map. This must be the
-same value as returned by the driver in the &v4l2-buffer;
-<structfield>length</structfield> field for the
-single-planar API, and the same value as returned by the driver
-in the &v4l2-plane; <structfield>length</structfield> field for the
-multi-planar API.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>prot</parameter></term>
- <listitem>
- <para>The <parameter>prot</parameter> argument describes the
-desired memory protection. Regardless of the device type and the
-direction of data exchange it should be set to
-<constant>PROT_READ</constant> | <constant>PROT_WRITE</constant>,
-permitting read and write access to image buffers. Drivers should
-support at least this combination of flags. Note the Linux
-<filename>video-buf</filename> kernel module, which is used by the
-bttv, saa7134, saa7146, cx88 and vivi driver supports only
-<constant>PROT_READ</constant> | <constant>PROT_WRITE</constant>. When
-the driver does not support the desired protection the
-<function>mmap()</function> function fails.</para>
- <para>Note device memory accesses (&eg; the memory on a
-graphics card with video capturing hardware) may incur a performance
-penalty compared to main memory accesses, or reads may be
-significantly slower than writes or vice versa. Other I/O methods may
-be more efficient in this case.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>The <parameter>flags</parameter> parameter
-specifies the type of the mapped object, mapping options and whether
-modifications made to the mapped copy of the page are private to the
-process or are to be shared with other references.</para>
- <para><constant>MAP_FIXED</constant> requests that the
-driver selects no other address than the one specified. If the
-specified address cannot be used, <function>mmap()</function> will fail. If
-<constant>MAP_FIXED</constant> is specified,
-<parameter>start</parameter> must be a multiple of the pagesize. Use
-of this option is discouraged.</para>
- <para>One of the <constant>MAP_SHARED</constant> or
-<constant>MAP_PRIVATE</constant> flags must be set.
-<constant>MAP_SHARED</constant> allows applications to share the
-mapped memory with other (&eg; child-) processes. Note the Linux
-<filename>video-buf</filename> module which is used by the bttv,
-saa7134, saa7146, cx88 and vivi driver supports only
-<constant>MAP_SHARED</constant>. <constant>MAP_PRIVATE</constant>
-requests copy-on-write semantics. V4L2 applications should not set the
-<constant>MAP_PRIVATE</constant>, <constant>MAP_DENYWRITE</constant>,
-<constant>MAP_EXECUTABLE</constant> or <constant>MAP_ANON</constant>
-flag.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fd;</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>offset</parameter></term>
- <listitem>
- <para>Offset of the buffer in device memory. This must be the
-same value as returned by the driver in the &v4l2-buffer;
-<structfield>m</structfield> union <structfield>offset</structfield> field for
-the single-planar API, and the same value as returned by the driver
-in the &v4l2-plane; <structfield>m</structfield> union
-<structfield>mem_offset</structfield> field for the multi-planar API.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The <function>mmap()</function> function asks to map
-<parameter>length</parameter> bytes starting at
-<parameter>offset</parameter> in the memory of the device specified by
-<parameter>fd</parameter> into the application address space,
-preferably at address <parameter>start</parameter>. This latter
-address is a hint only, and is usually specified as 0.</para>
-
- <para>Suitable length and offset parameters are queried with the
-&VIDIOC-QUERYBUF; ioctl. Buffers must be allocated with the
-&VIDIOC-REQBUFS; ioctl before they can be queried.</para>
-
- <para>To unmap buffers the &func-munmap; function is used.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success <function>mmap()</function> returns a pointer to
-the mapped buffer. On error <constant>MAP_FAILED</constant> (-1) is
-returned, and the <varname>errno</varname> variable is set
-appropriately. Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid file
-descriptor.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is
-not open for reading and writing.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <parameter>start</parameter> or
-<parameter>length</parameter> or <parameter>offset</parameter> are not
-suitable. (E.&nbsp;g. they are too large, or not aligned on a
-<constant>PAGESIZE</constant> boundary.)</para>
- <para>The <parameter>flags</parameter> or
-<parameter>prot</parameter> value is not supported.</para>
- <para>No buffers have been allocated with the
-&VIDIOC-REQBUFS; ioctl.</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>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-munmap.xml b/Documentation/DocBook/media/v4l/func-munmap.xml
deleted file mode 100644
index 860d49ca54a5..000000000000
--- a/Documentation/DocBook/media/v4l/func-munmap.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<refentry id="func-munmap">
- <refmeta>
- <refentrytitle>V4L2 munmap()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-munmap</refname>
- <refpurpose>Unmap device memory</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;unistd.h&gt;
-#include &lt;sys/mman.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>munmap</function></funcdef>
- <paramdef>void *<parameter>start</parameter></paramdef>
- <paramdef>size_t <parameter>length</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
- <refsect1>
- <title>Arguments</title>
- <variablelist>
- <varlistentry>
- <term><parameter>start</parameter></term>
- <listitem>
- <para>Address of the mapped buffer as returned by the
-&func-mmap; function.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>length</parameter></term>
- <listitem>
- <para>Length of the mapped buffer. This must be the same
-value as given to <function>mmap()</function> and returned by the
-driver in the &v4l2-buffer; <structfield>length</structfield>
-field for the single-planar API and in the &v4l2-plane;
-<structfield>length</structfield> field for the multi-planar API.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Unmaps a previously with the &func-mmap; function mapped
-buffer and frees it, if possible. <!-- ? This function (not freeing)
-has no impact on I/O in progress, specifically it does not imply
-&VIDIOC-STREAMOFF; to terminate I/O. Unmapped buffers can still be
-enqueued, dequeued or queried, they are just not accessible by the
-application.--></para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success <function>munmap()</function> returns 0, on
-failure -1 and the <varname>errno</varname> variable is set
-appropriately:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <parameter>start</parameter> or
-<parameter>length</parameter> is incorrect, or no buffers have been
-mapped yet.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-open.xml b/Documentation/DocBook/media/v4l/func-open.xml
deleted file mode 100644
index cf64e207c3ee..000000000000
--- a/Documentation/DocBook/media/v4l/func-open.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<refentry id="func-open">
- <refmeta>
- <refentrytitle>V4L2 open()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-open</refname>
- <refpurpose>Open a V4L2 device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>open</function></funcdef>
- <paramdef>const char *<parameter>device_name</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>device_name</parameter></term>
- <listitem>
- <para>Device to be opened.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>Open flags. Access mode must be
-<constant>O_RDWR</constant>. This is just a technicality, input devices
-still support only reading and output devices only writing.</para>
- <para>When the <constant>O_NONBLOCK</constant> flag is
-given, the read() function and the &VIDIOC-DQBUF; ioctl will return
-the &EAGAIN; when no data is available or no buffer is in the driver
-outgoing queue, otherwise these functions block until data becomes
-available. All V4L2 drivers exchanging data with applications must
-support the <constant>O_NONBLOCK</constant> flag.</para>
- <para>Other flags have no effect.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Description</title>
-
- <para>To open a V4L2 device applications call
-<function>open()</function> with the desired device name. This
-function has no side effects; all data format parameters, current
-input or output, control values or other properties remain unchanged.
-At the first <function>open()</function> call after loading the driver
-they will be reset to default values, drivers are never in an
-undefined state.</para>
- </refsect1>
- <refsect1>
- <title>Return Value</title>
-
- <para>On success <function>open</function> returns the new file
-descriptor. On error -1 is returned, and the <varname>errno</varname>
-variable is set appropriately. Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para>The caller has no permission to access the
-device.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The driver does not support multiple opens and the
-device is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENXIO</errorcode></term>
- <listitem>
- <para>No device corresponding to this device special file
-exists.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOMEM</errorcode></term>
- <listitem>
- <para>Not enough kernel memory was available to complete the
-request.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EMFILE</errorcode></term>
- <listitem>
- <para>The process already has the maximum number of
-files open.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENFILE</errorcode></term>
- <listitem>
- <para>The limit on the total number of files open on the
-system has been reached.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-poll.xml b/Documentation/DocBook/media/v4l/func-poll.xml
deleted file mode 100644
index 4c73f115219b..000000000000
--- a/Documentation/DocBook/media/v4l/func-poll.xml
+++ /dev/null
@@ -1,142 +0,0 @@
-<refentry id="func-poll">
- <refmeta>
- <refentrytitle>V4L2 poll()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-poll</refname>
- <refpurpose>Wait for some event on a file descriptor</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;sys/poll.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>poll</function></funcdef>
- <paramdef>struct pollfd *<parameter>ufds</parameter></paramdef>
- <paramdef>unsigned int <parameter>nfds</parameter></paramdef>
- <paramdef>int <parameter>timeout</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>With the <function>poll()</function> function applications
-can suspend execution until the driver has captured data or is ready
-to accept data for output.</para>
-
- <para>When streaming I/O has been negotiated this function waits
-until a buffer has been filled by the capture device and can be dequeued
-with the &VIDIOC-DQBUF; ioctl. For output devices this function waits
-until the device is ready to accept a new buffer to be queued up with
-the &VIDIOC-QBUF; ioctl for display. When buffers are already in the outgoing
-queue of the driver (capture) or the incoming queue isn't full (display)
-the function returns immediately.</para>
-
- <para>On success <function>poll()</function> returns the number of
-file descriptors that have been selected (that is, file descriptors
-for which the <structfield>revents</structfield> field of the
-respective <structname>pollfd</structname> structure is non-zero).
-Capture devices set the <constant>POLLIN</constant> and
-<constant>POLLRDNORM</constant> flags in the
-<structfield>revents</structfield> field, output devices the
-<constant>POLLOUT</constant> and <constant>POLLWRNORM</constant>
-flags. When the function timed out it returns a value of zero, on
-failure it returns <returnvalue>-1</returnvalue> and the
-<varname>errno</varname> variable is set appropriately. When the
-application did not call &VIDIOC-STREAMON; the
-<function>poll()</function> function succeeds, but sets the
-<constant>POLLERR</constant> flag in the
-<structfield>revents</structfield> field. When the
-application has called &VIDIOC-STREAMON; for a capture device but hasn't
-yet called &VIDIOC-QBUF;, the <function>poll()</function> function
-succeeds and sets the <constant>POLLERR</constant> flag in the
-<structfield>revents</structfield> field. For output devices this
-same situation will cause <function>poll()</function> to succeed
-as well, but it sets the <constant>POLLOUT</constant> and
-<constant>POLLWRNORM</constant> flags in the <structfield>revents</structfield>
-field.</para>
-
- <para>If an event occurred (see &VIDIOC-DQEVENT;) then
-<constant>POLLPRI</constant> will be set in the <structfield>revents</structfield>
-field and <function>poll()</function> will return.</para>
-
- <para>When use of the <function>read()</function> function has
-been negotiated and the driver does not capture yet, the
-<function>poll</function> function starts capturing. When that fails
-it returns a <constant>POLLERR</constant> as above. Otherwise it waits
-until data has been captured and can be read. When the driver captures
-continuously (as opposed to, for example, still images) the function
-may return immediately.</para>
-
- <para>When use of the <function>write()</function> function has
-been negotiated and the driver does not stream yet, the
-<function>poll</function> function starts streaming. When that fails
-it returns a <constant>POLLERR</constant> as above. Otherwise it waits
-until the driver is ready for a non-blocking
-<function>write()</function> call.</para>
-
- <para>If the caller is only interested in events (just
-<constant>POLLPRI</constant> is set in the <structfield>events</structfield>
-field), then <function>poll()</function> will <emphasis>not</emphasis>
-start streaming if the driver does not stream yet. This makes it
-possible to just poll for events and not for buffers.</para>
-
- <para>All drivers implementing the <function>read()</function> or
-<function>write()</function> function or streaming I/O must also
-support the <function>poll()</function> function.</para>
-
- <para>For more details see the
-<function>poll()</function> manual page.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, <function>poll()</function> returns the number
-structures which have non-zero <structfield>revents</structfield>
-fields, or zero if the call timed out. On error
-<returnvalue>-1</returnvalue> is returned, and the
-<varname>errno</varname> variable is set appropriately:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para>One or more of the <parameter>ufds</parameter> members
-specify an invalid file descriptor.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The driver does not support multiple read or write
-streams and the device is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EFAULT</errorcode></term>
- <listitem>
- <para><parameter>ufds</parameter> references an inaccessible
-memory area.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINTR</errorcode></term>
- <listitem>
- <para>The call was interrupted by a signal.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <parameter>nfds</parameter> argument is greater
-than <constant>OPEN_MAX</constant>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-read.xml b/Documentation/DocBook/media/v4l/func-read.xml
deleted file mode 100644
index e218bbfbd362..000000000000
--- a/Documentation/DocBook/media/v4l/func-read.xml
+++ /dev/null
@@ -1,181 +0,0 @@
-<refentry id="func-read">
- <refmeta>
- <refentrytitle>V4L2 read()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-read</refname>
- <refpurpose>Read from a V4L2 device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>ssize_t <function>read</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>void *<parameter>buf</parameter></paramdef>
- <paramdef>size_t <parameter>count</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>buf</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>count</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para><function>read()</function> attempts to read up to
-<parameter>count</parameter> bytes from file descriptor
-<parameter>fd</parameter> into the buffer starting at
-<parameter>buf</parameter>. The layout of the data in the buffer is
-discussed in the respective device interface section, see ##. If <parameter>count</parameter> is zero,
-<function>read()</function> returns zero and has no other results. If
-<parameter>count</parameter> is greater than
-<constant>SSIZE_MAX</constant>, the result is unspecified. Regardless
-of the <parameter>count</parameter> value each
-<function>read()</function> call will provide at most one frame (two
-fields) worth of data.</para>
-
- <para>By default <function>read()</function> blocks until data
-becomes available. When the <constant>O_NONBLOCK</constant> flag was
-given to the &func-open; function it
-returns immediately with an &EAGAIN; when no data is available. The
-&func-select; or &func-poll; functions
-can always be used to suspend execution until data becomes available. All
-drivers supporting the <function>read()</function> function must also
-support <function>select()</function> and
-<function>poll()</function>.</para>
-
- <para>Drivers can implement read functionality in different
-ways, using a single or multiple buffers and discarding the oldest or
-newest frames once the internal buffers are filled.</para>
-
- <para><function>read()</function> never returns a "snapshot" of a
-buffer being filled. Using a single buffer the driver will stop
-capturing when the application starts reading the buffer until the
-read is finished. Thus only the period of the vertical blanking
-interval is available for reading, or the capture rate must fall below
-the nominal frame rate of the video standard.</para>
-
-<para>The behavior of
-<function>read()</function> when called during the active picture
-period or the vertical blanking separating the top and bottom field
-depends on the discarding policy. A driver discarding the oldest
-frames keeps capturing into an internal buffer, continuously
-overwriting the previously, not read frame, and returns the frame
-being received at the time of the <function>read()</function> call as
-soon as it is complete.</para>
-
- <para>A driver discarding the newest frames stops capturing until
-the next <function>read()</function> call. The frame being received at
-<function>read()</function> time is discarded, returning the following
-frame instead. Again this implies a reduction of the capture rate to
-one half or less of the nominal frame rate. An example of this model
-is the video read mode of the bttv driver, initiating a DMA to user
-memory when <function>read()</function> is called and returning when
-the DMA finished.</para>
-
- <para>In the multiple buffer model drivers maintain a ring of
-internal buffers, automatically advancing to the next free buffer.
-This allows continuous capturing when the application can empty the
-buffers fast enough. Again, the behavior when the driver runs out of
-free buffers depends on the discarding policy.</para>
-
- <para>Applications can get and set the number of buffers used
-internally by the driver with the &VIDIOC-G-PARM; and &VIDIOC-S-PARM;
-ioctls. They are optional, however. The discarding policy is not
-reported and cannot be changed. For minimum requirements see <xref
- linkend="devices" />.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, the number of bytes read is returned. It is not
-an error if this number is smaller than the number of bytes requested,
-or the amount of data required for one frame. This may happen for
-example because <function>read()</function> was interrupted by a
-signal. On error, -1 is returned, and the <varname>errno</varname>
-variable is set appropriately. In this case the next read will start
-at the beginning of a new frame. Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EAGAIN</errorcode></term>
- <listitem>
- <para>Non-blocking I/O has been selected using
-O_NONBLOCK and no data was immediately available for reading.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid file
-descriptor or is not open for reading, or the process already has the
-maximum number of files open.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The driver does not support multiple read streams and the
-device is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EFAULT</errorcode></term>
- <listitem>
- <para><parameter>buf</parameter> references an inaccessible
-memory area.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINTR</errorcode></term>
- <listitem>
- <para>The call was interrupted by a signal before any
-data was read.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EIO</errorcode></term>
- <listitem>
- <para>I/O error. This indicates some hardware problem or a
-failure to communicate with a remote device (USB camera etc.).</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <function>read()</function> function is not
-supported by this driver, not on this device, or generally not on this
-type of device.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-select.xml b/Documentation/DocBook/media/v4l/func-select.xml
deleted file mode 100644
index e12a60d9bd85..000000000000
--- a/Documentation/DocBook/media/v4l/func-select.xml
+++ /dev/null
@@ -1,130 +0,0 @@
-<refentry id="func-select">
- <refmeta>
- <refentrytitle>V4L2 select()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-select</refname>
- <refpurpose>Synchronous I/O multiplexing</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>
-#include &lt;sys/time.h&gt;
-#include &lt;sys/types.h&gt;
-#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>select</function></funcdef>
- <paramdef>int <parameter>nfds</parameter></paramdef>
- <paramdef>fd_set *<parameter>readfds</parameter></paramdef>
- <paramdef>fd_set *<parameter>writefds</parameter></paramdef>
- <paramdef>fd_set *<parameter>exceptfds</parameter></paramdef>
- <paramdef>struct timeval *<parameter>timeout</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>With the <function>select()</function> function applications
-can suspend execution until the driver has captured data or is ready
-to accept data for output.</para>
-
- <para>When streaming I/O has been negotiated this function waits
-until a buffer has been filled or displayed and can be dequeued with
-the &VIDIOC-DQBUF; ioctl. When buffers are already in the outgoing
-queue of the driver the function returns immediately.</para>
-
- <para>On success <function>select()</function> returns the total
-number of bits set in the <structname>fd_set</structname>s. When the
-function timed out it returns a value of zero. On failure it returns
-<returnvalue>-1</returnvalue> and the <varname>errno</varname>
-variable is set appropriately. When the application did not call
-&VIDIOC-QBUF; or &VIDIOC-STREAMON; yet the
-<function>select()</function> function succeeds, setting the bit of
-the file descriptor in <parameter>readfds</parameter> or
-<parameter>writefds</parameter>, but subsequent &VIDIOC-DQBUF; calls
-will fail.<footnote><para>The Linux kernel implements
-<function>select()</function> like the &func-poll; function, but
-<function>select()</function> cannot return a
-<constant>POLLERR</constant>.</para>
- </footnote></para>
-
- <para>When use of the <function>read()</function> function has
-been negotiated and the driver does not capture yet, the
-<function>select()</function> function starts capturing. When that
-fails, <function>select()</function> returns successful and a
-subsequent <function>read()</function> call, which also attempts to
-start capturing, will return an appropriate error code. When the
-driver captures continuously (as opposed to, for example, still
-images) and data is already available the
-<function>select()</function> function returns immediately.</para>
-
- <para>When use of the <function>write()</function> function has
-been negotiated the <function>select()</function> function just waits
-until the driver is ready for a non-blocking
-<function>write()</function> call.</para>
-
- <para>All drivers implementing the <function>read()</function> or
-<function>write()</function> function or streaming I/O must also
-support the <function>select()</function> function.</para>
-
- <para>For more details see the <function>select()</function>
-manual page.</para>
-
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, <function>select()</function> returns the number
-of descriptors contained in the three returned descriptor sets, which
-will be zero if the timeout expired. On error
-<returnvalue>-1</returnvalue> is returned, and the
-<varname>errno</varname> variable is set appropriately; the sets and
-<parameter>timeout</parameter> are undefined. Possible error codes
-are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para>One or more of the file descriptor sets specified a
-file descriptor that is not open.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The driver does not support multiple read or write
-streams and the device is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EFAULT</errorcode></term>
- <listitem>
- <para>The <parameter>readfds</parameter>,
-<parameter>writefds</parameter>, <parameter>exceptfds</parameter> or
-<parameter>timeout</parameter> pointer references an inaccessible memory
-area.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINTR</errorcode></term>
- <listitem>
- <para>The call was interrupted by a signal.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <parameter>nfds</parameter> argument is less than
-zero or greater than <constant>FD_SETSIZE</constant>.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/func-write.xml b/Documentation/DocBook/media/v4l/func-write.xml
deleted file mode 100644
index 575207885726..000000000000
--- a/Documentation/DocBook/media/v4l/func-write.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<refentry id="func-write">
- <refmeta>
- <refentrytitle>V4L2 write()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>v4l2-write</refname>
- <refpurpose>Write to a V4L2 device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>ssize_t <function>write</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>void *<parameter>buf</parameter></paramdef>
- <paramdef>size_t <parameter>count</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>buf</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>count</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para><function>write()</function> writes up to
-<parameter>count</parameter> bytes to the device referenced by the
-file descriptor <parameter>fd</parameter> from the buffer starting at
-<parameter>buf</parameter>. When the hardware outputs are not active
-yet, this function enables them. When <parameter>count</parameter> is
-zero, <function>write()</function> returns
-<returnvalue>0</returnvalue> without any other effect.</para>
-
- <para>When the application does not provide more data in time, the
-previous video frame, raw VBI image, sliced VPS or WSS data is
-displayed again. Sliced Teletext or Closed Caption data is not
-repeated, the driver inserts a blank line instead.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para>On success, the number of bytes written are returned. Zero
-indicates nothing was written. On error, <returnvalue>-1</returnvalue>
-is returned, and the <varname>errno</varname> variable is set
-appropriately. In this case the next write will start at the beginning
-of a new frame. Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EAGAIN</errorcode></term>
- <listitem>
- <para>Non-blocking I/O has been selected using the <link
-linkend="func-open"><constant>O_NONBLOCK</constant></link> flag and no
-buffer space was available to write the data immediately.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid file
-descriptor or is not open for writing.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The driver does not support multiple write streams and the
-device is already in use.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EFAULT</errorcode></term>
- <listitem>
- <para><parameter>buf</parameter> references an inaccessible
-memory area.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINTR</errorcode></term>
- <listitem>
- <para>The call was interrupted by a signal before any
-data was written.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EIO</errorcode></term>
- <listitem>
- <para>I/O error. This indicates some hardware problem.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <function>write()</function> function is not
-supported by this driver, not on this device, or generally not on this
-type of device.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/gen-errors.xml b/Documentation/DocBook/media/v4l/gen-errors.xml
deleted file mode 100644
index 7e29a4e1f696..000000000000
--- a/Documentation/DocBook/media/v4l/gen-errors.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<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>EAGAIN (aka EWOULDBLOCK)</entry>
- <entry>The ioctl can't be handled because the device is in state where
- it can't perform it. This could happen for example in case where
- device is sleeping and ioctl is performed to query statistics.
- It is also returned when the ioctl would need to wait
- for an event, but the device was opened in non-blocking mode.
- </entry>
- </row>
- <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>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>
- </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>
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
deleted file mode 100644
index 21a3dde8f95d..000000000000
--- a/Documentation/DocBook/media/v4l/io.xml
+++ /dev/null
@@ -1,1545 +0,0 @@
- <title>Input/Output</title>
-
- <para>The V4L2 API defines several different methods to read from or
-write to a device. All drivers exchanging data with applications must
-support at least one of them.</para>
-
- <para>The classic I/O method using the <function>read()</function>
-and <function>write()</function> function is automatically selected
-after opening a V4L2 device. When the driver does not support this
-method attempts to read or write will fail at any time.</para>
-
- <para>Other methods must be negotiated. To select the streaming I/O
-method with memory mapped or user buffers applications call the
-&VIDIOC-REQBUFS; ioctl. The asynchronous I/O method is not defined
-yet.</para>
-
- <para>Video overlay can be considered another I/O method, although
-the application does not directly receive the image data. It is
-selected by initiating video overlay with the &VIDIOC-S-FMT; ioctl.
-For more information see <xref linkend="overlay" />.</para>
-
- <para>Generally exactly one I/O method, including overlay, is
-associated with each file descriptor. The only exceptions are
-applications not exchanging data with a driver ("panel applications",
-see <xref linkend="open" />) and drivers permitting simultaneous video capturing
-and overlay using the same file descriptor, for compatibility with V4L
-and earlier versions of V4L2.</para>
-
- <para><constant>VIDIOC_S_FMT</constant> and
-<constant>VIDIOC_REQBUFS</constant> would permit this to some degree,
-but for simplicity drivers need not support switching the I/O method
-(after first switching away from read/write) other than by closing
-and reopening the device.</para>
-
- <para>The following sections describe the various I/O methods in
-more detail.</para>
-
- <section id="rw">
- <title>Read/Write</title>
-
- <para>Input and output devices support the
-<function>read()</function> and <function>write()</function> function,
-respectively, when the <constant>V4L2_CAP_READWRITE</constant> flag in
-the <structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl is set.</para>
-
- <para>Drivers may need the CPU to copy the data, but they may also
-support DMA to or from user memory, so this I/O method is not
-necessarily less efficient than other methods merely exchanging buffer
-pointers. It is considered inferior though because no meta-information
-like frame counters or timestamps are passed. This information is
-necessary to recognize frame dropping and to synchronize with other
-data streams. However this is also the simplest I/O method, requiring
-little or no setup to exchange data. It permits command line stunts
-like this (the <application>vidctrl</application> tool is
-fictitious):</para>
-
- <informalexample>
- <screen>
-&gt; vidctrl /dev/video --input=0 --format=YUYV --size=352x288
-&gt; dd if=/dev/video of=myimage.422 bs=202752 count=1
-</screen>
- </informalexample>
-
- <para>To read from the device applications use the
-&func-read; function, to write the &func-write; function.
-Drivers must implement one I/O method if they
-exchange data with applications, but it need not be this.<footnote>
- <para>It would be desirable if applications could depend on
-drivers supporting all I/O interfaces, but as much as the complex
-memory mapping I/O can be inadequate for some devices we have no
-reason to require this interface, which is most useful for simple
-applications capturing still images.</para>
- </footnote> When reading or writing is supported, the driver
-must also support the &func-select; and &func-poll;
-function.<footnote>
- <para>At the driver level <function>select()</function> and
-<function>poll()</function> are the same, and
-<function>select()</function> is too important to be optional.</para>
- </footnote></para>
- </section>
-
- <section id="mmap">
- <title>Streaming I/O (Memory Mapping)</title>
-
- <para>Input and output devices support this I/O method when the
-<constant>V4L2_CAP_STREAMING</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl is set. There are two
-streaming methods, to determine if the memory mapping flavor is
-supported applications must call the &VIDIOC-REQBUFS; ioctl with the memory type set to <constant>V4L2_MEMORY_MMAP</constant>.</para>
-
- <para>Streaming is an I/O method where only pointers to buffers
-are exchanged between application and driver, the data itself is not
-copied. Memory mapping is primarily intended to map buffers in device
-memory into the application's address space. Device memory can be for
-example the video memory on a graphics card with a video capture
-add-on. However, being the most efficient I/O method available for a
-long time, many other drivers support streaming as well, allocating
-buffers in DMA-able main memory.</para>
-
- <para>A driver can support many sets of buffers. Each set is
-identified by a unique buffer type value. The sets are independent and
-each set can hold a different type of data. To access different sets
-at the same time different file descriptors must be used.<footnote>
- <para>One could use one file descriptor and set the buffer
-type field accordingly when calling &VIDIOC-QBUF; etc., but it makes
-the <function>select()</function> function ambiguous. We also like the
-clean approach of one file descriptor per logical stream. Video
-overlay for example is also a logical stream, although the CPU is not
-needed for continuous operation.</para>
- </footnote></para>
-
- <para>To allocate device buffers applications call the
-&VIDIOC-REQBUFS; ioctl with the desired number of buffers and buffer
-type, for example <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>.
-This ioctl can also be used to change the number of buffers or to free
-the allocated memory, provided none of the buffers are still
-mapped.</para>
-
- <para>Before applications can access the buffers they must map
-them into their address space with the &func-mmap; function. The
-location of the buffers in device memory can be determined with the
-&VIDIOC-QUERYBUF; ioctl. In the single-planar API case, the
-<structfield>m.offset</structfield> and <structfield>length</structfield>
-returned in a &v4l2-buffer; are passed as sixth and second parameter to the
-<function>mmap()</function> function. When using the multi-planar API,
-&v4l2-buffer; contains an array of &v4l2-plane; structures, each
-containing its own <structfield>m.offset</structfield> and
-<structfield>length</structfield>. When using the multi-planar API, every
-plane of every buffer has to be mapped separately, so the number of
-calls to &func-mmap; should be equal to number of buffers times number of
-planes in each buffer. The offset and length values must not be modified.
-Remember, the buffers are allocated in physical memory, as opposed to virtual
-memory, which can be swapped out to disk. Applications should free the buffers
-as soon as possible with the &func-munmap; function.</para>
-
- <example>
- <title>Mapping buffers in the single-planar API</title>
- <programlisting>
-&v4l2-requestbuffers; reqbuf;
-struct {
- void *start;
- size_t length;
-} *buffers;
-unsigned int i;
-
-memset(&amp;reqbuf, 0, sizeof(reqbuf));
-reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-reqbuf.memory = V4L2_MEMORY_MMAP;
-reqbuf.count = 20;
-
-if (-1 == ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf)) {
- if (errno == EINVAL)
- printf("Video capturing or mmap-streaming is not supported\n");
- else
- perror("VIDIOC_REQBUFS");
-
- exit(EXIT_FAILURE);
-}
-
-/* We want at least five buffers. */
-
-if (reqbuf.count &lt; 5) {
- /* You may need to free the buffers here. */
- printf("Not enough buffer memory\n");
- exit(EXIT_FAILURE);
-}
-
-buffers = calloc(reqbuf.count, sizeof(*buffers));
-assert(buffers != NULL);
-
-for (i = 0; i &lt; reqbuf.count; i++) {
- &v4l2-buffer; buffer;
-
- memset(&amp;buffer, 0, sizeof(buffer));
- buffer.type = reqbuf.type;
- buffer.memory = V4L2_MEMORY_MMAP;
- buffer.index = i;
-
- if (-1 == ioctl (fd, &VIDIOC-QUERYBUF;, &amp;buffer)) {
- perror("VIDIOC_QUERYBUF");
- exit(EXIT_FAILURE);
- }
-
- buffers[i].length = buffer.length; /* remember for munmap() */
-
- buffers[i].start = mmap(NULL, buffer.length,
- PROT_READ | PROT_WRITE, /* recommended */
- MAP_SHARED, /* recommended */
- fd, buffer.m.offset);
-
- if (MAP_FAILED == buffers[i].start) {
- /* If you do not exit here you should unmap() and free()
- the buffers mapped so far. */
- perror("mmap");
- exit(EXIT_FAILURE);
- }
-}
-
-/* Cleanup. */
-
-for (i = 0; i &lt; reqbuf.count; i++)
- munmap(buffers[i].start, buffers[i].length);
- </programlisting>
- </example>
-
- <example>
- <title>Mapping buffers in the multi-planar API</title>
- <programlisting>
-&v4l2-requestbuffers; reqbuf;
-/* Our current format uses 3 planes per buffer */
-#define FMT_NUM_PLANES = 3
-
-struct {
- void *start[FMT_NUM_PLANES];
- size_t length[FMT_NUM_PLANES];
-} *buffers;
-unsigned int i, j;
-
-memset(&amp;reqbuf, 0, sizeof(reqbuf));
-reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-reqbuf.memory = V4L2_MEMORY_MMAP;
-reqbuf.count = 20;
-
-if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;reqbuf) &lt; 0) {
- if (errno == EINVAL)
- printf("Video capturing or mmap-streaming is not supported\n");
- else
- perror("VIDIOC_REQBUFS");
-
- exit(EXIT_FAILURE);
-}
-
-/* We want at least five buffers. */
-
-if (reqbuf.count &lt; 5) {
- /* You may need to free the buffers here. */
- printf("Not enough buffer memory\n");
- exit(EXIT_FAILURE);
-}
-
-buffers = calloc(reqbuf.count, sizeof(*buffers));
-assert(buffers != NULL);
-
-for (i = 0; i &lt; reqbuf.count; i++) {
- &v4l2-buffer; buffer;
- &v4l2-plane; planes[FMT_NUM_PLANES];
-
- memset(&amp;buffer, 0, sizeof(buffer));
- buffer.type = reqbuf.type;
- buffer.memory = V4L2_MEMORY_MMAP;
- buffer.index = i;
- /* length in struct v4l2_buffer in multi-planar API stores the size
- * of planes array. */
- buffer.length = FMT_NUM_PLANES;
- buffer.m.planes = planes;
-
- if (ioctl(fd, &VIDIOC-QUERYBUF;, &amp;buffer) &lt; 0) {
- perror("VIDIOC_QUERYBUF");
- exit(EXIT_FAILURE);
- }
-
- /* Every plane has to be mapped separately */
- for (j = 0; j &lt; FMT_NUM_PLANES; j++) {
- buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
-
- buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
- PROT_READ | PROT_WRITE, /* recommended */
- MAP_SHARED, /* recommended */
- fd, buffer.m.planes[j].m.offset);
-
- if (MAP_FAILED == buffers[i].start[j]) {
- /* If you do not exit here you should unmap() and free()
- the buffers and planes mapped so far. */
- perror("mmap");
- exit(EXIT_FAILURE);
- }
- }
-}
-
-/* Cleanup. */
-
-for (i = 0; i &lt; reqbuf.count; i++)
- for (j = 0; j &lt; FMT_NUM_PLANES; j++)
- munmap(buffers[i].start[j], buffers[i].length[j]);
- </programlisting>
- </example>
-
- <para>Conceptually streaming drivers maintain two buffer queues, an incoming
-and an outgoing queue. They separate the synchronous capture or output
-operation locked to a video clock from the application which is
-subject to random disk or network delays and preemption by
-other processes, thereby reducing the probability of data loss.
-The queues are organized as FIFOs, buffers will be
-output in the order enqueued in the incoming FIFO, and were
-captured in the order dequeued from the outgoing FIFO.</para>
-
- <para>The driver may require a minimum number of buffers enqueued
-at all times to function, apart of this no limit exists on the number
-of buffers applications can enqueue in advance, or dequeue and
-process. They can also enqueue in a different order than buffers have
-been dequeued, and the driver can <emphasis>fill</emphasis> enqueued
-<emphasis>empty</emphasis> buffers in any order. <footnote>
- <para>Random enqueue order permits applications processing
-images out of order (such as video codecs) to return buffers earlier,
-reducing the probability of data loss. Random fill order allows
-drivers to reuse buffers on a LIFO-basis, taking advantage of caches
-holding scatter-gather lists and the like.</para>
- </footnote> The index number of a buffer (&v4l2-buffer;
-<structfield>index</structfield>) plays no role here, it only
-identifies the buffer.</para>
-
- <para>Initially all mapped buffers are in dequeued state,
-inaccessible by the driver. For capturing applications it is customary
-to first enqueue all mapped buffers, then to start capturing and enter
-the read loop. Here the application waits until a filled buffer can be
-dequeued, and re-enqueues the buffer when the data is no longer
-needed. Output applications fill and enqueue buffers, when enough
-buffers are stacked up the output is started with
-<constant>VIDIOC_STREAMON</constant>. In the write loop, when
-the application runs out of free buffers, it must wait until an empty
-buffer can be dequeued and reused.</para>
-
- <para>To enqueue and dequeue a buffer applications use the
-&VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl. The status of a buffer being
-mapped, enqueued, full or empty can be determined at any time using the
-&VIDIOC-QUERYBUF; ioctl. Two methods exist to suspend execution of the
-application until one or more buffers can be dequeued. By default
-<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
-outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
-given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
-returns immediately with an &EAGAIN; when no buffer is available. The
-&func-select; or &func-poll; functions are always available.</para>
-
- <para>To start and stop capturing or output applications call the
-&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
-<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both
-queues as a side effect. Since there is no notion of doing anything
-"now" on a multitasking system, if an application needs to synchronize
-with another event it should examine the &v4l2-buffer;
-<structfield>timestamp</structfield> of captured or outputted buffers.
-</para>
-
- <para>Drivers implementing memory mapping I/O must
-support the <constant>VIDIOC_REQBUFS</constant>,
-<constant>VIDIOC_QUERYBUF</constant>,
-<constant>VIDIOC_QBUF</constant>, <constant>VIDIOC_DQBUF</constant>,
-<constant>VIDIOC_STREAMON</constant> and
-<constant>VIDIOC_STREAMOFF</constant> ioctl, the
-<function>mmap()</function>, <function>munmap()</function>,
-<function>select()</function> and <function>poll()</function>
-function.<footnote>
- <para>At the driver level <function>select()</function> and
-<function>poll()</function> are the same, and
-<function>select()</function> is too important to be optional. The
-rest should be evident.</para>
- </footnote></para>
-
- <para>[capture example]</para>
-
- </section>
-
- <section id="userp">
- <title>Streaming I/O (User Pointers)</title>
-
- <para>Input and output devices support this I/O method when the
-<constant>V4L2_CAP_STREAMING</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl is set. If the particular user
-pointer method (not only memory mapping) is supported must be
-determined by calling the &VIDIOC-REQBUFS; ioctl with the memory type set to <constant>V4L2_MEMORY_USERPTR</constant>.</para>
-
- <para>This I/O method combines advantages of the read/write and
-memory mapping methods. Buffers (planes) are allocated by the application
-itself, and can reside for example in virtual or shared memory. Only
-pointers to data are exchanged, these pointers and meta-information
-are passed in &v4l2-buffer; (or in &v4l2-plane; in the multi-planar API case).
-The driver must be switched into user pointer I/O mode by calling the
-&VIDIOC-REQBUFS; with the desired buffer type. No buffers (planes) are allocated
-beforehand, consequently they are not indexed and cannot be queried like mapped
-buffers with the <constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
-
- <example>
- <title>Initiating streaming I/O with user pointers</title>
-
- <programlisting>
-&v4l2-requestbuffers; reqbuf;
-
-memset (&amp;reqbuf, 0, sizeof (reqbuf));
-reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-reqbuf.memory = V4L2_MEMORY_USERPTR;
-
-if (ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
- if (errno == EINVAL)
- printf ("Video capturing or user pointer streaming is not supported\n");
- else
- perror ("VIDIOC_REQBUFS");
-
- exit (EXIT_FAILURE);
-}
- </programlisting>
- </example>
-
- <para>Buffer (plane) addresses and sizes are passed on the fly with the
-&VIDIOC-QBUF; ioctl. Although buffers are commonly cycled,
-applications can pass different addresses and sizes at each
-<constant>VIDIOC_QBUF</constant> call. If required by the hardware the
-driver swaps memory pages within physical memory to create a
-continuous area of memory. This happens transparently to the
-application in the virtual memory subsystem of the kernel. When buffer
-pages have been swapped out to disk they are brought back and finally
-locked in physical memory for DMA.<footnote>
- <para>We expect that frequently used buffers are typically not
-swapped out. Anyway, the process of swapping, locking or generating
-scatter-gather lists may be time consuming. The delay can be masked by
-the depth of the incoming buffer queue, and perhaps by maintaining
-caches assuming a buffer will be soon enqueued again. On the other
-hand, to optimize memory usage drivers can limit the number of buffers
-locked in advance and recycle the most recently used buffers first. Of
-course, the pages of empty buffers in the incoming queue need not be
-saved to disk. Output buffers must be saved on the incoming and
-outgoing queue because an application may share them with other
-processes.</para>
- </footnote></para>
-
- <para>Filled or displayed buffers are dequeued with the
-&VIDIOC-DQBUF; ioctl. The driver can unlock the memory pages at any
-time between the completion of the DMA and this ioctl. The memory is
-also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
-when the device is closed. Applications must take care not to free
-buffers without dequeuing. For once, the buffers remain locked until
-further, wasting physical memory. Second the driver will not be
-notified when the memory is returned to the application's free list
-and subsequently reused for other purposes, possibly completing the
-requested DMA and overwriting valuable data.</para>
-
- <para>For capturing applications it is customary to enqueue a
-number of empty buffers, to start capturing and enter the read loop.
-Here the application waits until a filled buffer can be dequeued, and
-re-enqueues the buffer when the data is no longer needed. Output
-applications fill and enqueue buffers, when enough buffers are stacked
-up output is started. In the write loop, when the application
-runs out of free buffers it must wait until an empty buffer can be
-dequeued and reused. Two methods exist to suspend execution of the
-application until one or more buffers can be dequeued. By default
-<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
-outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
-given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
-returns immediately with an &EAGAIN; when no buffer is available. The
-&func-select; or &func-poll; function are always available.</para>
-
- <para>To start and stop capturing or output applications call the
-&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctl. Note
-<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both
-queues and unlocks all buffers as a side effect. Since there is no
-notion of doing anything "now" on a multitasking system, if an
-application needs to synchronize with another event it should examine
-the &v4l2-buffer; <structfield>timestamp</structfield> of captured
-or outputted buffers.</para>
-
- <para>Drivers implementing user pointer I/O must
-support the <constant>VIDIOC_REQBUFS</constant>,
-<constant>VIDIOC_QBUF</constant>, <constant>VIDIOC_DQBUF</constant>,
-<constant>VIDIOC_STREAMON</constant> and
-<constant>VIDIOC_STREAMOFF</constant> ioctl, the
-<function>select()</function> and <function>poll()</function> function.<footnote>
- <para>At the driver level <function>select()</function> and
-<function>poll()</function> are the same, and
-<function>select()</function> is too important to be optional. The
-rest should be evident.</para>
- </footnote></para>
- </section>
-
- <section id="dmabuf">
- <title>Streaming I/O (DMA buffer importing)</title>
-
-<para>The DMABUF framework provides a generic method for sharing buffers
-between multiple devices. Device drivers that support DMABUF can export a DMA
-buffer to userspace as a file descriptor (known as the exporter role), import a
-DMA buffer from userspace using a file descriptor previously exported for a
-different or the same device (known as the importer role), or both. This
-section describes the DMABUF importer role API in V4L2.</para>
-
- <para>Refer to <link linkend="vidioc-expbuf">DMABUF exporting</link> for
-details about exporting V4L2 buffers as DMABUF file descriptors.</para>
-
-<para>Input and output devices support the streaming I/O method when the
-<constant>V4L2_CAP_STREAMING</constant> flag in the
-<structfield>capabilities</structfield> field of &v4l2-capability; returned by
-the &VIDIOC-QUERYCAP; ioctl is set. Whether importing DMA buffers through
-DMABUF file descriptors is supported is determined by calling the
-&VIDIOC-REQBUFS; ioctl with the memory type set to
-<constant>V4L2_MEMORY_DMABUF</constant>.</para>
-
- <para>This I/O method is dedicated to sharing DMA buffers between different
-devices, which may be V4L devices or other video-related devices (e.g. DRM).
-Buffers (planes) are allocated by a driver on behalf of an application. Next,
-these buffers are exported to the application as file descriptors using an API
-which is specific for an allocator driver. Only such file descriptor are
-exchanged. The descriptors and meta-information are passed in &v4l2-buffer; (or
-in &v4l2-plane; in the multi-planar API case). The driver must be switched
-into DMABUF I/O mode by calling the &VIDIOC-REQBUFS; with the desired buffer
-type.</para>
-
- <example>
- <title>Initiating streaming I/O with DMABUF file descriptors</title>
-
- <programlisting>
-&v4l2-requestbuffers; reqbuf;
-
-memset(&amp;reqbuf, 0, sizeof (reqbuf));
-reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-reqbuf.memory = V4L2_MEMORY_DMABUF;
-reqbuf.count = 1;
-
-if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;reqbuf) == -1) {
- if (errno == EINVAL)
- printf("Video capturing or DMABUF streaming is not supported\n");
- else
- perror("VIDIOC_REQBUFS");
-
- exit(EXIT_FAILURE);
-}
- </programlisting>
- </example>
-
- <para>The buffer (plane) file descriptor is passed on the fly with the
-&VIDIOC-QBUF; ioctl. In case of multiplanar buffers, every plane can be
-associated with a different DMABUF descriptor. Although buffers are commonly
-cycled, applications can pass a different DMABUF descriptor at each
-<constant>VIDIOC_QBUF</constant> call.</para>
-
- <example>
- <title>Queueing DMABUF using single plane API</title>
-
- <programlisting>
-int buffer_queue(int v4lfd, int index, int dmafd)
-{
- &v4l2-buffer; buf;
-
- memset(&amp;buf, 0, sizeof buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_DMABUF;
- buf.index = index;
- buf.m.fd = dmafd;
-
- if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
- perror("VIDIOC_QBUF");
- return -1;
- }
-
- return 0;
-}
- </programlisting>
- </example>
-
- <example>
- <title>Queueing DMABUF using multi plane API</title>
-
- <programlisting>
-int buffer_queue_mp(int v4lfd, int index, int dmafd[], int n_planes)
-{
- &v4l2-buffer; buf;
- &v4l2-plane; planes[VIDEO_MAX_PLANES];
- int i;
-
- memset(&amp;buf, 0, sizeof buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- buf.memory = V4L2_MEMORY_DMABUF;
- buf.index = index;
- buf.m.planes = planes;
- buf.length = n_planes;
-
- memset(&amp;planes, 0, sizeof planes);
-
- for (i = 0; i &lt; n_planes; ++i)
- buf.m.planes[i].m.fd = dmafd[i];
-
- if (ioctl(v4lfd, &VIDIOC-QBUF;, &amp;buf) == -1) {
- perror("VIDIOC_QBUF");
- return -1;
- }
-
- return 0;
-}
- </programlisting>
- </example>
-
- <para>Captured or displayed buffers are dequeued with the
-&VIDIOC-DQBUF; ioctl. The driver can unlock the buffer at any
-time between the completion of the DMA and this ioctl. The memory is
-also unlocked when &VIDIOC-STREAMOFF; is called, &VIDIOC-REQBUFS;, or
-when the device is closed.</para>
-
- <para>For capturing applications it is customary to enqueue a
-number of empty buffers, to start capturing and enter the read loop.
-Here the application waits until a filled buffer can be dequeued, and
-re-enqueues the buffer when the data is no longer needed. Output
-applications fill and enqueue buffers, when enough buffers are stacked
-up output is started. In the write loop, when the application
-runs out of free buffers it must wait until an empty buffer can be
-dequeued and reused. Two methods exist to suspend execution of the
-application until one or more buffers can be dequeued. By default
-<constant>VIDIOC_DQBUF</constant> blocks when no buffer is in the
-outgoing queue. When the <constant>O_NONBLOCK</constant> flag was
-given to the &func-open; function, <constant>VIDIOC_DQBUF</constant>
-returns immediately with an &EAGAIN; when no buffer is available. The
-&func-select; and &func-poll; functions are always available.</para>
-
- <para>To start and stop capturing or displaying applications call the
-&VIDIOC-STREAMON; and &VIDIOC-STREAMOFF; ioctls. Note that
-<constant>VIDIOC_STREAMOFF</constant> removes all buffers from both queues and
-unlocks all buffers as a side effect. Since there is no notion of doing
-anything "now" on a multitasking system, if an application needs to synchronize
-with another event it should examine the &v4l2-buffer;
-<structfield>timestamp</structfield> of captured or outputted buffers.</para>
-
- <para>Drivers implementing DMABUF importing I/O must support the
-<constant>VIDIOC_REQBUFS</constant>, <constant>VIDIOC_QBUF</constant>,
-<constant>VIDIOC_DQBUF</constant>, <constant>VIDIOC_STREAMON</constant> and
-<constant>VIDIOC_STREAMOFF</constant> ioctls, and the
-<function>select()</function> and <function>poll()</function> functions.</para>
-
- </section>
-
- <section id="async">
- <title>Asynchronous I/O</title>
-
- <para>This method is not defined yet.</para>
- </section>
-
- <section id="buffer">
- <title>Buffers</title>
-
- <para>A buffer contains data exchanged by application and
-driver using one of the Streaming I/O methods. In the multi-planar API, the
-data is held in planes, while the buffer structure acts as a container
-for the planes. Only pointers to buffers (planes) are exchanged, the data
-itself is not copied. These pointers, together with meta-information like
-timestamps or field parity, are stored in a struct
-<structname>v4l2_buffer</structname>, argument to
-the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl.
-In the multi-planar API, some plane-specific members of struct
-<structname>v4l2_buffer</structname>, such as pointers and sizes for each
-plane, are stored in struct <structname>v4l2_plane</structname> instead.
-In that case, struct <structname>v4l2_buffer</structname> contains an array of
-plane structures.</para>
-
- <para>Dequeued video buffers come with timestamps. The driver
- decides at which part of the frame and with which clock the
- timestamp is taken. Please see flags in the masks
- <constant>V4L2_BUF_FLAG_TIMESTAMP_MASK</constant> and
- <constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant> in <xref
- linkend="buffer-flags" />. These flags are always valid and constant
- across all buffers during the whole video stream. Changes in these
- flags may take place as a side effect of &VIDIOC-S-INPUT; or
- &VIDIOC-S-OUTPUT; however. The
- <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant> timestamp type
- which is used by e.g. on mem-to-mem devices is an exception to the
- rule: the timestamp source flags are copied from the OUTPUT video
- buffer to the CAPTURE video buffer.</para>
-
- <table frame="none" pgwide="1" id="v4l2-buffer">
- <title>struct <structname>v4l2_buffer</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry></entry>
- <entry>Number of the buffer, set by the application except
-when calling &VIDIOC-DQBUF;, then it is set by the driver.
-This field can range from zero to the number of buffers allocated
-with the &VIDIOC-REQBUFS; ioctl (&v4l2-requestbuffers; <structfield>count</structfield>),
-plus any buffers allocated with &VIDIOC-CREATE-BUFS; minus one.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>Type of the buffer, same as &v4l2-format;
-<structfield>type</structfield> or &v4l2-requestbuffers;
-<structfield>type</structfield>, set by the application. See <xref
-linkend="v4l2-buf-type" /></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>bytesused</structfield></entry>
- <entry></entry>
- <entry>The number of bytes occupied by the data in the
-buffer. It depends on the negotiated data format and may change with
-each buffer for compressed variable size data like JPEG images.
-Drivers must set this field when <structfield>type</structfield>
-refers to a capture stream, applications when it refers to an output stream.
-If the application sets this to 0 for an output stream, then
-<structfield>bytesused</structfield> will be set to the size of the
-buffer (see the <structfield>length</structfield> field of this struct) by
-the driver. For multiplanar formats this field is ignored and the
-<structfield>planes</structfield> pointer is used instead.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry>Flags set by the application or driver, see <xref
-linkend="buffer-flags" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>field</structfield></entry>
- <entry></entry>
- <entry>Indicates the field order of the image in the
-buffer, see <xref linkend="v4l2-field" />. This field is not used when
-the buffer contains VBI data. Drivers must set it when
-<structfield>type</structfield> refers to a capture stream,
-applications when it refers to an output stream.</entry>
- </row>
- <row>
- <entry>struct timeval</entry>
- <entry><structfield>timestamp</structfield></entry>
- <entry></entry>
- <entry><para>For capture streams this is time when the first data
- byte was captured, as returned by the
- <function>clock_gettime()</function> function for the relevant
- clock id; see <constant>V4L2_BUF_FLAG_TIMESTAMP_*</constant> in
- <xref linkend="buffer-flags" />. For output streams the driver
- stores the time at which the last data byte was actually sent out
- in the <structfield>timestamp</structfield> field. This permits
- applications to monitor the drift between the video and system
- clock. For output streams that use <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant>
- the application has to fill in the timestamp which will be copied
- by the driver to the capture stream.</para></entry>
- </row>
- <row>
- <entry>&v4l2-timecode;</entry>
- <entry><structfield>timecode</structfield></entry>
- <entry></entry>
- <entry>When <structfield>type</structfield> is
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> and the
-<constant>V4L2_BUF_FLAG_TIMECODE</constant> flag is set in
-<structfield>flags</structfield>, this structure contains a frame
-timecode. In <link linkend="v4l2-field">V4L2_FIELD_ALTERNATE</link>
-mode the top and bottom field contain the same timecode.
-Timecodes are intended to help video editing and are typically recorded on
-video tapes, but also embedded in compressed formats like MPEG. This
-field is independent of the <structfield>timestamp</structfield> and
-<structfield>sequence</structfield> fields.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sequence</structfield></entry>
- <entry></entry>
- <entry>Set by the driver, counting the frames (not fields!) in
-sequence. This field is set for both input and output devices.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>In <link
-linkend="v4l2-field">V4L2_FIELD_ALTERNATE</link> mode the top and
-bottom field have the same sequence number. The count starts at zero
-and includes dropped or repeated frames. A dropped frame was received
-by an input device but could not be stored due to lack of free buffer
-space. A repeated frame was displayed again by an output device
-because the application did not pass new data in
-time.</para><para>Note this may count the frames received
-e.g. over USB, without taking into account the frames dropped by the
-remote hardware due to limited compression throughput or bus
-bandwidth. These devices identify by not enumerating any video
-standards, see <xref linkend="standard" />.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>memory</structfield></entry>
- <entry></entry>
- <entry>This field must be set by applications and/or drivers
-in accordance with the selected I/O method. See <xref linkend="v4l2-memory"
- /></entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield>m</structfield></entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>offset</structfield></entry>
- <entry>For the single-planar API and when
-<structfield>memory</structfield> is <constant>V4L2_MEMORY_MMAP</constant> this
-is the offset of the buffer from the start of the device memory. The value is
-returned by the driver and apart of serving as parameter to the &func-mmap;
-function not useful for applications. See <xref linkend="mmap" /> for details
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>unsigned long</entry>
- <entry><structfield>userptr</structfield></entry>
- <entry>For the single-planar API and when
-<structfield>memory</structfield> is <constant>V4L2_MEMORY_USERPTR</constant>
-this is a pointer to the buffer (casted to unsigned long type) in virtual
-memory, set by the application. See <xref linkend="userp" /> for details.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct v4l2_plane</entry>
- <entry><structfield>*planes</structfield></entry>
- <entry>When using the multi-planar API, contains a userspace pointer
- to an array of &v4l2-plane;. The size of the array should be put
- in the <structfield>length</structfield> field of this
- <structname>v4l2_buffer</structname> structure.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>int</entry>
- <entry><structfield>fd</structfield></entry>
- <entry>For the single-plane API and when
-<structfield>memory</structfield> is <constant>V4L2_MEMORY_DMABUF</constant> this
-is the file descriptor associated with a DMABUF buffer.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>length</structfield></entry>
- <entry></entry>
- <entry>Size of the buffer (not the payload) in bytes for the
- single-planar API. This is set by the driver based on the calls to
- &VIDIOC-REQBUFS; and/or &VIDIOC-CREATE-BUFS;. For the multi-planar API the application sets
- this to the number of elements in the <structfield>planes</structfield>
- array. The driver will fill in the actual number of valid elements in
- that array.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved2</structfield></entry>
- <entry></entry>
- <entry>A place holder for future extensions. Drivers and applications
-must set this to 0.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield></entry>
- <entry></entry>
- <entry>A place holder for future extensions. Drivers and applications
-must set this to 0.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-plane">
- <title>struct <structname>v4l2_plane</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>bytesused</structfield></entry>
- <entry></entry>
- <entry>The number of bytes occupied by data in the plane
- (its payload). Drivers must set this field when <structfield>type</structfield>
- refers to a capture stream, applications when it refers to an output stream.
- If the application sets this to 0 for an output stream, then
- <structfield>bytesused</structfield> will be set to the size of the
- plane (see the <structfield>length</structfield> field of this struct)
- by the driver. Note that the actual image data starts at
- <structfield>data_offset</structfield> which may not be 0.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>length</structfield></entry>
- <entry></entry>
- <entry>Size in bytes of the plane (not its payload). This is set by the driver
- based on the calls to &VIDIOC-REQBUFS; and/or &VIDIOC-CREATE-BUFS;.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield>m</structfield></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>mem_offset</structfield></entry>
- <entry>When the memory type in the containing &v4l2-buffer; is
- <constant>V4L2_MEMORY_MMAP</constant>, this is the value that
- should be passed to &func-mmap;, similar to the
- <structfield>offset</structfield> field in &v4l2-buffer;.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>unsigned long</entry>
- <entry><structfield>userptr</structfield></entry>
- <entry>When the memory type in the containing &v4l2-buffer; is
- <constant>V4L2_MEMORY_USERPTR</constant>, this is a userspace
- pointer to the memory allocated for this plane by an application.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>int</entry>
- <entry><structfield>fd</structfield></entry>
- <entry>When the memory type in the containing &v4l2-buffer; is
- <constant>V4L2_MEMORY_DMABUF</constant>, this is a file
- descriptor associated with a DMABUF buffer, similar to the
- <structfield>fd</structfield> field in &v4l2-buffer;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>data_offset</structfield></entry>
- <entry></entry>
- <entry>Offset in bytes to video data in the plane.
- Drivers must set this field when <structfield>type</structfield>
- refers to a capture stream, applications when it refers to an output stream.
- Note that data_offset is included in <structfield>bytesused</structfield>.
- So the size of the image in the plane is
- <structfield>bytesused</structfield>-<structfield>data_offset</structfield> at
- offset <structfield>data_offset</structfield> from the start of the plane.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[11]</structfield></entry>
- <entry></entry>
- <entry>Reserved for future use. Should be zeroed by drivers and
- applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-buf-type">
- <title>enum v4l2_buf_type</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant></entry>
- <entry>1</entry>
- <entry>Buffer of a single-planar video capture stream, see <xref
- linkend="capture" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
- </entry>
- <entry>9</entry>
- <entry>Buffer of a multi-planar video capture stream, see <xref
- linkend="capture" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant></entry>
- <entry>2</entry>
- <entry>Buffer of a single-planar video output stream, see <xref
- linkend="output" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>
- </entry>
- <entry>10</entry>
- <entry>Buffer of a multi-planar video output stream, see <xref
- linkend="output" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant></entry>
- <entry>3</entry>
- <entry>Buffer for video overlay, see <xref linkend="overlay" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VBI_CAPTURE</constant></entry>
- <entry>4</entry>
- <entry>Buffer of a raw VBI capture stream, see <xref
- linkend="raw-vbi" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant></entry>
- <entry>5</entry>
- <entry>Buffer of a raw VBI output stream, see <xref
- linkend="raw-vbi" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_SLICED_VBI_CAPTURE</constant></entry>
- <entry>6</entry>
- <entry>Buffer of a sliced VBI capture stream, see <xref
- linkend="sliced" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_SLICED_VBI_OUTPUT</constant></entry>
- <entry>7</entry>
- <entry>Buffer of a sliced VBI output stream, see <xref
- linkend="sliced" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant></entry>
- <entry>8</entry>
- <entry>Buffer for video output overlay (OSD), see <xref
- linkend="osd" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant></entry>
- <entry>11</entry>
- <entry>Buffer for Software Defined Radio (SDR) capture stream, see
- <xref linkend="sdr" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_TYPE_SDR_OUTPUT</constant></entry>
- <entry>12</entry>
- <entry>Buffer for Software Defined Radio (SDR) output stream, see
- <xref linkend="sdr" />.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="buffer-flags">
- <title>Buffer Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_BUF_FLAG_MAPPED</constant></entry>
- <entry>0x00000001</entry>
- <entry>The buffer resides in device memory and has been mapped
-into the application's address space, see <xref linkend="mmap" /> for details.
-Drivers set or clear this flag when the
-<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
- linkend="vidioc-qbuf">VIDIOC_QBUF</link> or <link
- linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called. Set by the driver.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_QUEUED</constant></entry>
- <entry>0x00000002</entry>
- <entry>Internally drivers maintain two buffer queues, an
-incoming and outgoing queue. When this flag is set, the buffer is
-currently on the incoming queue. It automatically moves to the
-outgoing queue after the buffer has been filled (capture devices) or
-displayed (output devices). Drivers set or clear this flag when the
-<constant>VIDIOC_QUERYBUF</constant> ioctl is called. After
-(successful) calling the <constant>VIDIOC_QBUF </constant>ioctl it is
-always set and after <constant>VIDIOC_DQBUF</constant> always
-cleared.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_DONE</constant></entry>
- <entry>0x00000004</entry>
- <entry>When this flag is set, the buffer is currently on
-the outgoing queue, ready to be dequeued from the driver. Drivers set
-or clear this flag when the <constant>VIDIOC_QUERYBUF</constant> ioctl
-is called. After calling the <constant>VIDIOC_QBUF</constant> or
-<constant>VIDIOC_DQBUF</constant> it is always cleared. Of course a
-buffer cannot be on both queues at the same time, the
-<constant>V4L2_BUF_FLAG_QUEUED</constant> and
-<constant>V4L2_BUF_FLAG_DONE</constant> flag are mutually exclusive.
-They can be both cleared however, then the buffer is in "dequeued"
-state, in the application domain so to say.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_ERROR</constant></entry>
- <entry>0x00000040</entry>
- <entry>When this flag is set, the buffer has been dequeued
- successfully, although the data might have been corrupted.
- This is recoverable, streaming may continue as normal and
- the buffer may be reused normally.
- Drivers set this flag when the <constant>VIDIOC_DQBUF</constant>
- ioctl is called.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry>
- <entry>0x00000008</entry>
- <entry>Drivers set or clear this flag when calling the
-<constant>VIDIOC_DQBUF</constant> ioctl. It may be set by video
-capture devices when the buffer contains a compressed image which is a
-key frame (or field), &ie; can be decompressed on its own. Also known as
-an I-frame. Applications can set this bit when <structfield>type</structfield>
-refers to an output stream.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_PFRAME</constant></entry>
- <entry>0x00000010</entry>
- <entry>Similar to <constant>V4L2_BUF_FLAG_KEYFRAME</constant>
-this flags predicted frames or fields which contain only differences to a
-previous key frame. Applications can set this bit when <structfield>type</structfield>
-refers to an output stream.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_BFRAME</constant></entry>
- <entry>0x00000020</entry>
- <entry>Similar to <constant>V4L2_BUF_FLAG_KEYFRAME</constant>
-this flags a bi-directional predicted frame or field which contains only
-the differences between the current frame and both the preceding and following
-key frames to specify its content. Applications can set this bit when
-<structfield>type</structfield> refers to an output stream.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TIMECODE</constant></entry>
- <entry>0x00000100</entry>
- <entry>The <structfield>timecode</structfield> field is valid.
-Drivers set or clear this flag when the <constant>VIDIOC_DQBUF</constant>
-ioctl is called. Applications can set this bit and the corresponding
-<structfield>timecode</structfield> structure when <structfield>type</structfield>
-refers to an output stream.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_PREPARED</constant></entry>
- <entry>0x00000400</entry>
- <entry>The buffer has been prepared for I/O and can be queued by the
-application. Drivers set or clear this flag when the
-<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link>, <link
- linkend="vidioc-qbuf">VIDIOC_PREPARE_BUF</link>, <link
- linkend="vidioc-qbuf">VIDIOC_QBUF</link> or <link
- linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant></entry>
- <entry>0x00000800</entry>
- <entry>Caches do not have to be invalidated for this buffer.
-Typically applications shall use this flag if the data captured in the buffer
-is not going to be touched by the CPU, instead the buffer will, probably, be
-passed on to a DMA-capable hardware unit for further processing or output.
-</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant></entry>
- <entry>0x00001000</entry>
- <entry>Caches do not have to be cleaned for this buffer.
-Typically applications shall use this flag for output buffers if the data
-in this buffer has not been created by the CPU but by some DMA-capable unit,
-in which case caches have not been used.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_LAST</constant></entry>
- <entry>0x00100000</entry>
- <entry>Last buffer produced by the hardware. mem2mem codec drivers
-set this flag on the capture queue for the last buffer when the
-<link linkend="vidioc-querybuf">VIDIOC_QUERYBUF</link> or
-<link linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl is called. Due to hardware
-limitations, the last buffer may be empty. In this case the driver will set the
-<structfield>bytesused</structfield> field to 0, regardless of the format. Any
-Any subsequent call to the <link linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl
-will not block anymore, but return an &EPIPE;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MASK</constant></entry>
- <entry>0x0000e000</entry>
- <entry>Mask for timestamp types below. To test the
- timestamp type, mask out bits not belonging to timestamp
- type by performing a logical and operation with buffer
- flags and timestamp mask.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN</constant></entry>
- <entry>0x00000000</entry>
- <entry>Unknown timestamp type. This type is used by
- drivers before Linux 3.9 and may be either monotonic (see
- below) or realtime (wall clock). Monotonic clock has been
- favoured in embedded systems whereas most of the drivers
- use the realtime clock. Either kinds of timestamps are
- available in user space via
- <function>clock_gettime(2)</function> using clock IDs
- <constant>CLOCK_MONOTONIC</constant> and
- <constant>CLOCK_REALTIME</constant>, respectively.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC</constant></entry>
- <entry>0x00002000</entry>
- <entry>The buffer timestamp has been taken from the
- <constant>CLOCK_MONOTONIC</constant> clock. To access the
- same clock outside V4L2, use
- <function>clock_gettime(2)</function>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant></entry>
- <entry>0x00004000</entry>
- <entry>The CAPTURE buffer timestamp has been taken from the
- corresponding OUTPUT buffer. This flag applies only to mem2mem devices.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant></entry>
- <entry>0x00070000</entry>
- <entry>Mask for timestamp sources below. The timestamp source
- defines the point of time the timestamp is taken in relation to
- the frame. Logical 'and' operation between the
- <structfield>flags</structfield> field and
- <constant>V4L2_BUF_FLAG_TSTAMP_SRC_MASK</constant> produces the
- value of the timestamp source. Applications must set the timestamp
- source when <structfield>type</structfield> refers to an output stream
- and <constant>V4L2_BUF_FLAG_TIMESTAMP_COPY</constant> is set.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_EOF</constant></entry>
- <entry>0x00000000</entry>
- <entry>End Of Frame. The buffer timestamp has been taken
- when the last pixel of the frame has been received or the
- last pixel of the frame has been transmitted. In practice,
- software generated timestamps will typically be read from
- the clock a small amount of time after the last pixel has
- been received or transmitten, depending on the system and
- other activity in it.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BUF_FLAG_TSTAMP_SRC_SOE</constant></entry>
- <entry>0x00010000</entry>
- <entry>Start Of Exposure. The buffer timestamp has been
- taken when the exposure of the frame has begun. This is
- only valid for the
- <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> buffer
- type.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-memory">
- <title>enum v4l2_memory</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MEMORY_MMAP</constant></entry>
- <entry>1</entry>
- <entry>The buffer is used for <link linkend="mmap">memory
-mapping</link> I/O.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MEMORY_USERPTR</constant></entry>
- <entry>2</entry>
- <entry>The buffer is used for <link linkend="userp">user
-pointer</link> I/O.</entry>
- </row>
- <row>
- <entry><constant>V4L2_MEMORY_OVERLAY</constant></entry>
- <entry>3</entry>
- <entry>[to do]</entry>
- </row>
- <row>
- <entry><constant>V4L2_MEMORY_DMABUF</constant></entry>
- <entry>4</entry>
- <entry>The buffer is used for <link linkend="dmabuf">DMA shared
-buffer</link> I/O.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section>
- <title>Timecodes</title>
-
- <para>The <structname>v4l2_timecode</structname> structure is
-designed to hold a <xref linkend="smpte12m" /> or similar timecode.
-(struct <structname>timeval</structname> timestamps are stored in
-&v4l2-buffer; field <structfield>timestamp</structfield>.)</para>
-
- <table frame="none" pgwide="1" id="v4l2-timecode">
- <title>struct <structname>v4l2_timecode</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Frame rate the timecodes are based on, see <xref
- linkend="timecode-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Timecode flags, see <xref linkend="timecode-flags" />.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>frames</structfield></entry>
- <entry>Frame count, 0 ... 23/24/29/49/59, depending on the
- type of timecode.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>seconds</structfield></entry>
- <entry>Seconds count, 0 ... 59. This is a binary, not BCD number.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>minutes</structfield></entry>
- <entry>Minutes count, 0 ... 59. This is a binary, not BCD number.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>hours</structfield></entry>
- <entry>Hours count, 0 ... 29. This is a binary, not BCD number.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>userbits</structfield>[4]</entry>
- <entry>The "user group" bits from the timecode.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="timecode-type">
- <title>Timecode Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TC_TYPE_24FPS</constant></entry>
- <entry>1</entry>
- <entry>24 frames per second, i.&nbsp;e. film.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_TYPE_25FPS</constant></entry>
- <entry>2</entry>
- <entry>25 frames per second, &ie; PAL or SECAM video.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_TYPE_30FPS</constant></entry>
- <entry>3</entry>
- <entry>30 frames per second, &ie; NTSC video.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_TYPE_50FPS</constant></entry>
- <entry>4</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_TYPE_60FPS</constant></entry>
- <entry>5</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="timecode-flags">
- <title>Timecode Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TC_FLAG_DROPFRAME</constant></entry>
- <entry>0x0001</entry>
- <entry>Indicates "drop frame" semantics for counting frames
-in 29.97 fps material. When set, frame numbers 0 and 1 at the start of
-each minute, except minutes 0, 10, 20, 30, 40, 50 are omitted from the
-count.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_FLAG_COLORFRAME</constant></entry>
- <entry>0x0002</entry>
- <entry>The "color frame" flag.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_USERBITS_field</constant></entry>
- <entry>0x000C</entry>
- <entry>Field mask for the "binary group flags".</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_USERBITS_USERDEFINED</constant></entry>
- <entry>0x0000</entry>
- <entry>Unspecified format.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TC_USERBITS_8BITCHARS</constant></entry>
- <entry>0x0008</entry>
- <entry>8-bit ISO characters.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
- </section>
-
- <section id="field-order">
- <title>Field Order</title>
-
- <para>We have to distinguish between progressive and interlaced
-video. Progressive video transmits all lines of a video image
-sequentially. Interlaced video divides an image into two fields,
-containing only the odd and even lines of the image, respectively.
-Alternating the so called odd and even field are transmitted, and due
-to a small delay between fields a cathode ray TV displays the lines
-interleaved, yielding the original frame. This curious technique was
-invented because at refresh rates similar to film the image would
-fade out too quickly. Transmitting fields reduces the flicker without
-the necessity of doubling the frame rate and with it the bandwidth
-required for each channel.</para>
-
- <para>It is important to understand a video camera does not expose
-one frame at a time, merely transmitting the frames separated into
-fields. The fields are in fact captured at two different instances in
-time. An object on screen may well move between one field and the
-next. For applications analysing motion it is of paramount importance
-to recognize which field of a frame is older, the <emphasis>temporal
-order</emphasis>.</para>
-
- <para>When the driver provides or accepts images field by field
-rather than interleaved, it is also important applications understand
-how the fields combine to frames. We distinguish between top (aka odd) and
-bottom (aka even) fields, the <emphasis>spatial order</emphasis>: The first line
-of the top field is the first line of an interlaced frame, the first
-line of the bottom field is the second line of that frame.</para>
-
- <para>However because fields were captured one after the other,
-arguing whether a frame commences with the top or bottom field is
-pointless. Any two successive top and bottom, or bottom and top fields
-yield a valid frame. Only when the source was progressive to begin
-with, &eg; when transferring film to video, two fields may come from
-the same frame, creating a natural order.</para>
-
- <para>Counter to intuition the top field is not necessarily the
-older field. Whether the older field contains the top or bottom lines
-is a convention determined by the video standard. Hence the
-distinction between temporal and spatial order of fields. The diagrams
-below should make this clearer.</para>
-
- <para>All video capture and output devices must report the current
-field order. Some drivers may permit the selection of a different
-order, to this end applications initialize the
-<structfield>field</structfield> field of &v4l2-pix-format; before
-calling the &VIDIOC-S-FMT; ioctl. If this is not desired it should
-have the value <constant>V4L2_FIELD_ANY</constant> (0).</para>
-
- <table frame="none" pgwide="1" id="v4l2-field">
- <title>enum v4l2_field</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FIELD_ANY</constant></entry>
- <entry>0</entry>
- <entry>Applications request this field order when any
-one of the <constant>V4L2_FIELD_NONE</constant>,
-<constant>V4L2_FIELD_TOP</constant>,
-<constant>V4L2_FIELD_BOTTOM</constant>, or
-<constant>V4L2_FIELD_INTERLACED</constant> formats is acceptable.
-Drivers choose depending on hardware capabilities or e.&nbsp;g. the
-requested image size, and return the actual field order. Drivers must
-never return <constant>V4L2_FIELD_ANY</constant>. If multiple
-field orders are possible the driver must choose one of the possible
-field orders during &VIDIOC-S-FMT; or &VIDIOC-TRY-FMT;. &v4l2-buffer;
-<structfield>field</structfield> can never be
-<constant>V4L2_FIELD_ANY</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_NONE</constant></entry>
- <entry>1</entry>
- <entry>Images are in progressive format, not interlaced.
-The driver may also indicate this order when it cannot distinguish
-between <constant>V4L2_FIELD_TOP</constant> and
-<constant>V4L2_FIELD_BOTTOM</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_TOP</constant></entry>
- <entry>2</entry>
- <entry>Images consist of the top (aka odd) field only.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_BOTTOM</constant></entry>
- <entry>3</entry>
- <entry>Images consist of the bottom (aka even) field only.
-Applications may wish to prevent a device from capturing interlaced
-images because they will have "comb" or "feathering" artefacts around
-moving objects.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_INTERLACED</constant></entry>
- <entry>4</entry>
- <entry>Images contain both fields, interleaved line by
-line. The temporal order of the fields (whether the top or bottom
-field is first transmitted) depends on the current video standard.
-M/NTSC transmits the bottom field first, all other standards the top
-field first.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_SEQ_TB</constant></entry>
- <entry>5</entry>
- <entry>Images contain both fields, the top field lines
-are stored first in memory, immediately followed by the bottom field
-lines. Fields are always stored in temporal order, the older one first
-in memory. Image sizes refer to the frame, not fields.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_SEQ_BT</constant></entry>
- <entry>6</entry>
- <entry>Images contain both fields, the bottom field
-lines are stored first in memory, immediately followed by the top
-field lines. Fields are always stored in temporal order, the older one
-first in memory. Image sizes refer to the frame, not fields.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_ALTERNATE</constant></entry>
- <entry>7</entry>
- <entry>The two fields of a frame are passed in separate
-buffers, in temporal order, &ie; the older one first. To indicate the field
-parity (whether the current field is a top or bottom field) the driver
-or application, depending on data direction, must set &v4l2-buffer;
-<structfield>field</structfield> to
-<constant>V4L2_FIELD_TOP</constant> or
-<constant>V4L2_FIELD_BOTTOM</constant>. Any two successive fields pair
-to build a frame. If fields are successive, without any dropped fields
-between them (fields can drop individually), can be determined from
-the &v4l2-buffer; <structfield>sequence</structfield> field. This format
-cannot be selected when using the read/write I/O method since there
-is no way to communicate if a field was a top or bottom field.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_INTERLACED_TB</constant></entry>
- <entry>8</entry>
- <entry>Images contain both fields, interleaved line by
-line, top field first. The top field is transmitted first.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FIELD_INTERLACED_BT</constant></entry>
- <entry>9</entry>
- <entry>Images contain both fields, interleaved line by
-line, top field first. The bottom field is transmitted first.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <figure id="fieldseq-tb">
- <title>Field Order, Top Field First Transmitted</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="fieldseq_tb.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="fieldseq_tb.gif" format="GIF" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <figure id="fieldseq-bt">
- <title>Field Order, Bottom Field First Transmitted</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="fieldseq_bt.pdf" format="PS" />
- </imageobject>
- <imageobject>
- <imagedata fileref="fieldseq_bt.gif" format="GIF" />
- </imageobject>
- </mediaobject>
- </figure>
- </section>
diff --git a/Documentation/DocBook/media/v4l/keytable.c.xml b/Documentation/DocBook/media/v4l/keytable.c.xml
deleted file mode 100644
index d53254a3be15..000000000000
--- a/Documentation/DocBook/media/v4l/keytable.c.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<programlisting>
-/* keytable.c - This program allows checking/replacing keys at IR
-
- Copyright (C) 2006-2009 Mauro Carvalho Chehab &lt;mchehab@infradead.org&gt;
-
- 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 &lt;ctype.h&gt;
-#include &lt;errno.h&gt;
-#include &lt;fcntl.h&gt;
-#include &lt;stdio.h&gt;
-#include &lt;stdlib.h&gt;
-#include &lt;string.h&gt;
-#include &lt;linux/input.h&gt;
-#include &lt;sys/ioctl.h&gt;
-
-#include "parse.h"
-
-void prtcode (int *codes)
-{
- struct parse_key *p;
-
- for (p=keynames;p-&gt;name!=NULL;p++) {
- if (p-&gt;value == (unsigned)codes[1]) {
- printf("scancode 0x%04x = %s (0x%02x)\n", codes[0], p-&gt;name, codes[1]);
- return;
- }
- }
-
- if (isprint (codes[1]))
- printf("scancode %d = '%c' (0x%02x)\n", codes[0], codes[1], codes[1]);
- else
- printf("scancode %d = 0x%02x\n", codes[0], codes[1]);
-}
-
-int parse_code(char *string)
-{
- struct parse_key *p;
-
- for (p=keynames;p-&gt;name!=NULL;p++) {
- if (!strcasecmp(p-&gt;name, string)) {
- return p-&gt;value;
- }
- }
- return -1;
-}
-
-int main (int argc, char *argv[])
-{
- int fd;
- unsigned int i, j;
- int codes[2];
-
- if (argc&lt;2 || argc&gt;4) {
- printf ("usage: %s &lt;device&gt; to get table; or\n"
- " %s &lt;device&gt; &lt;scancode&gt; &lt;keycode&gt;\n"
- " %s &lt;device&gt; &lt;keycode_file&gt;\n",*argv,*argv,*argv);
- return -1;
- }
-
- if ((fd = open(argv[1], O_RDONLY)) &lt; 0) {
- perror("Couldn't open input device");
- return(-1);
- }
-
- if (argc==4) {
- int value;
-
- value=parse_code(argv[3]);
-
- if (value==-1) {
- value = strtol(argv[3], NULL, 0);
- if (errno)
- perror("value");
- }
-
- codes [0] = (unsigned) strtol(argv[2], NULL, 0);
- codes [1] = (unsigned) value;
-
- if(ioctl(fd, EVIOCSKEYCODE, codes))
- perror ("EVIOCSKEYCODE");
-
- if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
- prtcode(codes);
- return 0;
- }
-
- if (argc==3) {
- FILE *fin;
- int value;
- char *scancode, *keycode, s[2048];
-
- fin=fopen(argv[2],"r");
- if (fin==NULL) {
- perror ("opening keycode file");
- return -1;
- }
-
- /* Clears old table */
- for (j = 0; j &lt; 256; j++) {
- for (i = 0; i &lt; 256; i++) {
- codes[0] = (j &lt;&lt; 8) | i;
- codes[1] = KEY_RESERVED;
- ioctl(fd, EVIOCSKEYCODE, codes);
- }
- }
-
- while (fgets(s,sizeof(s),fin)) {
- scancode=strtok(s,"\n\t =:");
- if (!scancode) {
- perror ("parsing input file scancode");
- return -1;
- }
- if (!strcasecmp(scancode, "scancode")) {
- scancode = strtok(NULL,"\n\t =:");
- if (!scancode) {
- perror ("parsing input file scancode");
- return -1;
- }
- }
-
- keycode=strtok(NULL,"\n\t =:(");
- if (!keycode) {
- perror ("parsing input file keycode");
- return -1;
- }
-
- // printf ("parsing %s=%s:", scancode, keycode);
- value=parse_code(keycode);
- // printf ("\tvalue=%d\n",value);
-
- if (value==-1) {
- value = strtol(keycode, NULL, 0);
- if (errno)
- perror("value");
- }
-
- codes [0] = (unsigned) strtol(scancode, NULL, 0);
- codes [1] = (unsigned) value;
-
- // printf("\t%04x=%04x\n",codes[0], codes[1]);
- if(ioctl(fd, EVIOCSKEYCODE, codes)) {
- fprintf(stderr, "Setting scancode 0x%04x with 0x%04x via ",codes[0], codes[1]);
- perror ("EVIOCSKEYCODE");
- }
-
- if(ioctl(fd, EVIOCGKEYCODE, codes)==0)
- prtcode(codes);
- }
- return 0;
- }
-
- /* Get scancode table */
- for (j = 0; j &lt; 256; j++) {
- for (i = 0; i &lt; 256; i++) {
- codes[0] = (j &lt;&lt; 8) | i;
- if (!ioctl(fd, EVIOCGKEYCODE, codes) &amp;&amp; codes[1] != KEY_RESERVED)
- prtcode(codes);
- }
- }
- return 0;
-}
-
-</programlisting>
diff --git a/Documentation/DocBook/media/v4l/libv4l.xml b/Documentation/DocBook/media/v4l/libv4l.xml
deleted file mode 100644
index d3b71e20003c..000000000000
--- a/Documentation/DocBook/media/v4l/libv4l.xml
+++ /dev/null
@@ -1,160 +0,0 @@
-<title>Libv4l Userspace Library</title>
-<section id="libv4l-introduction">
- <title>Introduction</title>
-
- <para>libv4l is a collection of libraries which adds a thin abstraction
-layer on top of video4linux2 devices. The purpose of this (thin) layer
-is to make it easy for application writers to support a wide variety of
-devices without having to write separate code for different devices in the
-same class.</para>
-<para>An example of using libv4l is provided by
-<link linkend='v4l2grab-example'>v4l2grab</link>.
-</para>
-
- <para>libv4l consists of 3 different libraries:</para>
- <section>
- <title>libv4lconvert</title>
-
- <para>libv4lconvert is a library that converts several
-different pixelformats found in V4L2 drivers into a few common RGB and
-YUY formats.</para>
- <para>It currently accepts the following V4L2 driver formats:
-<link linkend="V4L2-PIX-FMT-BGR24"><constant>V4L2_PIX_FMT_BGR24</constant></link>,
-<link linkend="V4L2-PIX-FMT-HM12"><constant>V4L2_PIX_FMT_HM12</constant></link>,
-<link linkend="V4L2-PIX-FMT-JPEG"><constant>V4L2_PIX_FMT_JPEG</constant></link>,
-<link linkend="V4L2-PIX-FMT-MJPEG"><constant>V4L2_PIX_FMT_MJPEG</constant></link>,
-<link linkend="V4L2-PIX-FMT-MR97310A"><constant>V4L2_PIX_FMT_MR97310A</constant></link>,
-<link linkend="V4L2-PIX-FMT-OV511"><constant>V4L2_PIX_FMT_OV511</constant></link>,
-<link linkend="V4L2-PIX-FMT-OV518"><constant>V4L2_PIX_FMT_OV518</constant></link>,
-<link linkend="V4L2-PIX-FMT-PAC207"><constant>V4L2_PIX_FMT_PAC207</constant></link>,
-<link linkend="V4L2-PIX-FMT-PJPG"><constant>V4L2_PIX_FMT_PJPG</constant></link>,
-<link linkend="V4L2-PIX-FMT-RGB24"><constant>V4L2_PIX_FMT_RGB24</constant></link>,
-<link linkend="V4L2-PIX-FMT-SBGGR8"><constant>V4L2_PIX_FMT_SBGGR8</constant></link>,
-<link linkend="V4L2-PIX-FMT-SGBRG8"><constant>V4L2_PIX_FMT_SGBRG8</constant></link>,
-<link linkend="V4L2-PIX-FMT-SGRBG8"><constant>V4L2_PIX_FMT_SGRBG8</constant></link>,
-<link linkend="V4L2-PIX-FMT-SN9C10X"><constant>V4L2_PIX_FMT_SN9C10X</constant></link>,
-<link linkend="V4L2-PIX-FMT-SN9C20X-I420"><constant>V4L2_PIX_FMT_SN9C20X_I420</constant></link>,
-<link linkend="V4L2-PIX-FMT-SPCA501"><constant>V4L2_PIX_FMT_SPCA501</constant></link>,
-<link linkend="V4L2-PIX-FMT-SPCA505"><constant>V4L2_PIX_FMT_SPCA505</constant></link>,
-<link linkend="V4L2-PIX-FMT-SPCA508"><constant>V4L2_PIX_FMT_SPCA508</constant></link>,
-<link linkend="V4L2-PIX-FMT-SPCA561"><constant>V4L2_PIX_FMT_SPCA561</constant></link>,
-<link linkend="V4L2-PIX-FMT-SQ905C"><constant>V4L2_PIX_FMT_SQ905C</constant></link>,
-<constant>V4L2_PIX_FMT_SRGGB8</constant>,
-<link linkend="V4L2-PIX-FMT-UYVY"><constant>V4L2_PIX_FMT_UYVY</constant></link>,
-<link linkend="V4L2-PIX-FMT-YUV420"><constant>V4L2_PIX_FMT_YUV420</constant></link>,
-<link linkend="V4L2-PIX-FMT-YUYV"><constant>V4L2_PIX_FMT_YUYV</constant></link>,
-<link linkend="V4L2-PIX-FMT-YVU420"><constant>V4L2_PIX_FMT_YVU420</constant></link>,
-and <link linkend="V4L2-PIX-FMT-YVYU"><constant>V4L2_PIX_FMT_YVYU</constant></link>.
-</para>
- <para>Later on libv4lconvert was expanded to also be able to do
-various video processing functions to improve webcam video quality.
-The video processing is split in to 2 parts: libv4lconvert/control and
-libv4lconvert/processing.</para>
-
- <para>The control part is used to offer video controls which can
-be used to control the video processing functions made available by
- libv4lconvert/processing. These controls are stored application wide
-(until reboot) by using a persistent shared memory object.</para>
-
- <para>libv4lconvert/processing offers the actual video
-processing functionality.</para>
- </section>
- <section>
- <title>libv4l1</title>
- <para>This library offers functions that can be used to quickly
-make v4l1 applications work with v4l2 devices. These functions work exactly
-like the normal open/close/etc, except that libv4l1 does full emulation of
-the v4l1 api on top of v4l2 drivers, in case of v4l1 drivers it
-will just pass calls through.</para>
- <para>Since those functions are emulations of the old V4L1 API,
-it shouldn't be used for new applications.</para>
- </section>
- <section>
- <title>libv4l2</title>
- <para>This library should be used for all modern V4L2
-applications.</para>
- <para>It provides handles to call V4L2 open/ioctl/close/poll
-methods. Instead of just providing the raw output of the device, it enhances
-the calls in the sense that it will use libv4lconvert to provide more video
-formats and to enhance the image quality.</para>
- <para>In most cases, libv4l2 just passes the calls directly
-through to the v4l2 driver, intercepting the calls to
-<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>,
-<link linkend='vidioc-g-fmt'><constant>VIDIOC_G_FMT</constant></link>
-<link linkend='vidioc-g-fmt'><constant>VIDIOC_S_FMT</constant></link>
-<link linkend='vidioc-enum-framesizes'><constant>VIDIOC_ENUM_FRAMESIZES</constant></link>
-and <link linkend='vidioc-enum-frameintervals'><constant>VIDIOC_ENUM_FRAMEINTERVALS</constant></link>
-in order to emulate the formats
-<link linkend="V4L2-PIX-FMT-BGR24"><constant>V4L2_PIX_FMT_BGR24</constant></link>,
-<link linkend="V4L2-PIX-FMT-RGB24"><constant>V4L2_PIX_FMT_RGB24</constant></link>,
-<link linkend="V4L2-PIX-FMT-YUV420"><constant>V4L2_PIX_FMT_YUV420</constant></link>,
-and <link linkend="V4L2-PIX-FMT-YVU420"><constant>V4L2_PIX_FMT_YVU420</constant></link>,
-if they aren't available in the driver.
-<link linkend='vidioc-enum-fmt'><constant>VIDIOC_ENUM_FMT</constant></link>
-keeps enumerating the hardware supported formats, plus the emulated formats
-offered by libv4l at the end.
-</para>
- <section id="libv4l-ops">
- <title>Libv4l device control functions</title>
- <para>The common file operation methods are provided by
-libv4l.</para>
- <para>Those functions operate just like glibc
-open/close/dup/ioctl/read/mmap/munmap:</para>
-<itemizedlist><listitem>
- <para>int v4l2_open(const char *file, int oflag,
-...) -
-operates like the standard <link linkend='func-open'>open()</link> function.
-</para></listitem><listitem>
- <para>int v4l2_close(int fd) -
-operates like the standard <link linkend='func-close'>close()</link> function.
-</para></listitem><listitem>
- <para>int v4l2_dup(int fd) -
-operates like the standard dup() function, duplicating a file handler.
-</para></listitem><listitem>
- <para>int v4l2_ioctl (int fd, unsigned long int request, ...) -
-operates like the standard <link linkend='func-ioctl'>ioctl()</link> function.
-</para></listitem><listitem>
- <para>int v4l2_read (int fd, void* buffer, size_t n) -
-operates like the standard <link linkend='func-read'>read()</link> function.
-</para></listitem><listitem>
- <para>void v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, int64_t offset); -
-operates like the standard <link linkend='func-mmap'>mmap()</link> function.
-</para></listitem><listitem>
- <para>int v4l2_munmap(void *_start, size_t length); -
-operates like the standard <link linkend='func-munmap'>munmap()</link> function.
-</para></listitem>
-</itemizedlist>
- <para>Those functions provide additional control:</para>
-<itemizedlist><listitem>
- <para>int v4l2_fd_open(int fd, int v4l2_flags) -
-opens an already opened fd for further use through v4l2lib and possibly
-modify libv4l2's default behavior through the v4l2_flags argument.
-Currently, v4l2_flags can be <constant>V4L2_DISABLE_CONVERSION</constant>,
-to disable format conversion.
-</para></listitem><listitem>
- <para>int v4l2_set_control(int fd, int cid, int value) -
-This function takes a value of 0 - 65535, and then scales that range to
-the actual range of the given v4l control id, and then if the cid exists
-and is not locked sets the cid to the scaled value.
-</para></listitem><listitem>
- <para>int v4l2_get_control(int fd, int cid) -
-This function returns a value of 0 - 65535, scaled to from the actual range
-of the given v4l control id. when the cid does not exist, could not be
-accessed for some reason, or some error occurred 0 is returned.
-</para></listitem>
-</itemizedlist>
- </section>
- </section>
- <section>
-
- <title>v4l1compat.so wrapper library</title>
-
- <para>This library intercepts calls to
-open/close/ioctl/mmap/mmunmap operations and redirects them to the libv4l
-counterparts, by using LD_PRELOAD=/usr/lib/v4l1compat.so. It also
-emulates V4L1 calls via V4L2 API.</para>
- <para>It allows usage of binary legacy applications that
-still don't use libv4l.</para>
- </section>
-
-</section>
diff --git a/Documentation/DocBook/media/v4l/lirc_device_interface.xml b/Documentation/DocBook/media/v4l/lirc_device_interface.xml
deleted file mode 100644
index f53ad58027a7..000000000000
--- a/Documentation/DocBook/media/v4l/lirc_device_interface.xml
+++ /dev/null
@@ -1,255 +0,0 @@
-<section id="lirc_dev">
-<title>LIRC Device Interface</title>
-
-
-<section id="lirc_dev_intro">
-<title>Introduction</title>
-
-<para>The LIRC device interface is a bi-directional interface for
-transporting raw IR data between userspace and kernelspace. Fundamentally,
-it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number
-of standard struct file_operations defined on it. With respect to
-transporting raw IR data to and fro, the essential fops are read, write
-and ioctl.</para>
-
-<para>Example dmesg output upon a driver registering w/LIRC:</para>
- <blockquote>
- <para>$ dmesg |grep lirc_dev</para>
- <para>lirc_dev: IR Remote Control driver registered, major 248</para>
- <para>rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0</para>
- </blockquote>
-
-<para>What you should see for a chardev:</para>
- <blockquote>
- <para>$ ls -l /dev/lirc*</para>
- <para>crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0</para>
- </blockquote>
-</section>
-
-<section id="lirc_read">
-<title>LIRC read fop</title>
-
-<para>The lircd userspace daemon reads raw IR data from the LIRC chardev. The
-exact format of the data depends on what modes a driver supports, and what
-mode has been selected. lircd obtains supported modes and sets the active mode
-via the ioctl interface, detailed at <xref linkend="lirc_ioctl"/>. The generally
-preferred mode is LIRC_MODE_MODE2, in which packets containing an int value
-describing an IR signal are read from the chardev.</para>
-
-<para>See also <ulink url="http://www.lirc.org/html/technical.html">http://www.lirc.org/html/technical.html</ulink> for more info.</para>
-</section>
-
-<section id="lirc_write">
-<title>LIRC write fop</title>
-
-<para>The data written to the chardev is a pulse/space sequence of integer
-values. Pulses and spaces are only marked implicitly by their position. The
-data must start and end with a pulse, therefore, the data must always include
-an uneven number of samples. The write function must block until the data has
-been transmitted by the hardware. If more data is provided than the hardware
-can send, the driver returns EINVAL.</para>
-
-</section>
-
-<section id="lirc_ioctl">
-<title>LIRC ioctl fop</title>
-
-<para>The LIRC device's ioctl definition is bound by the ioctl function
-definition of struct file_operations, leaving us with an unsigned int
-for the ioctl command and an unsigned long for the arg. For the purposes
-of ioctl portability across 32-bit and 64-bit, these values are capped
-to their 32-bit sizes.</para>
-
-<para>The following ioctls can be used to change specific hardware settings.
-In general each driver should have a default set of settings. The driver
-implementation is expected to re-apply the default settings when the device
-is closed by user-space, so that every application opening the device can rely
-on working with the default settings initially.</para>
-
-<variablelist>
- <varlistentry>
- <term>LIRC_GET_FEATURES</term>
- <listitem>
- <para>Obviously, get the underlying hardware device's features. If a driver
- does not announce support of certain features, calling of the corresponding
- ioctls is undefined.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_SEND_MODE</term>
- <listitem>
- <para>Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_REC_MODE</term>
- <listitem>
- <para>Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE
- are supported by lircd.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_SEND_CARRIER</term>
- <listitem>
- <para>Get carrier frequency (in Hz) currently used for transmit.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_REC_CARRIER</term>
- <listitem>
- <para>Get carrier frequency (in Hz) currently used for IR reception.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE</term>
- <listitem>
- <para>Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently,
- no special meaning is defined for 0 or 100, but this could be used to switch
- off carrier generation in the future, so these values should be reserved.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_REC_RESOLUTION</term>
- <listitem>
- <para>Some receiver have maximum resolution which is defined by internal
- sample rate or data format limitations. E.g. it's common that signals can
- only be reported in 50 microsecond steps. This integer value is used by
- lircd to automatically adjust the steps tolerance value in the lircd
- config file.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_M{IN,AX}_TIMEOUT</term>
- <listitem>
- <para>Some devices have internal timers that can be used to detect when
- there's no IR activity for a long time. This can help lircd in detecting
- that a IR signal is finished and can speed up the decoding process.
- Returns an integer value with the minimum/maximum timeout that can be
- set. Some devices have a fixed timeout, in that case both ioctls will
- return the same value even though the timeout cannot be changed.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE}</term>
- <listitem>
- <para>Some devices are able to filter out spikes in the incoming signal
- using given filter rules. These ioctls return the hardware capabilities
- that describe the bounds of the possible filters. Filter settings depend
- on the IR protocols that are expected. lircd derives the settings from
- all protocols definitions found in its config file.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_GET_LENGTH</term>
- <listitem>
- <para>Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE).
- Reads on the device must be done in blocks matching the bit count.
- The bit could should be rounded up so that it matches full bytes.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_{SEND,REC}_MODE</term>
- <listitem>
- <para>Set send/receive mode. Largely obsolete for send, as only
- LIRC_MODE_PULSE is supported.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_{SEND,REC}_CARRIER</term>
- <listitem>
- <para>Set send/receive carrier (in Hz). Return 0 on success.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_TRANSMITTER_MASK</term>
- <listitem>
- <para>This enables the given set of transmitters. The first transmitter
- is encoded by the least significant bit, etc. When an invalid bit mask
- is given, i.e. a bit is set, even though the device does not have so many
- transitters, then this ioctl returns the number of available transitters
- and does nothing otherwise.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_REC_TIMEOUT</term>
- <listitem>
- <para>Sets the integer value for IR inactivity timeout (cf.
- LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if
- supported by the hardware) disables all hardware timeouts and data should
- be reported as soon as possible. If the exact value cannot be set, then
- the next possible value _greater_ than the given value should be set.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_REC_TIMEOUT_REPORTS</term>
- <listitem>
- <para>Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By
- default, timeout reports should be turned off.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_REC_FILTER_{,PULSE,SPACE}</term>
- <listitem>
- <para>Pulses/spaces shorter than this are filtered out by hardware. If
- filters cannot be set independently for pulse/space, the corresponding
- ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_MEASURE_CARRIER_MODE</term>
- <listitem>
- <para>Enable (1)/disable (0) measure mode. If enabled, from the next key
- press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default
- this should be turned off.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE</term>
- <listitem>
- <para>To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE
- with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER
- with the upper bound.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_NOTIFY_DECODE</term>
- <listitem>
- <para>This ioctl is called by lircd whenever a successful decoding of an
- incoming IR signal could be done. This can be used by supporting hardware
- to give visual feedback to the user e.g. by flashing a LED.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SETUP_{START,END}</term>
- <listitem>
- <para>Setting of several driver parameters can be optimized by encapsulating
- the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a
- driver receives a LIRC_SETUP_START ioctl it can choose to not commit
- further setting changes to the hardware until a LIRC_SETUP_END is received.
- But this is open to the driver implementation and every driver must also
- handle parameter changes which are not encapsulated by LIRC_SETUP_START
- and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>LIRC_SET_WIDEBAND_RECEIVER</term>
- <listitem>
- <para>Some receivers are equipped with special wide band receiver which is intended
- to be used to learn output of existing remote.
- Calling that ioctl with (1) will enable it, and with (0) disable it.
- This might be useful of receivers that have otherwise narrow band receiver
- that prevents them to be used with some remotes.
- Wide band receiver might also be more precise
- On the other hand its disadvantage it usually reduced range of reception.
- Note: wide band receiver might be implictly enabled if you enable
- carrier reports. In that case it will be disabled as soon as you disable
- carrier reports. Trying to disable wide band receiver while carrier
- reports are active will do nothing.</para>
- </listitem>
- </varlistentry>
-</variablelist>
-<section id="lirc_dev_errors">
- &return-value;
-</section>
-</section>
-</section>
diff --git a/Documentation/DocBook/media/v4l/media-controller.xml b/Documentation/DocBook/media/v4l/media-controller.xml
deleted file mode 100644
index 5f2fc07a93d7..000000000000
--- a/Documentation/DocBook/media/v4l/media-controller.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<partinfo>
- <authorgroup>
- <author>
- <firstname>Laurent</firstname>
- <surname>Pinchart</surname>
- <affiliation><address><email>laurent.pinchart@ideasonboard.com</email></address></affiliation>
- <contrib>Initial version.</contrib>
- </author>
- </authorgroup>
- <copyright>
- <year>2010</year>
- <holder>Laurent Pinchart</holder>
- </copyright>
-
- <revhistory>
- <!-- Put document revisions here, newest first. -->
- <revision>
- <revnumber>1.0.0</revnumber>
- <date>2010-11-10</date>
- <authorinitials>lp</authorinitials>
- <revremark>Initial revision</revremark>
- </revision>
- </revhistory>
-</partinfo>
-
-<title>Media Controller API</title>
-
-<chapter id="media_controller">
- <title>Media Controller</title>
-
- <section id="media-controller-intro">
- <title>Introduction</title>
- <para>Media devices increasingly handle multiple related functions. Many USB
- cameras include microphones, video capture hardware can also output video,
- or SoC camera interfaces also perform memory-to-memory operations similar to
- video codecs.</para>
- <para>Independent functions, even when implemented in the same hardware, can
- be modelled as separate devices. A USB camera with a microphone will be
- presented to userspace applications as V4L2 and ALSA capture devices. The
- devices' relationships (when using a webcam, end-users shouldn't have to
- manually select the associated USB microphone), while not made available
- directly to applications by the drivers, can usually be retrieved from
- sysfs.</para>
- <para>With more and more advanced SoC devices being introduced, the current
- approach will not scale. Device topologies are getting increasingly complex
- and can't always be represented by a tree structure. Hardware blocks are
- shared between different functions, creating dependencies between seemingly
- unrelated devices.</para>
- <para>Kernel abstraction APIs such as V4L2 and ALSA provide means for
- applications to access hardware parameters. As newer hardware expose an
- increasingly high number of those parameters, drivers need to guess what
- applications really require based on limited information, thereby
- implementing policies that belong to userspace.</para>
- <para>The media controller API aims at solving those problems.</para>
- </section>
-
- <section id="media-controller-model">
- <title>Media device model</title>
- <para>Discovering a device internal topology, and configuring it at runtime,
- is one of the goals of the media controller API. To achieve this, hardware
- devices and Linux Kernel interfaces are modelled as graph objects on
- an oriented graph. The object types that constitute the graph are:</para>
- <itemizedlist>
- <listitem><para>An <emphasis role="bold">entity</emphasis>
- is a basic media hardware or software building block. It can correspond to
- a large variety of logical blocks such as physical hardware devices
- (CMOS sensor for instance), logical hardware devices (a building block in
- a System-on-Chip image processing pipeline), DMA channels or physical
- connectors.</para></listitem>
- <listitem><para>An <emphasis role="bold">interface</emphasis>
- is a graph representation of a Linux Kernel userspace API interface,
- like a device node or a sysfs file that controls one or more entities
- in the graph.</para></listitem>
- <listitem><para>A <emphasis role="bold">pad</emphasis>
- is a data connection endpoint through which an entity can interact with
- other entities. Data (not restricted to video) produced by an entity
- flows from the entity's output to one or more entity inputs. Pads should
- not be confused with physical pins at chip boundaries.</para></listitem>
- <listitem><para>A <emphasis role="bold">data link</emphasis>
- is a point-to-point oriented connection between two pads, either on the
- same entity or on different entities. Data flows from a source pad to a
- sink pad.</para></listitem>
- <listitem><para>An <emphasis role="bold">interface link</emphasis>
- is a point-to-point bidirectional control connection between a Linux
- Kernel interface and an entity.m</para></listitem>
- </itemizedlist>
- </section>
-
- <!-- All non-ioctl specific data types go here. -->
- &sub-media-types;
-</chapter>
-
-<appendix id="media-user-func">
- <title>Function Reference</title>
- <!-- Keep this alphabetically sorted. -->
- &sub-media-func-open;
- &sub-media-func-close;
- &sub-media-func-ioctl;
- <!-- All ioctls go here. -->
- &sub-media-ioc-device-info;
- &sub-media-ioc-g-topology;
- &sub-media-ioc-enum-entities;
- &sub-media-ioc-enum-links;
- &sub-media-ioc-setup-link;
-</appendix>
diff --git a/Documentation/DocBook/media/v4l/media-func-close.xml b/Documentation/DocBook/media/v4l/media-func-close.xml
deleted file mode 100644
index be149c802aeb..000000000000
--- a/Documentation/DocBook/media/v4l/media-func-close.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<refentry id="media-func-close">
- <refmeta>
- <refentrytitle>media close()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>media-close</refname>
- <refpurpose>Close a media device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>close</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>&fd;</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Closes the media device. Resources associated with the file descriptor
- are freed. The device configuration remain unchanged.</para>
- </refsect1>
-
- <refsect1>
- <title>Return Value</title>
-
- <para><function>close</function> returns 0 on success. On error, -1 is
- returned, and <varname>errno</varname> is set appropriately. Possible error
- codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBADF</errorcode></term>
- <listitem>
- <para><parameter>fd</parameter> is not a valid open file descriptor.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-func-ioctl.xml b/Documentation/DocBook/media/v4l/media-func-ioctl.xml
deleted file mode 100644
index 39478d0fbcaa..000000000000
--- a/Documentation/DocBook/media/v4l/media-func-ioctl.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<refentry id="media-func-ioctl">
- <refmeta>
- <refentrytitle>media ioctl()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>media-ioctl</refname>
- <refpurpose>Control a media 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>Media ioctl request code as defined in the media.h header file,
- for example MEDIA_IOC_SETUP_LINK.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>Pointer to a request-specific structure.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>The <function>ioctl()</function> function manipulates media device
- parameters. The argument <parameter>fd</parameter> must be an open file
- descriptor.</para>
- <para>The ioctl <parameter>request</parameter> code specifies the media
- function to be called. It 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.</para>
- <para>Macros and structures definitions specifying media ioctl requests and
- their parameters are located in the media.h header file. All media ioctl
- requests, their respective function and parameters are specified in
- <xref linkend="media-user-func" />.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <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>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-func-open.xml b/Documentation/DocBook/media/v4l/media-func-open.xml
deleted file mode 100644
index 122374a3e894..000000000000
--- a/Documentation/DocBook/media/v4l/media-func-open.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<refentry id="media-func-open">
- <refmeta>
- <refentrytitle>media open()</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>media-open</refname>
- <refpurpose>Open a media device</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
- <funcprototype>
- <funcdef>int <function>open</function></funcdef>
- <paramdef>const char *<parameter>device_name</parameter></paramdef>
- <paramdef>int <parameter>flags</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>device_name</parameter></term>
- <listitem>
- <para>Device to be opened.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>flags</parameter></term>
- <listitem>
- <para>Open flags. Access mode must be either <constant>O_RDONLY</constant>
- or <constant>O_RDWR</constant>. Other flags have no effect.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- <title>Description</title>
- <para>To open a media device applications call <function>open()</function>
- with the desired device name. The function has no side effects; the device
- configuration remain unchanged.</para>
- <para>When the device is opened in read-only mode, attempts to modify its
- configuration will result in an error, and <varname>errno</varname> will be
- set to <errorcode>EBADF</errorcode>.</para>
- </refsect1>
- <refsect1>
- <title>Return Value</title>
-
- <para><function>open</function> returns the new file descriptor on success.
- On error, -1 is returned, and <varname>errno</varname> is set appropriately.
- Possible error codes are:</para>
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para>The requested access to the file is not allowed.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EMFILE</errorcode></term>
- <listitem>
- <para>The process already has the maximum number of files open.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENFILE</errorcode></term>
- <listitem>
- <para>The system limit on the total number of open files has been
- reached.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOMEM</errorcode></term>
- <listitem>
- <para>Insufficient kernel memory was available.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENXIO</errorcode></term>
- <listitem>
- <para>No device corresponding to this device special file exists.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-device-info.xml b/Documentation/DocBook/media/v4l/media-ioc-device-info.xml
deleted file mode 100644
index b0a21ac300b8..000000000000
--- a/Documentation/DocBook/media/v4l/media-ioc-device-info.xml
+++ /dev/null
@@ -1,132 +0,0 @@
-<refentry id="media-ioc-device-info">
- <refmeta>
- <refentrytitle>ioctl MEDIA_IOC_DEVICE_INFO</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>MEDIA_IOC_DEVICE_INFO</refname>
- <refpurpose>Query device information</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 media_device_info *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='media-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>MEDIA_IOC_DEVICE_INFO</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>All media devices must support the <constant>MEDIA_IOC_DEVICE_INFO</constant>
- ioctl. To query device information, applications call the ioctl with a
- pointer to a &media-device-info;. The driver fills the structure and returns
- the information to the application.
- The ioctl never fails.</para>
-
- <table pgwide="1" frame="none" id="media-device-info">
- <title>struct <structname>media_device_info</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>char</entry>
- <entry><structfield>driver</structfield>[16]</entry>
- <entry><para>Name of the driver implementing the media API as a
- NUL-terminated ASCII string. The driver version is stored in the
- <structfield>driver_version</structfield> field.</para>
- <para>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.</para></entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>model</structfield>[32]</entry>
- <entry>Device model name as a NUL-terminated UTF-8 string. The
- device version is stored in the <structfield>device_version</structfield>
- field and is not be appended to the model name.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>serial</structfield>[40]</entry>
- <entry>Serial number as a NUL-terminated ASCII string.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>bus_info</structfield>[32]</entry>
- <entry>Location of the device in the system as a NUL-terminated
- ASCII string. This includes the bus type name (PCI, USB, ...) and a
- bus-specific identifier.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>media_version</structfield></entry>
- <entry>Media API version, formatted with the
- <constant>KERNEL_VERSION()</constant> macro.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>hw_revision</structfield></entry>
- <entry>Hardware device revision in a driver-specific format.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>driver_version</structfield></entry>
- <entry>Media device driver version, formatted with the
- <constant>KERNEL_VERSION()</constant> macro. Together with the
- <structfield>driver</structfield> field this identifies a particular
- driver.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[31]</entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set this array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>The <structfield>serial</structfield> and <structfield>bus_info</structfield>
- fields can be used to distinguish between multiple instances of otherwise
- identical hardware. The serial number takes precedence when provided and can
- be assumed to be unique. If the serial number is an empty string, the
- <structfield>bus_info</structfield> field can be used instead. The
- <structfield>bus_info</structfield> field is guaranteed to be unique, but
- can vary across reboots or device unplug/replug.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml b/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
deleted file mode 100644
index 0c4f96bfc2de..000000000000
--- a/Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
+++ /dev/null
@@ -1,180 +0,0 @@
-<refentry id="media-ioc-enum-entities">
- <refmeta>
- <refentrytitle>ioctl MEDIA_IOC_ENUM_ENTITIES</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>MEDIA_IOC_ENUM_ENTITIES</refname>
- <refpurpose>Enumerate entities and their properties</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 media_entity_desc *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='media-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>MEDIA_IOC_ENUM_ENTITIES</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>To query the attributes of an entity, applications set the id field
- of a &media-entity-desc; structure and call the MEDIA_IOC_ENUM_ENTITIES
- ioctl with a pointer to this structure. The driver fills the rest of the
- structure or returns an &EINVAL; when the id is invalid.</para>
- <para>Entities can be enumerated by or'ing the id with the
- <constant>MEDIA_ENT_ID_FLAG_NEXT</constant> flag. The driver will return
- information about the entity with the smallest id strictly larger than the
- requested one ('next entity'), or the &EINVAL; if there is none.</para>
- <para>Entity IDs can be non-contiguous. Applications must
- <emphasis>not</emphasis> try to enumerate entities by calling
- MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para>
-
- <table pgwide="1" frame="none" id="media-entity-desc">
- <title>struct <structname>media_entity_desc</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity id, set by the application. When the id is or'ed with
- <constant>MEDIA_ENT_ID_FLAG_NEXT</constant>, the driver clears the
- flag and returns the first entity with a larger id.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity name as an UTF-8 NULL-terminated string.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity type, see <xref linkend="media-entity-type" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>revision</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity revision. Always zero (obsolete)</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity flags, see <xref linkend="media-entity-flag" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>group_id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity group ID. Always zero (obsolete)</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>pads</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Number of pads</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>links</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Total number of outbound links. Inbound links are not counted
- in this field.</entry>
- </row>
- <row>
- <entry>union</entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct</entry>
- <entry><structfield>dev</structfield></entry>
- <entry></entry>
- <entry>Valid for (sub-)devices that create a single device node.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>major</structfield></entry>
- <entry>Device node major number.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>minor</structfield></entry>
- <entry>Device node minor number.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8</entry>
- <entry><structfield>raw</structfield>[184]</entry>
- <entry></entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &media-entity-desc; <structfield>id</structfield> references
- a non-existing entity.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml b/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml
deleted file mode 100644
index 2bbeea9f3e18..000000000000
--- a/Documentation/DocBook/media/v4l/media-ioc-enum-links.xml
+++ /dev/null
@@ -1,160 +0,0 @@
-<refentry id="media-ioc-enum-links">
- <refmeta>
- <refentrytitle>ioctl MEDIA_IOC_ENUM_LINKS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>MEDIA_IOC_ENUM_LINKS</refname>
- <refpurpose>Enumerate all pads and links for a given entity</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 media_links_enum *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='media-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>MEDIA_IOC_ENUM_LINKS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To enumerate pads and/or links for a given entity, applications set
- the entity field of a &media-links-enum; structure and initialize the
- &media-pad-desc; and &media-link-desc; structure arrays pointed by the
- <structfield>pads</structfield> and <structfield>links</structfield> fields.
- They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this
- structure.</para>
- <para>If the <structfield>pads</structfield> field is not NULL, the driver
- fills the <structfield>pads</structfield> array with information about the
- entity's pads. The array must have enough room to store all the entity's
- pads. The number of pads can be retrieved with the &MEDIA-IOC-ENUM-ENTITIES;
- ioctl.</para>
- <para>If the <structfield>links</structfield> field is not NULL, the driver
- fills the <structfield>links</structfield> array with information about the
- entity's outbound links. The array must have enough room to store all the
- entity's outbound links. The number of outbound links can be retrieved with
- the &MEDIA-IOC-ENUM-ENTITIES; ioctl.</para>
- <para>Only forward links that originate at one of the entity's source pads
- are returned during the enumeration process.</para>
-
- <table pgwide="1" frame="none" id="media-links-enum">
- <title>struct <structname>media_links_enum</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>entity</structfield></entry>
- <entry>Entity id, set by the application.</entry>
- </row>
- <row>
- <entry>&media-pad-desc;</entry>
- <entry>*<structfield>pads</structfield></entry>
- <entry>Pointer to a pads array allocated by the application. Ignored
- if NULL.</entry>
- </row>
- <row>
- <entry>&media-link-desc;</entry>
- <entry>*<structfield>links</structfield></entry>
- <entry>Pointer to a links array allocated by the application. Ignored
- if NULL.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-pad-desc">
- <title>struct <structname>media_pad_desc</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>entity</structfield></entry>
- <entry>ID of the entity this pad belongs to.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>index</structfield></entry>
- <entry>0-based pad index.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-link-desc">
- <title>struct <structname>media_link_desc</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>&media-pad-desc;</entry>
- <entry><structfield>source</structfield></entry>
- <entry>Pad at the origin of this link.</entry>
- </row>
- <row>
- <entry>&media-pad-desc;</entry>
- <entry><structfield>sink</structfield></entry>
- <entry>Pad at the target of this link.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &media-links-enum; <structfield>id</structfield> references
- a non-existing entity.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml
deleted file mode 100644
index e0d49fa329f0..000000000000
--- a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml
+++ /dev/null
@@ -1,391 +0,0 @@
-<refentry id="media-g-topology">
- <refmeta>
- <refentrytitle>ioctl MEDIA_IOC_G_TOPOLOGY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>MEDIA_IOC_G_TOPOLOGY</refname>
- <refpurpose>Enumerate the graph topology and graph element properties</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 media_v2_topology *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='media-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>MEDIA_IOC_G_TOPOLOGY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>The typical usage of this ioctl is to call it twice.
- On the first call, the structure defined at &media-v2-topology; should
- be zeroed. At return, if no errors happen, this ioctl will return the
- <constant>topology_version</constant> and the total number of entities,
- interfaces, pads and links.</para>
- <para>Before the second call, the userspace should allocate arrays to
- store the graph elements that are desired, putting the pointers to them
- at the ptr_entities, ptr_interfaces, ptr_links and/or ptr_pads, keeping
- the other values untouched.</para>
- <para>If the <constant>topology_version</constant> remains the same, the
- ioctl should fill the desired arrays with the media graph elements.</para>
-
- <table pgwide="1" frame="none" id="media-v2-topology">
- <title>struct <structname>media_v2_topology</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u64</entry>
- <entry><structfield>topology_version</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Version of the media graph topology. When the graph is
- created, this field starts with zero. Every time a graph
- element is added or removed, this field is
- incremented.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>num_entities</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Number of entities in the graph</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>ptr_entities</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>A pointer to a memory area where the entities array
- will be stored, converted to a 64-bits integer.
- It can be zero. if zero, the ioctl won't store the
- entities. It will just update
- <constant>num_entities</constant></entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>num_interfaces</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Number of interfaces in the graph</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>ptr_interfaces</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>A pointer to a memory area where the interfaces array
- will be stored, converted to a 64-bits integer.
- It can be zero. if zero, the ioctl won't store the
- interfaces. It will just update
- <constant>num_interfaces</constant></entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>num_pads</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Total number of pads in the graph</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>ptr_pads</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>A pointer to a memory area where the pads array
- will be stored, converted to a 64-bits integer.
- It can be zero. if zero, the ioctl won't store the
- pads. It will just update
- <constant>num_pads</constant></entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>num_links</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Total number of data and interface links in the graph</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>ptr_links</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>A pointer to a memory area where the links array
- will be stored, converted to a 64-bits integer.
- It can be zero. if zero, the ioctl won't store the
- links. It will just update
- <constant>num_links</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-v2-entity">
- <title>struct <structname>media_v2_entity</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Unique ID for the entity.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>name</structfield>[64]</entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity name as an UTF-8 NULL-terminated string.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>function</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Entity main function, see <xref linkend="media-entity-type" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[12]</entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set this array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-v2-interface">
- <title>struct <structname>media_v2_interface</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Unique ID for the interface.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>intf_type</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Interface type, see <xref linkend="media-intf-type" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Interface flags. Currently unused.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[9]</entry>
- <entry></entry>
- <entry></entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set this array to zero.</entry>
- </row>
- <row>
- <entry>struct media_v2_intf_devnode</entry>
- <entry><structfield>devnode</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Used only for device node interfaces. See <xref linkend="media-v2-intf-devnode" /> for details..</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-v2-intf-devnode">
- <title>struct <structname>media_v2_interface</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>major</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Device node major number.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>minor</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Device node minor number.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-v2-pad">
- <title>struct <structname>media_v2_pad</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Unique ID for the pad.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>entity_id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Unique ID for the entity where this pad belongs.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[9]</entry>
- <entry></entry>
- <entry></entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set this array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="media-v2-link">
- <title>struct <structname>media_v2_pad</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Unique ID for the pad.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>source_id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>
- <para>On pad to pad links: unique ID for the source pad.</para>
- <para>On interface to entity links: unique ID for the interface.</para>
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sink_id</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>
- <para>On pad to pad links: unique ID for the sink pad.</para>
- <para>On interface to entity links: unique ID for the entity.</para>
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[5]</entry>
- <entry></entry>
- <entry></entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set this array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>ENOSPC</errorcode></term>
- <listitem>
- <para>This is returned when either one or more of the num_entities,
- num_interfaces, num_links or num_pads are non-zero and are smaller
- than the actual number of elements inside the graph. This may happen
- if the <constant>topology_version</constant> changed when compared
- to the last time this ioctl was called. Userspace should usually
- free the area for the pointers, zero the struct elements and call
- this ioctl again.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-ioc-setup-link.xml b/Documentation/DocBook/media/v4l/media-ioc-setup-link.xml
deleted file mode 100644
index fc2e522ee65a..000000000000
--- a/Documentation/DocBook/media/v4l/media-ioc-setup-link.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<refentry id="media-ioc-setup-link">
- <refmeta>
- <refentrytitle>ioctl MEDIA_IOC_SETUP_LINK</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>MEDIA_IOC_SETUP_LINK</refname>
- <refpurpose>Modify the properties of a link</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 media_link_desc *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Arguments</title>
-
- <variablelist>
- <varlistentry>
- <term><parameter>fd</parameter></term>
- <listitem>
- <para>File descriptor returned by
- <link linkend='media-func-open'><function>open()</function></link>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>request</parameter></term>
- <listitem>
- <para>MEDIA_IOC_SETUP_LINK</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To change link properties applications fill a &media-link-desc; with
- link identification information (source and sink pad) and the new requested
- link flags. They then call the MEDIA_IOC_SETUP_LINK ioctl with a pointer to
- that structure.</para>
- <para>The only configurable property is the <constant>ENABLED</constant>
- link flag to enable/disable a link. Links marked with the
- <constant>IMMUTABLE</constant> link flag can not be enabled or disabled.
- </para>
- <para>Link configuration has no side effect on other links. If an enabled
- link at the sink pad prevents the link from being enabled, the driver
- returns with an &EBUSY;.</para>
- <para>Only links marked with the <constant>DYNAMIC</constant> link flag can
- be enabled/disabled while streaming media data. Attempting to enable or
- disable a streaming non-dynamic link will return an &EBUSY;.</para>
- <para>If the specified link can't be found the driver returns with an
- &EINVAL;.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &media-link-desc; references a non-existing link, or the
- link is immutable and an attempt to modify its configuration was made.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml
deleted file mode 100644
index 95aa1f9c836a..000000000000
--- a/Documentation/DocBook/media/v4l/media-types.xml
+++ /dev/null
@@ -1,379 +0,0 @@
-<section id="media-controller-types">
-<title>Types and flags used to represent the media graph elements</title>
-
- <table frame="none" pgwide="1" id="media-entity-type">
- <title>Media entity types</title>
- <tgroup cols="2">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <tbody valign="top">
- <row>
- <entry><constant>MEDIA_ENT_F_UNKNOWN</constant> and <constant>MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN</constant></entry>
- <entry>Unknown entity. That generally indicates that
- a driver didn't initialize properly the entity, with is a Kernel bug</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IO_V4L</constant></entry>
- <entry>Data streaming input and/or output entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IO_VBI</constant></entry>
- <entry>V4L VBI streaming input or output entity</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IO_SWRADIO</constant></entry>
- <entry>V4L Software Digital Radio (SDR) streaming input or output entity</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IO_DTV</constant></entry>
- <entry>DVB Digital TV streaming input or output entity</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_DTV_DEMOD</constant></entry>
- <entry>Digital TV demodulator entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_TS_DEMUX</constant></entry>
- <entry>MPEG Transport stream demux entity. Could be implemented on hardware or in Kernelspace by the Linux DVB subsystem.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_DTV_CA</constant></entry>
- <entry>Digital TV Conditional Access module (CAM) entity</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_DTV_NET_DECAP</constant></entry>
- <entry>Digital TV network ULE/MLE desencapsulation entity. Could be implemented on hardware or in Kernelspace</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_CONN_RF</constant></entry>
- <entry>Connector for a Radio Frequency (RF) signal.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_CONN_SVIDEO</constant></entry>
- <entry>Connector for a S-Video signal.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_CONN_COMPOSITE</constant></entry>
- <entry>Connector for a RGB composite signal.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_CAM_SENSOR</constant></entry>
- <entry>Camera video sensor entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_FLASH</constant></entry>
- <entry>Flash controller entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_LENS</constant></entry>
- <entry>Lens controller entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_ATV_DECODER</constant></entry>
- <entry>Analog video decoder, the basic function of the video decoder
- is to accept analogue video from a wide variety of sources such as
- broadcast, DVD players, cameras and video cassette recorders, in
- either NTSC, PAL, SECAM or HD format, separating the stream
- into its component parts, luminance and chrominance, and output
- it in some digital video standard, with appropriate timing
- signals.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_TUNER</constant></entry>
- <entry>Digital TV, analog TV, radio and/or software radio tuner,
- with consists on a PLL tuning stage that converts radio
- frequency (RF) signal into an Intermediate Frequency (IF).
- Modern tuners have internally IF-PLL decoders for audio
- and video, but older models have those stages implemented
- on separate entities.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IF_VID_DECODER</constant></entry>
- <entry>IF-PLL video decoder. It receives the IF from a PLL
- and decodes the analog TV video signal. This is commonly
- found on some very old analog tuners, like Philips MK3
- designs. They all contain a tda9887 (or some software
- compatible similar chip, like tda9885). Those devices
- use a different I2C address than the tuner PLL.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_IF_AUD_DECODER</constant></entry>
- <entry>IF-PLL sound decoder. It receives the IF from a PLL
- and decodes the analog TV audio signal. This is commonly
- found on some very old analog hardware, like Micronas
- msp3400, Philips tda9840, tda985x, etc. Those devices
- use a different I2C address than the tuner PLL and
- should be controlled together with the IF-PLL video
- decoder.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_AUDIO_CAPTURE</constant></entry>
- <entry>Audio Capture Function Entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_AUDIO_PLAYBACK</constant></entry>
- <entry>Audio Playback Function Entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_AUDIO_MIXER</constant></entry>
- <entry>Audio Mixer Function Entity.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_COMPOSER</constant></entry>
- <entry>Video composer (blender). An entity capable of video
- composing must have at least two sink pads and one source
- pad, and composes input video frames onto output video
- frames. Composition can be performed using alpha blending,
- color keying, raster operations (ROP), stitching or any other
- means.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER</constant></entry>
- <entry>Video pixel formatter. An entity capable of pixel formatting
- must have at least one sink pad and one source pad. Read
- pixel formatters read pixels from memory and perform a subset
- of unpacking, cropping, color keying, alpha multiplication
- and pixel encoding conversion. Write pixel formatters perform
- a subset of dithering, pixel encoding conversion and packing
- and write pixels to memory.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_PIXEL_ENC_CONV</constant></entry>
- <entry>Video pixel encoding converter. An entity capable of pixel
- enconding conversion must have at least one sink pad and one
- source pad, and convert the encoding of pixels received on
- its sink pad(s) to a different encoding output on its source
- pad(s). Pixel encoding conversion includes but isn't limited
- to RGB to/from HSV, RGB to/from YUV and CFA (Bayer) to RGB
- conversions.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_LUT</constant></entry>
- <entry>Video look-up table. An entity capable of video lookup table
- processing must have one sink pad and one source pad. It uses
- the values of the pixels received on its sink pad to look up
- entries in internal tables and output them on its source pad.
- The lookup processing can be performed on all components
- separately or combine them for multi-dimensional table
- lookups.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_SCALER</constant></entry>
- <entry>Video scaler. An entity capable of video scaling must have
- at least one sink pad and one source pad, and scale the
- video frame(s) received on its sink pad(s) to a different
- resolution output on its source pad(s). The range of
- supported scaling ratios is entity-specific and can differ
- between the horizontal and vertical directions (in particular
- scaling can be supported in one direction only). Binning and
- skipping are considered as scaling.
- </entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_F_PROC_VIDEO_STATISTICS</constant></entry>
- <entry>Video statistics computation (histogram, 3A, ...). An entity
- capable of statistics computation must have one sink pad and
- one source pad. It computes statistics over the frames
- received on its sink pad and outputs the statistics data on
- its source pad.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="media-entity-flag">
- <title>Media entity flags</title>
- <tgroup cols="2">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <tbody valign="top">
- <row>
- <entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry>
- <entry>Default entity for its type. Used to discover the default
- audio, VBI and video devices, the default camera sensor, ...</entry>
- </row>
- <row>
- <entry><constant>MEDIA_ENT_FL_CONNECTOR</constant></entry>
- <entry>The entity represents a data conector</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="media-intf-type">
- <title>Media interface types</title>
- <tgroup cols="3">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <colspec colname="c3"/>
- <tbody valign="top">
- <row>
- <entry><constant>MEDIA_INTF_T_DVB_FE</constant></entry>
- <entry>Device node interface for the Digital TV frontend</entry>
- <entry>typically, /dev/dvb/adapter?/frontend?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_DVB_DEMUX</constant></entry>
- <entry>Device node interface for the Digital TV demux</entry>
- <entry>typically, /dev/dvb/adapter?/demux?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_DVB_DVR</constant></entry>
- <entry>Device node interface for the Digital TV DVR</entry>
- <entry>typically, /dev/dvb/adapter?/dvr?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_DVB_CA</constant></entry>
- <entry>Device node interface for the Digital TV Conditional Access</entry>
- <entry>typically, /dev/dvb/adapter?/ca?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_DVB_FE</constant></entry>
- <entry>Device node interface for the Digital TV network control</entry>
- <entry>typically, /dev/dvb/adapter?/net?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_V4L_VIDEO</constant></entry>
- <entry>Device node interface for video (V4L)</entry>
- <entry>typically, /dev/video?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_V4L_VBI</constant></entry>
- <entry>Device node interface for VBI (V4L)</entry>
- <entry>typically, /dev/vbi?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_V4L_RADIO</constant></entry>
- <entry>Device node interface for radio (V4L)</entry>
- <entry>typically, /dev/vbi?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_V4L_SUBDEV</constant></entry>
- <entry>Device node interface for a V4L subdevice</entry>
- <entry>typically, /dev/v4l-subdev?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_V4L_SWRADIO</constant></entry>
- <entry>Device node interface for Software Defined Radio (V4L)</entry>
- <entry>typically, /dev/swradio?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_PCM_CAPTURE</constant></entry>
- <entry>Device node interface for ALSA PCM Capture</entry>
- <entry>typically, /dev/snd/pcmC?D?c</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_PCM_PLAYBACK</constant></entry>
- <entry>Device node interface for ALSA PCM Playback</entry>
- <entry>typically, /dev/snd/pcmC?D?p</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_CONTROL</constant></entry>
- <entry>Device node interface for ALSA Control</entry>
- <entry>typically, /dev/snd/controlC?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_COMPRESS</constant></entry>
- <entry>Device node interface for ALSA Compress</entry>
- <entry>typically, /dev/snd/compr?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_RAWMIDI</constant></entry>
- <entry>Device node interface for ALSA Raw MIDI</entry>
- <entry>typically, /dev/snd/midi?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_HWDEP</constant></entry>
- <entry>Device node interface for ALSA Hardware Dependent</entry>
- <entry>typically, /dev/snd/hwC?D?</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_SEQUENCER</constant></entry>
- <entry>Device node interface for ALSA Sequencer</entry>
- <entry>typically, /dev/snd/seq</entry>
- </row>
- <row>
- <entry><constant>MEDIA_INTF_T_ALSA_TIMER</constant></entry>
- <entry>Device node interface for ALSA Timer</entry>
- <entry>typically, /dev/snd/timer</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="media-pad-flag">
- <title>Media pad flags</title>
- <tgroup cols="2">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <tbody valign="top">
- <row>
- <entry><constant>MEDIA_PAD_FL_SINK</constant></entry>
- <entry>Input pad, relative to the entity. Input pads sink data and
- are targets of links.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_PAD_FL_SOURCE</constant></entry>
- <entry>Output pad, relative to the entity. Output pads source data
- and are origins of links.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_PAD_FL_MUST_CONNECT</constant></entry>
- <entry>If this flag is set and the pad is linked to any other
- pad, then at least one of those links must be enabled for the
- entity to be able to stream. There could be temporary reasons
- (e.g. device configuration dependent) for the pad to need
- enabled links even when this flag isn't set; the absence of the
- flag doesn't imply there is none.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>One and only one of <constant>MEDIA_PAD_FL_SINK</constant> and
- <constant>MEDIA_PAD_FL_SOURCE</constant> must be set for every pad.</para>
-
- <table frame="none" pgwide="1" id="media-link-flag">
- <title>Media link flags</title>
- <tgroup cols="2">
- <colspec colname="c1"/>
- <colspec colname="c2"/>
- <tbody valign="top">
- <row>
- <entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry>
- <entry>The link is enabled and can be used to transfer media data.
- When two or more links target a sink pad, only one of them can be
- enabled at a time.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry>
- <entry>The link enabled state can't be modified at runtime. An
- immutable link is always enabled.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry>
- <entry>The link enabled state can be modified during streaming. This
- flag is set by drivers and is read-only for applications.</entry>
- </row>
- <row>
- <entry><constant>MEDIA_LNK_FL_LINK_TYPE</constant></entry>
- <entry><para>This is a bitmask that defines the type of the link.
- Currently, two types of links are supported:</para>
- <para><constant>MEDIA_LNK_FL_DATA_LINK</constant>
- if the link is between two pads</para>
- <para><constant>MEDIA_LNK_FL_INTERFACE_LINK</constant>
- if the link is between an interface and an entity</para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
-</section>
diff --git a/Documentation/DocBook/media/v4l/pipeline.pdf b/Documentation/DocBook/media/v4l/pipeline.pdf
deleted file mode 100644
index ee3e37f04b6a..000000000000
--- a/Documentation/DocBook/media/v4l/pipeline.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/pixfmt-grey.xml b/Documentation/DocBook/media/v4l/pixfmt-grey.xml
deleted file mode 100644
index bee970d3f76d..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-grey.xml
+++ /dev/null
@@ -1,62 +0,0 @@
- <refentry id="V4L2-PIX-FMT-GREY">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_GREY ('GREY')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_GREY</constant></refname>
- <refpurpose>Grey-scale image</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image. It is really a degenerate
-Y'CbCr format which simply contains no Cb or Cr data.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_GREY</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-m420.xml b/Documentation/DocBook/media/v4l/pixfmt-m420.xml
deleted file mode 100644
index aadae92c5d04..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-m420.xml
+++ /dev/null
@@ -1,139 +0,0 @@
- <refentry id="V4L2-PIX-FMT-M420">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_M420 ('M420')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_M420</constant></refname>
- <refpurpose>Format with &frac12; horizontal and vertical chroma
- resolution, also known as YUV 4:2:0. Hybrid plane line-interleaved
- layout.</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>M420 is a YUV format with &frac12; horizontal and vertical chroma
- subsampling (YUV 4:2:0). Pixels are organized as interleaved luma and
- chroma planes. Two lines of luma data are followed by one line of chroma
- data.</para>
- <para>The luma plane has one byte per pixel. The chroma plane contains
- interleaved CbCr pixels subsampled by &frac12; in the horizontal and
- vertical directions. Each CbCr pair belongs to four pixels. For example,
-Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.</para>
-
- <para>All line lengths are identical: if the Y lines include pad bytes
- so do the CbCr lines.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_M420</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12.xml
deleted file mode 100644
index 84dd4fd7cb80..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv12.xml
+++ /dev/null
@@ -1,143 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV12 ('NV12'), V4L2_PIX_FMT_NV21 ('NV21')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV12"><constant>V4L2_PIX_FMT_NV12</constant></refname>
- <refname id="V4L2-PIX-FMT-NV21"><constant>V4L2_PIX_FMT_NV21</constant></refname>
- <refpurpose>Formats with &frac12; horizontal and vertical
-chroma resolution, also known as YUV 4:2:0. One luminance and one
-chrominance plane with alternating chroma samples as opposed to
-<constant>V4L2_PIX_FMT_YVU420</constant></refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These are two-plane versions of the YUV 4:2:0 format.
-The three components are separated into two sub-images or planes. The
-Y plane is first. The Y plane has one byte per pixel. For
-<constant>V4L2_PIX_FMT_NV12</constant>, a combined CbCr plane
-immediately follows the Y plane in memory. The CbCr plane is the same
-width, in bytes, as the Y plane (and of the image), but is half as
-tall in pixels. Each CbCr pair belongs to four pixels. For example,
-Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
-<constant>V4L2_PIX_FMT_NV21</constant> is the same except the Cb and
-Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
-
- <para>If the Y plane has pad bytes after each row, then the
-CbCr plane has as many pad bytes after its rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_NV12</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
deleted file mode 100644
index f3a3d459fcdf..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
+++ /dev/null
@@ -1,153 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12'), V4L2_PIX_FMT_NV21M ('NM21'), V4L2_PIX_FMT_NV12MT_16X16</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV12M"><constant>V4L2_PIX_FMT_NV12M</constant></refname>
- <refname id="V4L2-PIX-FMT-NV21M"><constant>V4L2_PIX_FMT_NV21M</constant></refname>
- <refname id="V4L2-PIX-FMT-NV12MT-16X16"><constant>V4L2_PIX_FMT_NV12MT_16X16</constant></refname>
- <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> and <constant>V4L2_PIX_FMT_NV21</constant> with planes
- non contiguous in memory. </refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a multi-planar, two-plane version of the YUV 4:2:0 format.
-The three components are separated into two sub-images or planes.
-<constant>V4L2_PIX_FMT_NV12M</constant> differs from <constant>V4L2_PIX_FMT_NV12
-</constant> in that the two planes are non-contiguous in memory, i.e. the chroma
-plane do not necessarily immediately follows the luma plane.
-The luminance data occupies the first plane. The Y plane has one byte per pixel.
-In the second plane there is a chrominance data with alternating chroma samples.
-The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
-but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
-Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
-Y'<subscript>10</subscript>, Y'<subscript>11</subscript>.
-<constant>V4L2_PIX_FMT_NV12MT_16X16</constant> is the tiled version of
-<constant>V4L2_PIX_FMT_NV12M</constant> with 16x16 macroblock tiles. Here pixels
-are arranged in 16x16 2D tiles and tiles are arranged in linear order in memory.
-<constant>V4L2_PIX_FMT_NV21M</constant> is the same as <constant>V4L2_PIX_FMT_NV12M</constant>
-except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
-
- <para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
-used only in drivers and applications that support the multi-planar API,
-described in <xref linkend="planar-apis"/>. </para>
-
- <para>If the Y plane has pad bytes after each row, then the
-CbCr plane has as many pad bytes after its rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_NV12M</constant> 4 &times; 4 pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start0&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;4:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml
deleted file mode 100644
index 8a70a1707b7a..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv12mt.xml
+++ /dev/null
@@ -1,66 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV12MT ('TM12')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV12MT"><constant>V4L2_PIX_FMT_NV12MT
-</constant></refname>
- <refpurpose>Formats with &frac12; horizontal and vertical
-chroma resolution. This format has two planes - one for luminance and one for
-chrominance. Chroma samples are interleaved. The difference to
-<constant>V4L2_PIX_FMT_NV12</constant> is the memory layout. Pixels are
-grouped in macroblocks of 64x32 size. The order of macroblocks in memory is
-also not standard.
- </refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is the two-plane versions of the YUV 4:2:0 format where data
-is grouped into 64x32 macroblocks. The three components are separated into two
-sub-images or planes. The Y plane has one byte per pixel and pixels are grouped
-into 64x32 macroblocks. The CbCr plane has the same width, in bytes, as the Y
-plane (and the image), but is half as tall in pixels. The chroma plane is also
-grouped into 64x32 macroblocks.</para>
- <para>Width of the buffer has to be aligned to the multiple of 128, and
-height alignment is 32. Every four adjacent buffers - two horizontally and two
-vertically are grouped together and are located in memory in Z or flipped Z
-order. </para>
- <para>Layout of macroblocks in memory is presented in the following
-figure.</para>
- <para><figure id="nv12mt">
- <title><constant>V4L2_PIX_FMT_NV12MT</constant> macroblock Z shape
-memory layout</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="nv12mt.gif" format="GIF" />
- </imageobject>
- </mediaobject>
- </figure>
- The requirement that width is multiple of 128 is implemented because,
-the Z shape cannot be cut in half horizontally. In case the vertical resolution
-of macroblocks is odd then the last row of macroblocks is arranged in a linear
-order. </para>
- <para>In case of chroma the layout is identical. Cb and Cr samples are
-interleaved. Height of the buffer is aligned to 32.
- </para>
- <example>
- <title>Memory layout of macroblocks in <constant>V4L2_PIX_FMT_NV12
-</constant> format pixel image - extreme case</title>
- <para>
- <figure id="nv12mt_ex">
- <title>Example <constant>V4L2_PIX_FMT_NV12MT</constant> memory
-layout of macroblocks</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="nv12mt_example.gif" format="GIF" />
- </imageobject>
- </mediaobject>
- </figure>
- Memory layout of macroblocks of <constant>V4L2_PIX_FMT_NV12MT
-</constant> format in most extreme case.
- </para>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv16.xml b/Documentation/DocBook/media/v4l/pixfmt-nv16.xml
deleted file mode 100644
index 8ae1f8a810d0..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv16.xml
+++ /dev/null
@@ -1,166 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV16 ('NV16'), V4L2_PIX_FMT_NV61 ('NV61')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV16"><constant>V4L2_PIX_FMT_NV16</constant></refname>
- <refname id="V4L2-PIX-FMT-NV61"><constant>V4L2_PIX_FMT_NV61</constant></refname>
- <refpurpose>Formats with &frac12; horizontal
-chroma resolution, also known as YUV 4:2:2. One luminance and one
-chrominance plane with alternating chroma samples as opposed to
-<constant>V4L2_PIX_FMT_YVU420</constant></refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These are two-plane versions of the YUV 4:2:2 format.
-The three components are separated into two sub-images or planes. The
-Y plane is first. The Y plane has one byte per pixel. For
-<constant>V4L2_PIX_FMT_NV16</constant>, a combined CbCr plane
-immediately follows the Y plane in memory. The CbCr plane is the same
-width and height, in bytes, as the Y plane (and of the image).
-Each CbCr pair belongs to two pixels. For example,
-Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>.
-<constant>V4L2_PIX_FMT_NV61</constant> is the same except the Cb and
-Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
-
- <para>If the Y plane has pad bytes after each row, then the
-CbCr plane has as many pad bytes after its rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_NV16</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;28:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml
deleted file mode 100644
index fb2b5e35d665..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv16m.xml
+++ /dev/null
@@ -1,170 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV16M ('NM16'), V4L2_PIX_FMT_NV61M ('NM61')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV16M"><constant>V4L2_PIX_FMT_NV16M</constant></refname>
- <refname id="V4L2-PIX-FMT-NV61M"><constant>V4L2_PIX_FMT_NV61M</constant></refname>
- <refpurpose>Variation of <constant>V4L2_PIX_FMT_NV16</constant> and <constant>V4L2_PIX_FMT_NV61</constant> with planes
- non contiguous in memory. </refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a multi-planar, two-plane version of the YUV 4:2:2 format.
-The three components are separated into two sub-images or planes.
-<constant>V4L2_PIX_FMT_NV16M</constant> differs from <constant>V4L2_PIX_FMT_NV16
-</constant> in that the two planes are non-contiguous in memory, i.e. the chroma
-plane does not necessarily immediately follow the luma plane.
-The luminance data occupies the first plane. The Y plane has one byte per pixel.
-In the second plane there is chrominance data with alternating chroma samples.
-The CbCr plane is the same width and height, in bytes, as the Y plane.
-Each CbCr pair belongs to two pixels. For example,
-Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
-Y'<subscript>00</subscript>, Y'<subscript>01</subscript>.
-<constant>V4L2_PIX_FMT_NV61M</constant> is the same as <constant>V4L2_PIX_FMT_NV16M</constant>
-except the Cb and Cr bytes are swapped, the CrCb plane starts with a Cr byte.</para>
-
- <para><constant>V4L2_PIX_FMT_NV16M</constant> and
-<constant>V4L2_PIX_FMT_NV61M</constant> are intended to be used only in drivers
-and applications that support the multi-planar API, described in
-<xref linkend="planar-apis"/>. </para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_NV16M</constant> 4 &times; 4 pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start0&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>02</subscript></entry>
- <entry>Cr<subscript>02</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;4:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>12</subscript></entry>
- <entry>Cr<subscript>12</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;8:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cb<subscript>22</subscript></entry>
- <entry>Cr<subscript>22</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;12:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cb<subscript>32</subscript></entry>
- <entry>Cr<subscript>32</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv24.xml b/Documentation/DocBook/media/v4l/pixfmt-nv24.xml
deleted file mode 100644
index fb255f2ca9dd..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-nv24.xml
+++ /dev/null
@@ -1,121 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV24 ('NV24'), V4L2_PIX_FMT_NV42 ('NV42')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-NV24"><constant>V4L2_PIX_FMT_NV24</constant></refname>
- <refname id="V4L2-PIX-FMT-NV42"><constant>V4L2_PIX_FMT_NV42</constant></refname>
- <refpurpose>Formats with full horizontal and vertical
-chroma resolutions, also known as YUV 4:4:4. One luminance and one
-chrominance plane with alternating chroma samples as opposed to
-<constant>V4L2_PIX_FMT_YVU420</constant></refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These are two-plane versions of the YUV 4:4:4 format. The three
- components are separated into two sub-images or planes. The Y plane is
- first, with each Y sample stored in one byte per pixel. For
- <constant>V4L2_PIX_FMT_NV24</constant>, a combined CbCr plane
- immediately follows the Y plane in memory. The CbCr plane has the same
- width and height, in pixels, as the Y plane (and the image). Each line
- contains one CbCr pair per pixel, with each Cb and Cr sample stored in
- one byte. <constant>V4L2_PIX_FMT_NV42</constant> is the same except that
- the Cb and Cr samples are swapped, the CrCb plane starts with a Cr
- sample.</para>
-
- <para>If the Y plane has pad bytes after each row, then the CbCr plane
- has twice as many pad bytes after its rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_NV24</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Cb<subscript>02</subscript></entry>
- <entry>Cr<subscript>02</subscript></entry>
- <entry>Cb<subscript>03</subscript></entry>
- <entry>Cr<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Cb<subscript>12</subscript></entry>
- <entry>Cr<subscript>12</subscript></entry>
- <entry>Cb<subscript>13</subscript></entry>
- <entry>Cr<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;32:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Cb<subscript>22</subscript></entry>
- <entry>Cr<subscript>22</subscript></entry>
- <entry>Cb<subscript>23</subscript></entry>
- <entry>Cr<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;40:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Cb<subscript>32</subscript></entry>
- <entry>Cr<subscript>32</subscript></entry>
- <entry>Cb<subscript>33</subscript></entry>
- <entry>Cr<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
deleted file mode 100644
index b60fb935b91b..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+++ /dev/null
@@ -1,937 +0,0 @@
-<refentry id="packed-rgb">
- <refmeta>
- <refentrytitle>Packed RGB formats</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>Packed RGB formats</refname>
- <refpurpose>Packed RGB formats</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These formats are designed to match the pixel formats of
-typical PC graphics frame buffers. They occupy 8, 16, 24 or 32 bits
-per pixel. These are all packed-pixel formats, meaning all the data
-for a pixel lie next to each other in memory.</para>
-
- <table pgwide="1" frame="none" id="rgb-formats">
- <title>Packed RGB Image Formats</title>
- <tgroup cols="37" align="center">
- <colspec colname="id" align="left" />
- <colspec colname="fourcc" />
- <colspec colname="bit" />
-
- <colspec colnum="4" colname="b07" align="center" />
- <colspec colnum="5" colname="b06" align="center" />
- <colspec colnum="6" colname="b05" align="center" />
- <colspec colnum="7" colname="b04" align="center" />
- <colspec colnum="8" colname="b03" align="center" />
- <colspec colnum="9" colname="b02" align="center" />
- <colspec colnum="10" colname="b01" align="center" />
- <colspec colnum="11" colname="b00" align="center" />
-
- <colspec colnum="13" colname="b17" align="center" />
- <colspec colnum="14" colname="b16" align="center" />
- <colspec colnum="15" colname="b15" align="center" />
- <colspec colnum="16" colname="b14" align="center" />
- <colspec colnum="17" colname="b13" align="center" />
- <colspec colnum="18" colname="b12" align="center" />
- <colspec colnum="19" colname="b11" align="center" />
- <colspec colnum="20" colname="b10" align="center" />
-
- <colspec colnum="22" colname="b27" align="center" />
- <colspec colnum="23" colname="b26" align="center" />
- <colspec colnum="24" colname="b25" align="center" />
- <colspec colnum="25" colname="b24" align="center" />
- <colspec colnum="26" colname="b23" align="center" />
- <colspec colnum="27" colname="b22" align="center" />
- <colspec colnum="28" colname="b21" align="center" />
- <colspec colnum="29" colname="b20" align="center" />
-
- <colspec colnum="31" colname="b37" align="center" />
- <colspec colnum="32" colname="b36" align="center" />
- <colspec colnum="33" colname="b35" align="center" />
- <colspec colnum="34" colname="b34" align="center" />
- <colspec colnum="35" colname="b33" align="center" />
- <colspec colnum="36" colname="b32" align="center" />
- <colspec colnum="37" colname="b31" align="center" />
- <colspec colnum="38" colname="b30" align="center" />
-
- <spanspec namest="b07" nameend="b00" spanname="b0" />
- <spanspec namest="b17" nameend="b10" spanname="b1" />
- <spanspec namest="b27" nameend="b20" spanname="b2" />
- <spanspec namest="b37" nameend="b30" spanname="b3" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>&nbsp;</entry>
- <entry spanname="b0">Byte&nbsp;0 in memory</entry>
- <entry spanname="b1">Byte&nbsp;1</entry>
- <entry spanname="b2">Byte&nbsp;2</entry>
- <entry spanname="b3">Byte&nbsp;3</entry>
- </row>
- <row>
- <entry>&nbsp;</entry>
- <entry>&nbsp;</entry>
- <entry>Bit</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="V4L2-PIX-FMT-RGB332">
- <entry><constant>V4L2_PIX_FMT_RGB332</constant></entry>
- <entry>'RGB1'</entry>
- <entry></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-ARGB444">
- <entry><constant>V4L2_PIX_FMT_ARGB444</constant></entry>
- <entry>'AR12'</entry>
- <entry></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-XRGB444">
- <entry><constant>V4L2_PIX_FMT_XRGB444</constant></entry>
- <entry>'XR12'</entry>
- <entry></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-ARGB555">
- <entry><constant>V4L2_PIX_FMT_ARGB555</constant></entry>
- <entry>'AR15'</entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-XRGB555">
- <entry><constant>V4L2_PIX_FMT_XRGB555</constant></entry>
- <entry>'XR15'</entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB565">
- <entry><constant>V4L2_PIX_FMT_RGB565</constant></entry>
- <entry>'RGBP'</entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-ARGB555X">
- <entry><constant>V4L2_PIX_FMT_ARGB555X</constant></entry>
- <entry>'AR15' | (1 &lt;&lt; 31)</entry>
- <entry></entry>
- <entry>a</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-XRGB555X">
- <entry><constant>V4L2_PIX_FMT_XRGB555X</constant></entry>
- <entry>'XR15' | (1 &lt;&lt; 31)</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB565X">
- <entry><constant>V4L2_PIX_FMT_RGB565X</constant></entry>
- <entry>'RGBR'</entry>
- <entry></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-BGR24">
- <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
- <entry>'BGR3'</entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB24">
- <entry><constant>V4L2_PIX_FMT_RGB24</constant></entry>
- <entry>'RGB3'</entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-BGR666">
- <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
- <entry>'BGRH'</entry>
- <entry></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- </row>
- <row id="V4L2-PIX-FMT-ABGR32">
- <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
- <entry>'AR24'</entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-XBGR32">
- <entry><constant>V4L2_PIX_FMT_XBGR32</constant></entry>
- <entry>'XR24'</entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- </row>
- <row id="V4L2-PIX-FMT-ARGB32">
- <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry>
- <entry>'BA24'</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-XRGB32">
- <entry><constant>V4L2_PIX_FMT_XRGB32</constant></entry>
- <entry>'BX24'</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Bit 7 is the most significant bit.</para>
-
- <para>The usage and value of the alpha bits (a) in the ARGB and ABGR formats
- (collectively referred to as alpha formats) depend on the device type and
- hardware operation. <link linkend="capture">Capture</link> devices
- (including capture queues of mem-to-mem devices) fill the alpha component in
- memory. When the device outputs an alpha channel the alpha component will
- have a meaningful value. Otherwise, when the device doesn't output an alpha
- channel but can set the alpha bit to a user-configurable value, the <link
- linkend="v4l2-alpha-component"><constant>V4L2_CID_ALPHA_COMPONENT</constant>
- </link> control is used to specify that alpha value, and the alpha component
- of all pixels will be set to the value specified by that control. Otherwise
- a corresponding format without an alpha component (XRGB or XBGR) must be
- used instead of an alpha format.</para>
-
- <para><link linkend="output">Output</link> devices (including output queues
- of mem-to-mem devices and <link linkend="osd">video output overlay</link>
- devices) read the alpha component from memory. When the device processes the
- alpha channel the alpha component must be filled with meaningful values by
- applications. Otherwise a corresponding format without an alpha component
- (XRGB or XBGR) must be used instead of an alpha format.</para>
-
- <para>The XRGB and XBGR formats contain undefined bits (-). Applications,
- devices and drivers must ignore those bits, for both <link
- linkend="capture">capture</link> and <link linkend="output">output</link>
- devices.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_BGR24</constant> 4 &times; 4 pixel
-image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="13" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00</subscript></entry>
- <entry>G<subscript>00</subscript></entry>
- <entry>R<subscript>00</subscript></entry>
- <entry>B<subscript>01</subscript></entry>
- <entry>G<subscript>01</subscript></entry>
- <entry>R<subscript>01</subscript></entry>
- <entry>B<subscript>02</subscript></entry>
- <entry>G<subscript>02</subscript></entry>
- <entry>R<subscript>02</subscript></entry>
- <entry>B<subscript>03</subscript></entry>
- <entry>G<subscript>03</subscript></entry>
- <entry>R<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>B<subscript>10</subscript></entry>
- <entry>G<subscript>10</subscript></entry>
- <entry>R<subscript>10</subscript></entry>
- <entry>B<subscript>11</subscript></entry>
- <entry>G<subscript>11</subscript></entry>
- <entry>R<subscript>11</subscript></entry>
- <entry>B<subscript>12</subscript></entry>
- <entry>G<subscript>12</subscript></entry>
- <entry>R<subscript>12</subscript></entry>
- <entry>B<subscript>13</subscript></entry>
- <entry>G<subscript>13</subscript></entry>
- <entry>R<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>B<subscript>20</subscript></entry>
- <entry>G<subscript>20</subscript></entry>
- <entry>R<subscript>20</subscript></entry>
- <entry>B<subscript>21</subscript></entry>
- <entry>G<subscript>21</subscript></entry>
- <entry>R<subscript>21</subscript></entry>
- <entry>B<subscript>22</subscript></entry>
- <entry>G<subscript>22</subscript></entry>
- <entry>R<subscript>22</subscript></entry>
- <entry>B<subscript>23</subscript></entry>
- <entry>G<subscript>23</subscript></entry>
- <entry>R<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;36:</entry>
- <entry>B<subscript>30</subscript></entry>
- <entry>G<subscript>30</subscript></entry>
- <entry>R<subscript>30</subscript></entry>
- <entry>B<subscript>31</subscript></entry>
- <entry>G<subscript>31</subscript></entry>
- <entry>R<subscript>31</subscript></entry>
- <entry>B<subscript>32</subscript></entry>
- <entry>G<subscript>32</subscript></entry>
- <entry>R<subscript>32</subscript></entry>
- <entry>B<subscript>33</subscript></entry>
- <entry>G<subscript>33</subscript></entry>
- <entry>R<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
-
- <para>Formats defined in <xref linkend="rgb-formats-deprecated"/> are
- deprecated and must not be used by new drivers. They are documented here for
- reference. The meaning of their alpha bits (a) is ill-defined and
- interpreted as in either the corresponding ARGB or XRGB format, depending on
- the driver.</para>
-
- <table pgwide="1" frame="none" id="rgb-formats-deprecated">
- <title>Deprecated Packed RGB Image Formats</title>
- <tgroup cols="37" align="center">
- <colspec colname="id" align="left" />
- <colspec colname="fourcc" />
- <colspec colname="bit" />
-
- <colspec colnum="4" colname="b07" align="center" />
- <colspec colnum="5" colname="b06" align="center" />
- <colspec colnum="6" colname="b05" align="center" />
- <colspec colnum="7" colname="b04" align="center" />
- <colspec colnum="8" colname="b03" align="center" />
- <colspec colnum="9" colname="b02" align="center" />
- <colspec colnum="10" colname="b01" align="center" />
- <colspec colnum="11" colname="b00" align="center" />
-
- <colspec colnum="13" colname="b17" align="center" />
- <colspec colnum="14" colname="b16" align="center" />
- <colspec colnum="15" colname="b15" align="center" />
- <colspec colnum="16" colname="b14" align="center" />
- <colspec colnum="17" colname="b13" align="center" />
- <colspec colnum="18" colname="b12" align="center" />
- <colspec colnum="19" colname="b11" align="center" />
- <colspec colnum="20" colname="b10" align="center" />
-
- <colspec colnum="22" colname="b27" align="center" />
- <colspec colnum="23" colname="b26" align="center" />
- <colspec colnum="24" colname="b25" align="center" />
- <colspec colnum="25" colname="b24" align="center" />
- <colspec colnum="26" colname="b23" align="center" />
- <colspec colnum="27" colname="b22" align="center" />
- <colspec colnum="28" colname="b21" align="center" />
- <colspec colnum="29" colname="b20" align="center" />
-
- <colspec colnum="31" colname="b37" align="center" />
- <colspec colnum="32" colname="b36" align="center" />
- <colspec colnum="33" colname="b35" align="center" />
- <colspec colnum="34" colname="b34" align="center" />
- <colspec colnum="35" colname="b33" align="center" />
- <colspec colnum="36" colname="b32" align="center" />
- <colspec colnum="37" colname="b31" align="center" />
- <colspec colnum="38" colname="b30" align="center" />
-
- <spanspec namest="b07" nameend="b00" spanname="b0" />
- <spanspec namest="b17" nameend="b10" spanname="b1" />
- <spanspec namest="b27" nameend="b20" spanname="b2" />
- <spanspec namest="b37" nameend="b30" spanname="b3" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>&nbsp;</entry>
- <entry spanname="b0">Byte&nbsp;0 in memory</entry>
- <entry spanname="b1">Byte&nbsp;1</entry>
- <entry spanname="b2">Byte&nbsp;2</entry>
- <entry spanname="b3">Byte&nbsp;3</entry>
- </row>
- <row>
- <entry>&nbsp;</entry>
- <entry>&nbsp;</entry>
- <entry>Bit</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody>
- <row id="V4L2-PIX-FMT-RGB444">
- <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
- <entry>'R444'</entry>
- <entry></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB555">
- <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
- <entry>'RGBO'</entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB555X">
- <entry><constant>V4L2_PIX_FMT_RGB555X</constant></entry>
- <entry>'RGBQ'</entry>
- <entry></entry>
- <entry>a</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-BGR32">
- <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
- <entry>'BGR4'</entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- </row>
- <row id="V4L2-PIX-FMT-RGB32">
- <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
- <entry>'RGB4'</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>A test utility to determine which RGB formats a driver
-actually supports is available from the LinuxTV v4l-dvb repository.
-See &v4l-dvb; for access instructions.</para>
-
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml
deleted file mode 100644
index 33fa5a47a865..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-packed-yuv.xml
+++ /dev/null
@@ -1,236 +0,0 @@
-<refentry id="packed-yuv">
- <refmeta>
- <refentrytitle>Packed YUV formats</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>Packed YUV formats</refname>
- <refpurpose>Packed YUV formats</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>Similar to the packed RGB formats these formats store
-the Y, Cb and Cr component of each pixel in one 16 or 32 bit
-word.</para>
-
- <table pgwide="1" frame="none">
- <title>Packed YUV Image Formats</title>
- <tgroup cols="37" align="center">
- <colspec colname="id" align="left" />
- <colspec colname="fourcc" />
- <colspec colname="bit" />
-
- <colspec colnum="4" colname="b07" align="center" />
- <colspec colnum="5" colname="b06" align="center" />
- <colspec colnum="6" colname="b05" align="center" />
- <colspec colnum="7" colname="b04" align="center" />
- <colspec colnum="8" colname="b03" align="center" />
- <colspec colnum="9" colname="b02" align="center" />
- <colspec colnum="10" colname="b01" align="center" />
- <colspec colnum="11" colname="b00" align="center" />
-
- <colspec colnum="13" colname="b17" align="center" />
- <colspec colnum="14" colname="b16" align="center" />
- <colspec colnum="15" colname="b15" align="center" />
- <colspec colnum="16" colname="b14" align="center" />
- <colspec colnum="17" colname="b13" align="center" />
- <colspec colnum="18" colname="b12" align="center" />
- <colspec colnum="19" colname="b11" align="center" />
- <colspec colnum="20" colname="b10" align="center" />
-
- <colspec colnum="22" colname="b27" align="center" />
- <colspec colnum="23" colname="b26" align="center" />
- <colspec colnum="24" colname="b25" align="center" />
- <colspec colnum="25" colname="b24" align="center" />
- <colspec colnum="26" colname="b23" align="center" />
- <colspec colnum="27" colname="b22" align="center" />
- <colspec colnum="28" colname="b21" align="center" />
- <colspec colnum="29" colname="b20" align="center" />
-
- <colspec colnum="31" colname="b37" align="center" />
- <colspec colnum="32" colname="b36" align="center" />
- <colspec colnum="33" colname="b35" align="center" />
- <colspec colnum="34" colname="b34" align="center" />
- <colspec colnum="35" colname="b33" align="center" />
- <colspec colnum="36" colname="b32" align="center" />
- <colspec colnum="37" colname="b31" align="center" />
- <colspec colnum="38" colname="b30" align="center" />
-
- <spanspec namest="b07" nameend="b00" spanname="b0" />
- <spanspec namest="b17" nameend="b10" spanname="b1" />
- <spanspec namest="b27" nameend="b20" spanname="b2" />
- <spanspec namest="b37" nameend="b30" spanname="b3" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>&nbsp;</entry>
- <entry spanname="b0">Byte&nbsp;0 in memory</entry>
- <entry spanname="b1">Byte&nbsp;1</entry>
- <entry spanname="b2">Byte&nbsp;2</entry>
- <entry spanname="b3">Byte&nbsp;3</entry>
- </row>
- <row>
- <entry>&nbsp;</entry>
- <entry>&nbsp;</entry>
- <entry>Bit</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- <entry>&nbsp;</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="V4L2-PIX-FMT-YUV444">
- <entry><constant>V4L2_PIX_FMT_YUV444</constant></entry>
- <entry>'Y444'</entry>
- <entry></entry>
- <entry>Cb<subscript>3</subscript></entry>
- <entry>Cb<subscript>2</subscript></entry>
- <entry>Cb<subscript>1</subscript></entry>
- <entry>Cb<subscript>0</subscript></entry>
- <entry>Cr<subscript>3</subscript></entry>
- <entry>Cr<subscript>2</subscript></entry>
- <entry>Cr<subscript>1</subscript></entry>
- <entry>Cr<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>Y'<subscript>3</subscript></entry>
- <entry>Y'<subscript>2</subscript></entry>
- <entry>Y'<subscript>1</subscript></entry>
- <entry>Y'<subscript>0</subscript></entry>
- </row>
-
- <row id="V4L2-PIX-FMT-YUV555">
- <entry><constant>V4L2_PIX_FMT_YUV555</constant></entry>
- <entry>'YUVO'</entry>
- <entry></entry>
- <entry>Cb<subscript>2</subscript></entry>
- <entry>Cb<subscript>1</subscript></entry>
- <entry>Cb<subscript>0</subscript></entry>
- <entry>Cr<subscript>4</subscript></entry>
- <entry>Cr<subscript>3</subscript></entry>
- <entry>Cr<subscript>2</subscript></entry>
- <entry>Cr<subscript>1</subscript></entry>
- <entry>Cr<subscript>0</subscript></entry>
- <entry></entry>
- <entry>a</entry>
- <entry>Y'<subscript>4</subscript></entry>
- <entry>Y'<subscript>3</subscript></entry>
- <entry>Y'<subscript>2</subscript></entry>
- <entry>Y'<subscript>1</subscript></entry>
- <entry>Y'<subscript>0</subscript></entry>
- <entry>Cb<subscript>4</subscript></entry>
- <entry>Cb<subscript>3</subscript></entry>
- </row>
-
- <row id="V4L2-PIX-FMT-YUV565">
- <entry><constant>V4L2_PIX_FMT_YUV565</constant></entry>
- <entry>'YUVP'</entry>
- <entry></entry>
- <entry>Cb<subscript>2</subscript></entry>
- <entry>Cb<subscript>1</subscript></entry>
- <entry>Cb<subscript>0</subscript></entry>
- <entry>Cr<subscript>4</subscript></entry>
- <entry>Cr<subscript>3</subscript></entry>
- <entry>Cr<subscript>2</subscript></entry>
- <entry>Cr<subscript>1</subscript></entry>
- <entry>Cr<subscript>0</subscript></entry>
- <entry></entry>
- <entry>Y'<subscript>4</subscript></entry>
- <entry>Y'<subscript>3</subscript></entry>
- <entry>Y'<subscript>2</subscript></entry>
- <entry>Y'<subscript>1</subscript></entry>
- <entry>Y'<subscript>0</subscript></entry>
- <entry>Cb<subscript>5</subscript></entry>
- <entry>Cb<subscript>4</subscript></entry>
- <entry>Cb<subscript>3</subscript></entry>
- </row>
-
- <row id="V4L2-PIX-FMT-YUV32">
- <entry><constant>V4L2_PIX_FMT_YUV32</constant></entry>
- <entry>'YUV4'</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry></entry>
- <entry>Y'<subscript>7</subscript></entry>
- <entry>Y'<subscript>6</subscript></entry>
- <entry>Y'<subscript>5</subscript></entry>
- <entry>Y'<subscript>4</subscript></entry>
- <entry>Y'<subscript>3</subscript></entry>
- <entry>Y'<subscript>2</subscript></entry>
- <entry>Y'<subscript>1</subscript></entry>
- <entry>Y'<subscript>0</subscript></entry>
- <entry></entry>
- <entry>Cb<subscript>7</subscript></entry>
- <entry>Cb<subscript>6</subscript></entry>
- <entry>Cb<subscript>5</subscript></entry>
- <entry>Cb<subscript>4</subscript></entry>
- <entry>Cb<subscript>3</subscript></entry>
- <entry>Cb<subscript>2</subscript></entry>
- <entry>Cb<subscript>1</subscript></entry>
- <entry>Cb<subscript>0</subscript></entry>
- <entry></entry>
- <entry>Cr<subscript>7</subscript></entry>
- <entry>Cr<subscript>6</subscript></entry>
- <entry>Cr<subscript>5</subscript></entry>
- <entry>Cr<subscript>4</subscript></entry>
- <entry>Cr<subscript>3</subscript></entry>
- <entry>Cr<subscript>2</subscript></entry>
- <entry>Cr<subscript>1</subscript></entry>
- <entry>Cr<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>Bit 7 is the most significant bit. The value of a = alpha
-bits is undefined when reading from the driver, ignored when writing
-to the driver, except when alpha blending has been negotiated for a
-<link linkend="overlay">Video Overlay</link> or <link
-linkend="osd">Video Output Overlay</link>.</para>
-
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml b/Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml
deleted file mode 100644
index 6494b05d84a1..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sbggr16.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<refentry id="V4L2-PIX-FMT-SBGGR16">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SBGGR16 ('BYR2')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_SBGGR16</constant></refname>
- <refpurpose>Bayer RGB format</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This format is similar to <link
-linkend="V4L2-PIX-FMT-SBGGR8">
-<constant>V4L2_PIX_FMT_SBGGR8</constant></link>, except each pixel has
-a depth of 16 bits. The least significant byte is stored at lower
-memory addresses (little-endian). Note the actual sampling precision
-may be lower than 16 bits, for example 10 bits per pixel with values
-in range 0 to 1023.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SBGGR16</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00low</subscript></entry>
- <entry>B<subscript>00high</subscript></entry>
- <entry>G<subscript>01low</subscript></entry>
- <entry>G<subscript>01high</subscript></entry>
- <entry>B<subscript>02low</subscript></entry>
- <entry>B<subscript>02high</subscript></entry>
- <entry>G<subscript>03low</subscript></entry>
- <entry>G<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>G<subscript>10low</subscript></entry>
- <entry>G<subscript>10high</subscript></entry>
- <entry>R<subscript>11low</subscript></entry>
- <entry>R<subscript>11high</subscript></entry>
- <entry>G<subscript>12low</subscript></entry>
- <entry>G<subscript>12high</subscript></entry>
- <entry>R<subscript>13low</subscript></entry>
- <entry>R<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>B<subscript>20low</subscript></entry>
- <entry>B<subscript>20high</subscript></entry>
- <entry>G<subscript>21low</subscript></entry>
- <entry>G<subscript>21high</subscript></entry>
- <entry>B<subscript>22low</subscript></entry>
- <entry>B<subscript>22high</subscript></entry>
- <entry>G<subscript>23low</subscript></entry>
- <entry>G<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>G<subscript>30low</subscript></entry>
- <entry>G<subscript>30high</subscript></entry>
- <entry>R<subscript>31low</subscript></entry>
- <entry>R<subscript>31high</subscript></entry>
- <entry>G<subscript>32low</subscript></entry>
- <entry>G<subscript>32high</subscript></entry>
- <entry>R<subscript>33low</subscript></entry>
- <entry>R<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml b/Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml
deleted file mode 100644
index 5eaf2b42d3f7..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sbggr8.xml
+++ /dev/null
@@ -1,67 +0,0 @@
- <refentry id="V4L2-PIX-FMT-SBGGR8">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SBGGR8 ('BA81')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_SBGGR8</constant></refname>
- <refpurpose>Bayer RGB format</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is commonly the native format of digital cameras,
-reflecting the arrangement of sensors on the CCD device. Only one red,
-green or blue value is given for each pixel. Missing components must
-be interpolated from neighbouring pixels. From left to right the first
-row consists of a blue and green value, the second row of a green and
-red value. This scheme repeats to the right and down for every two
-columns and rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SBGGR8</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00</subscript></entry>
- <entry>G<subscript>01</subscript></entry>
- <entry>B<subscript>02</subscript></entry>
- <entry>G<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>G<subscript>10</subscript></entry>
- <entry>R<subscript>11</subscript></entry>
- <entry>G<subscript>12</subscript></entry>
- <entry>R<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>B<subscript>20</subscript></entry>
- <entry>G<subscript>21</subscript></entry>
- <entry>B<subscript>22</subscript></entry>
- <entry>G<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>G<subscript>30</subscript></entry>
- <entry>R<subscript>31</subscript></entry>
- <entry>G<subscript>32</subscript></entry>
- <entry>R<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
deleted file mode 100644
index 6118d8f7a20c..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<refentry id="V4L2-SDR-FMT-CS08">
- <refmeta>
- <refentrytitle>V4L2_SDR_FMT_CS8 ('CS08')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>
- <constant>V4L2_SDR_FMT_CS8</constant>
- </refname>
- <refpurpose>Complex signed 8-bit IQ sample</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>
-This format contains sequence of complex number samples. Each complex number
-consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
-represented as a 8 bit signed number. I value comes first and Q value after
-that.
- </para>
- <example>
- <title><constant>V4L2_SDR_FMT_CS8</constant> 1 sample</title>
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="2" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>I'<subscript>0</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;1:</entry>
- <entry>Q'<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
deleted file mode 100644
index e4b494ce1369..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<refentry id="V4L2-SDR-FMT-CS14LE">
- <refmeta>
- <refentrytitle>V4L2_SDR_FMT_CS14LE ('CS14')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>
- <constant>V4L2_SDR_FMT_CS14LE</constant>
- </refname>
- <refpurpose>Complex signed 14-bit little endian IQ sample</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>
-This format contains sequence of complex number samples. Each complex number
-consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
-represented as a 14 bit signed little endian number. I value comes first
-and Q value after that. 14 bit value is stored in 16 bit space with unused
-high bits padded with 0.
- </para>
- <example>
- <title><constant>V4L2_SDR_FMT_CS14LE</constant> 1 sample</title>
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="3" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>I'<subscript>0[7:0]</subscript></entry>
- <entry>I'<subscript>0[13:8]</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;2:</entry>
- <entry>Q'<subscript>0[7:0]</subscript></entry>
- <entry>Q'<subscript>0[13:8]</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
deleted file mode 100644
index 2d80104c178b..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu08.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<refentry id="V4L2-SDR-FMT-CU08">
- <refmeta>
- <refentrytitle>V4L2_SDR_FMT_CU8 ('CU08')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>
- <constant>V4L2_SDR_FMT_CU8</constant>
- </refname>
- <refpurpose>Complex unsigned 8-bit IQ sample</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>
-This format contains sequence of complex number samples. Each complex number
-consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
-represented as a 8 bit unsigned number. I value comes first and Q value after
-that.
- </para>
- <example>
- <title><constant>V4L2_SDR_FMT_CU8</constant> 1 sample</title>
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="2" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>I'<subscript>0</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;1:</entry>
- <entry>Q'<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
deleted file mode 100644
index 26288ffa9071..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sdr-cu16le.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<refentry id="V4L2-SDR-FMT-CU16LE">
- <refmeta>
- <refentrytitle>V4L2_SDR_FMT_CU16LE ('CU16')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>
- <constant>V4L2_SDR_FMT_CU16LE</constant>
- </refname>
- <refpurpose>Complex unsigned 16-bit little endian IQ sample</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>
-This format contains sequence of complex number samples. Each complex number
-consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
-represented as a 16 bit unsigned little endian number. I value comes first
-and Q value after that.
- </para>
- <example>
- <title><constant>V4L2_SDR_FMT_CU16LE</constant> 1 sample</title>
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="3" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>I'<subscript>0[7:0]</subscript></entry>
- <entry>I'<subscript>0[15:8]</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;2:</entry>
- <entry>Q'<subscript>0[7:0]</subscript></entry>
- <entry>Q'<subscript>0[15:8]</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
deleted file mode 100644
index 3df076b99f94..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<refentry id="V4L2-SDR-FMT-RU12LE">
- <refmeta>
- <refentrytitle>V4L2_SDR_FMT_RU12LE ('RU12')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname>
- <constant>V4L2_SDR_FMT_RU12LE</constant>
- </refname>
- <refpurpose>Real unsigned 12-bit little endian sample</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>
-This format contains sequence of real number samples. Each sample is
-represented as a 12 bit unsigned little endian number. Sample is stored
-in 16 bit space with unused high bits padded with 0.
- </para>
- <example>
- <title><constant>V4L2_SDR_FMT_RU12LE</constant> 1 sample</title>
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="3" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>I'<subscript>0[7:0]</subscript></entry>
- <entry>I'<subscript>0[11:8]</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml b/Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml
deleted file mode 100644
index fee65dca79c5..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sgbrg8.xml
+++ /dev/null
@@ -1,67 +0,0 @@
- <refentry id="V4L2-PIX-FMT-SGBRG8">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SGBRG8 ('GBRG')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_SGBRG8</constant></refname>
- <refpurpose>Bayer RGB format</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is commonly the native format of digital cameras,
-reflecting the arrangement of sensors on the CCD device. Only one red,
-green or blue value is given for each pixel. Missing components must
-be interpolated from neighbouring pixels. From left to right the first
-row consists of a green and blue value, the second row of a red and
-green value. This scheme repeats to the right and down for every two
-columns and rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SGBRG8</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>G<subscript>00</subscript></entry>
- <entry>B<subscript>01</subscript></entry>
- <entry>G<subscript>02</subscript></entry>
- <entry>B<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>R<subscript>10</subscript></entry>
- <entry>G<subscript>11</subscript></entry>
- <entry>R<subscript>12</subscript></entry>
- <entry>G<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>G<subscript>20</subscript></entry>
- <entry>B<subscript>21</subscript></entry>
- <entry>G<subscript>22</subscript></entry>
- <entry>B<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>R<subscript>30</subscript></entry>
- <entry>G<subscript>31</subscript></entry>
- <entry>R<subscript>32</subscript></entry>
- <entry>G<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml b/Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml
deleted file mode 100644
index 7803b8c41b45..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml
+++ /dev/null
@@ -1,67 +0,0 @@
- <refentry id="V4L2-PIX-FMT-SGRBG8">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SGRBG8 ('GRBG')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_SGRBG8</constant></refname>
- <refpurpose>Bayer RGB format</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is commonly the native format of digital cameras,
-reflecting the arrangement of sensors on the CCD device. Only one red,
-green or blue value is given for each pixel. Missing components must
-be interpolated from neighbouring pixels. From left to right the first
-row consists of a green and blue value, the second row of a red and
-green value. This scheme repeats to the right and down for every two
-columns and rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SGRBG8</constant> 4 &times;
-4 pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>G<subscript>00</subscript></entry>
- <entry>R<subscript>01</subscript></entry>
- <entry>G<subscript>02</subscript></entry>
- <entry>R<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>B<subscript>10</subscript></entry>
- <entry>G<subscript>11</subscript></entry>
- <entry>B<subscript>12</subscript></entry>
- <entry>G<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>G<subscript>20</subscript></entry>
- <entry>R<subscript>21</subscript></entry>
- <entry>G<subscript>22</subscript></entry>
- <entry>R<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>B<subscript>30</subscript></entry>
- <entry>G<subscript>31</subscript></entry>
- <entry>B<subscript>32</subscript></entry>
- <entry>G<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml
deleted file mode 100644
index f34d03ebda3a..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10.xml
+++ /dev/null
@@ -1,90 +0,0 @@
- <refentry id="pixfmt-srggb10">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SRGGB10 ('RG10'),
- V4L2_PIX_FMT_SGRBG10 ('BA10'),
- V4L2_PIX_FMT_SGBRG10 ('GB10'),
- V4L2_PIX_FMT_SBGGR10 ('BG10'),
- </refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-SRGGB10"><constant>V4L2_PIX_FMT_SRGGB10</constant></refname>
- <refname id="V4L2-PIX-FMT-SGRBG10"><constant>V4L2_PIX_FMT_SGRBG10</constant></refname>
- <refname id="V4L2-PIX-FMT-SGBRG10"><constant>V4L2_PIX_FMT_SGBRG10</constant></refname>
- <refname id="V4L2-PIX-FMT-SBGGR10"><constant>V4L2_PIX_FMT_SBGGR10</constant></refname>
- <refpurpose>10-bit Bayer formats expanded to 16 bits</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These four pixel formats are raw sRGB / Bayer formats with
-10 bits per colour. Each colour component is stored in a 16-bit word, with 6
-unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
-and n/2 blue or red samples, with alternating red and blue rows. Bytes are
-stored in memory in little endian order. They are conventionally described
-as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
-formats</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SBGGR10</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte, high 6 bits in high bytes are 0.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00low</subscript></entry>
- <entry>B<subscript>00high</subscript></entry>
- <entry>G<subscript>01low</subscript></entry>
- <entry>G<subscript>01high</subscript></entry>
- <entry>B<subscript>02low</subscript></entry>
- <entry>B<subscript>02high</subscript></entry>
- <entry>G<subscript>03low</subscript></entry>
- <entry>G<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>G<subscript>10low</subscript></entry>
- <entry>G<subscript>10high</subscript></entry>
- <entry>R<subscript>11low</subscript></entry>
- <entry>R<subscript>11high</subscript></entry>
- <entry>G<subscript>12low</subscript></entry>
- <entry>G<subscript>12high</subscript></entry>
- <entry>R<subscript>13low</subscript></entry>
- <entry>R<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>B<subscript>20low</subscript></entry>
- <entry>B<subscript>20high</subscript></entry>
- <entry>G<subscript>21low</subscript></entry>
- <entry>G<subscript>21high</subscript></entry>
- <entry>B<subscript>22low</subscript></entry>
- <entry>B<subscript>22high</subscript></entry>
- <entry>G<subscript>23low</subscript></entry>
- <entry>G<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>G<subscript>30low</subscript></entry>
- <entry>G<subscript>30high</subscript></entry>
- <entry>R<subscript>31low</subscript></entry>
- <entry>R<subscript>31high</subscript></entry>
- <entry>G<subscript>32low</subscript></entry>
- <entry>G<subscript>32high</subscript></entry>
- <entry>R<subscript>33low</subscript></entry>
- <entry>R<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
deleted file mode 100644
index d2e5845e57fb..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10alaw8.xml
+++ /dev/null
@@ -1,34 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>
- V4L2_PIX_FMT_SBGGR10ALAW8 ('aBA8'),
- V4L2_PIX_FMT_SGBRG10ALAW8 ('aGA8'),
- V4L2_PIX_FMT_SGRBG10ALAW8 ('agA8'),
- V4L2_PIX_FMT_SRGGB10ALAW8 ('aRA8'),
- </refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-SBGGR10ALAW8">
- <constant>V4L2_PIX_FMT_SBGGR10ALAW8</constant>
- </refname>
- <refname id="V4L2-PIX-FMT-SGBRG10ALAW8">
- <constant>V4L2_PIX_FMT_SGBRG10ALAW8</constant>
- </refname>
- <refname id="V4L2-PIX-FMT-SGRBG10ALAW8">
- <constant>V4L2_PIX_FMT_SGRBG10ALAW8</constant>
- </refname>
- <refname id="V4L2-PIX-FMT-SRGGB10ALAW8">
- <constant>V4L2_PIX_FMT_SRGGB10ALAW8</constant>
- </refname>
- <refpurpose>10-bit Bayer formats compressed to 8 bits</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>These four pixel formats are raw sRGB / Bayer
- formats with 10 bits per color compressed to 8 bits each,
- using the A-LAW algorithm. Each color component consumes 8
- bits of memory. In other respects this format is similar to
- <xref linkend="V4L2-PIX-FMT-SRGGB8"></xref>.</para>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
deleted file mode 100644
index bde89878c5c5..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
+++ /dev/null
@@ -1,28 +0,0 @@
- <refentry id="pixfmt-srggb10dpcm8">
- <refmeta>
- <refentrytitle>
- V4L2_PIX_FMT_SBGGR10DPCM8 ('bBA8'),
- V4L2_PIX_FMT_SGBRG10DPCM8 ('bGA8'),
- V4L2_PIX_FMT_SGRBG10DPCM8 ('BD10'),
- V4L2_PIX_FMT_SRGGB10DPCM8 ('bRA8'),
- </refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-SBGGR10DPCM8"><constant>V4L2_PIX_FMT_SBGGR10DPCM8</constant></refname>
- <refname id="V4L2-PIX-FMT-SGBRG10DPCM8"><constant>V4L2_PIX_FMT_SGBRG10DPCM8</constant></refname>
- <refname id="V4L2-PIX-FMT-SGRBG10DPCM8"><constant>V4L2_PIX_FMT_SGRBG10DPCM8</constant></refname>
- <refname id="V4L2-PIX-FMT-SRGGB10DPCM8"><constant>V4L2_PIX_FMT_SRGGB10DPCM8</constant></refname>
- <refpurpose>10-bit Bayer formats compressed to 8 bits</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These four pixel formats are raw sRGB / Bayer formats
- with 10 bits per colour compressed to 8 bits each, using DPCM
- compression. DPCM, differential pulse-code modulation, is lossy.
- Each colour component consumes 8 bits of memory. In other respects
- this format is similar to <xref linkend="pixfmt-srggb10" />.</para>
-
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
deleted file mode 100644
index a8cc102cde4f..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
+++ /dev/null
@@ -1,99 +0,0 @@
- <refentry id="pixfmt-srggb10p">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SRGGB10P ('pRAA'),
- V4L2_PIX_FMT_SGRBG10P ('pgAA'),
- V4L2_PIX_FMT_SGBRG10P ('pGAA'),
- V4L2_PIX_FMT_SBGGR10P ('pBAA'),
- </refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-SRGGB10P"><constant>V4L2_PIX_FMT_SRGGB10P</constant></refname>
- <refname id="V4L2-PIX-FMT-SGRBG10P"><constant>V4L2_PIX_FMT_SGRBG10P</constant></refname>
- <refname id="V4L2-PIX-FMT-SGBRG10P"><constant>V4L2_PIX_FMT_SGBRG10P</constant></refname>
- <refname id="V4L2-PIX-FMT-SBGGR10P"><constant>V4L2_PIX_FMT_SBGGR10P</constant></refname>
- <refpurpose>10-bit packed Bayer formats</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These four pixel formats are packed raw sRGB /
- Bayer formats with 10 bits per colour. Every four consecutive
- colour components are packed into 5 bytes. Each of the first 4
- bytes contain the 8 high order bits of the pixels, and the
- fifth byte contains the two least significants bits of each
- pixel, in the same order.</para>
-
- <para>Each n-pixel row contains n/2 green samples and n/2 blue
- or red samples, with alternating green-red and green-blue
- rows. They are conventionally described as GRGR... BGBG...,
- RGRG... GBGB..., etc. Below is an example of one of these
- formats:</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SBGGR10P</constant> 4 &times; 4
- pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="topbot" colsep="1" rowsep="1">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00high</subscript></entry>
- <entry>G<subscript>01high</subscript></entry>
- <entry>B<subscript>02high</subscript></entry>
- <entry>G<subscript>03high</subscript></entry>
- <entry>B<subscript>00low</subscript>(bits 7--6)
- G<subscript>01low</subscript>(bits 5--4)
- B<subscript>02low</subscript>(bits 3--2)
- G<subscript>03low</subscript>(bits 1--0)
- </entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;5:</entry>
- <entry>G<subscript>10high</subscript></entry>
- <entry>R<subscript>11high</subscript></entry>
- <entry>G<subscript>12high</subscript></entry>
- <entry>R<subscript>13high</subscript></entry>
- <entry>G<subscript>10low</subscript>(bits 7--6)
- R<subscript>11low</subscript>(bits 5--4)
- G<subscript>12low</subscript>(bits 3--2)
- R<subscript>13low</subscript>(bits 1--0)
- </entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;10:</entry>
- <entry>B<subscript>20high</subscript></entry>
- <entry>G<subscript>21high</subscript></entry>
- <entry>B<subscript>22high</subscript></entry>
- <entry>G<subscript>23high</subscript></entry>
- <entry>B<subscript>20low</subscript>(bits 7--6)
- G<subscript>21low</subscript>(bits 5--4)
- B<subscript>22low</subscript>(bits 3--2)
- G<subscript>23low</subscript>(bits 1--0)
- </entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;15:</entry>
- <entry>G<subscript>30high</subscript></entry>
- <entry>R<subscript>31high</subscript></entry>
- <entry>G<subscript>32high</subscript></entry>
- <entry>R<subscript>33high</subscript></entry>
- <entry>G<subscript>30low</subscript>(bits 7--6)
- R<subscript>31low</subscript>(bits 5--4)
- G<subscript>32low</subscript>(bits 3--2)
- R<subscript>33low</subscript>(bits 1--0)
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
deleted file mode 100644
index 0c8e4adf417f..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
+++ /dev/null
@@ -1,90 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SRGGB12 ('RG12'),
- V4L2_PIX_FMT_SGRBG12 ('BA12'),
- V4L2_PIX_FMT_SGBRG12 ('GB12'),
- V4L2_PIX_FMT_SBGGR12 ('BG12'),
- </refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-SRGGB12"><constant>V4L2_PIX_FMT_SRGGB12</constant></refname>
- <refname id="V4L2-PIX-FMT-SGRBG12"><constant>V4L2_PIX_FMT_SGRBG12</constant></refname>
- <refname id="V4L2-PIX-FMT-SGBRG12"><constant>V4L2_PIX_FMT_SGBRG12</constant></refname>
- <refname id="V4L2-PIX-FMT-SBGGR12"><constant>V4L2_PIX_FMT_SBGGR12</constant></refname>
- <refpurpose>12-bit Bayer formats expanded to 16 bits</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These four pixel formats are raw sRGB / Bayer formats with
-12 bits per colour. Each colour component is stored in a 16-bit word, with 4
-unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
-and n/2 blue or red samples, with alternating red and blue rows. Bytes are
-stored in memory in little endian order. They are conventionally described
-as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
-formats</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SBGGR12</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte, high 6 bits in high bytes are 0.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>B<subscript>00low</subscript></entry>
- <entry>B<subscript>00high</subscript></entry>
- <entry>G<subscript>01low</subscript></entry>
- <entry>G<subscript>01high</subscript></entry>
- <entry>B<subscript>02low</subscript></entry>
- <entry>B<subscript>02high</subscript></entry>
- <entry>G<subscript>03low</subscript></entry>
- <entry>G<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>G<subscript>10low</subscript></entry>
- <entry>G<subscript>10high</subscript></entry>
- <entry>R<subscript>11low</subscript></entry>
- <entry>R<subscript>11high</subscript></entry>
- <entry>G<subscript>12low</subscript></entry>
- <entry>G<subscript>12high</subscript></entry>
- <entry>R<subscript>13low</subscript></entry>
- <entry>R<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>B<subscript>20low</subscript></entry>
- <entry>B<subscript>20high</subscript></entry>
- <entry>G<subscript>21low</subscript></entry>
- <entry>G<subscript>21high</subscript></entry>
- <entry>B<subscript>22low</subscript></entry>
- <entry>B<subscript>22high</subscript></entry>
- <entry>G<subscript>23low</subscript></entry>
- <entry>G<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>G<subscript>30low</subscript></entry>
- <entry>G<subscript>30high</subscript></entry>
- <entry>R<subscript>31low</subscript></entry>
- <entry>R<subscript>31high</subscript></entry>
- <entry>G<subscript>32low</subscript></entry>
- <entry>G<subscript>32high</subscript></entry>
- <entry>R<subscript>33low</subscript></entry>
- <entry>R<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb8.xml
deleted file mode 100644
index 2570e3be3cf1..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb8.xml
+++ /dev/null
@@ -1,67 +0,0 @@
- <refentry id="V4L2-PIX-FMT-SRGGB8">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_SRGGB8 ('RGGB')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_SRGGB8</constant></refname>
- <refpurpose>Bayer RGB format</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is commonly the native format of digital cameras,
-reflecting the arrangement of sensors on the CCD device. Only one red,
-green or blue value is given for each pixel. Missing components must
-be interpolated from neighbouring pixels. From left to right the first
-row consists of a red and green value, the second row of a green and
-blue value. This scheme repeats to the right and down for every two
-columns and rows.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_SRGGB8</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>R<subscript>00</subscript></entry>
- <entry>G<subscript>01</subscript></entry>
- <entry>R<subscript>02</subscript></entry>
- <entry>G<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>G<subscript>10</subscript></entry>
- <entry>B<subscript>11</subscript></entry>
- <entry>G<subscript>12</subscript></entry>
- <entry>B<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>R<subscript>20</subscript></entry>
- <entry>G<subscript>21</subscript></entry>
- <entry>R<subscript>22</subscript></entry>
- <entry>G<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>G<subscript>30</subscript></entry>
- <entry>B<subscript>31</subscript></entry>
- <entry>G<subscript>32</subscript></entry>
- <entry>B<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-uv8.xml b/Documentation/DocBook/media/v4l/pixfmt-uv8.xml
deleted file mode 100644
index c507c1f73cd0..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-uv8.xml
+++ /dev/null
@@ -1,62 +0,0 @@
- <refentry id="V4L2-PIX-FMT-UV8">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_UV8 ('UV8')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_UV8</constant></refname>
- <refpurpose>UV plane interleaved</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
- <para>In this format there is no Y plane, Only CbCr plane. ie
- (UV interleaved)</para>
- <example>
- <title>
- <constant>V4L2_PIX_FMT_UV8</constant>
- pixel image
- </title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-uyvy.xml b/Documentation/DocBook/media/v4l/pixfmt-uyvy.xml
deleted file mode 100644
index b1f6801a17ff..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-uyvy.xml
+++ /dev/null
@@ -1,120 +0,0 @@
- <refentry id="V4L2-PIX-FMT-UYVY">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_UYVY ('UYVY')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_UYVY</constant></refname>
- <refpurpose>Variation of
-<constant>V4L2_PIX_FMT_YUYV</constant> with different order of samples
-in memory</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>In this format each four bytes is two pixels. Each four
-bytes is two Y's, a Cb and a Cr. Each Y goes to one of the pixels, and
-the Cb and Cr belong to both pixels. As you can see, the Cr and Cb
-components have half the horizontal resolution of the Y
-component.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_UYVY</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-vyuy.xml b/Documentation/DocBook/media/v4l/pixfmt-vyuy.xml
deleted file mode 100644
index 82803408b389..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-vyuy.xml
+++ /dev/null
@@ -1,120 +0,0 @@
- <refentry id="V4L2-PIX-FMT-VYUY">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_VYUY ('VYUY')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_VYUY</constant></refname>
- <refpurpose>Variation of
-<constant>V4L2_PIX_FMT_YUYV</constant> with different order of samples
-in memory</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>In this format each four bytes is two pixels. Each four
-bytes is two Y's, a Cb and a Cr. Each Y goes to one of the pixels, and
-the Cb and Cr belong to both pixels. As you can see, the Cr and Cb
-components have half the horizontal resolution of the Y
-component.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_VYUY</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y10.xml b/Documentation/DocBook/media/v4l/pixfmt-y10.xml
deleted file mode 100644
index d065043db8d8..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y10.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y10">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y10 ('Y10 ')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y10</constant></refname>
- <refpurpose>Grey-scale image</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 10 bits per pixel. Pixels
-are stored in 16-bit words with unused high bits padded with 0. The least
-significant byte is stored at lower memory addresses (little-endian).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y10</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00low</subscript></entry>
- <entry>Y'<subscript>00high</subscript></entry>
- <entry>Y'<subscript>01low</subscript></entry>
- <entry>Y'<subscript>01high</subscript></entry>
- <entry>Y'<subscript>02low</subscript></entry>
- <entry>Y'<subscript>02high</subscript></entry>
- <entry>Y'<subscript>03low</subscript></entry>
- <entry>Y'<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10low</subscript></entry>
- <entry>Y'<subscript>10high</subscript></entry>
- <entry>Y'<subscript>11low</subscript></entry>
- <entry>Y'<subscript>11high</subscript></entry>
- <entry>Y'<subscript>12low</subscript></entry>
- <entry>Y'<subscript>12high</subscript></entry>
- <entry>Y'<subscript>13low</subscript></entry>
- <entry>Y'<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20low</subscript></entry>
- <entry>Y'<subscript>20high</subscript></entry>
- <entry>Y'<subscript>21low</subscript></entry>
- <entry>Y'<subscript>21high</subscript></entry>
- <entry>Y'<subscript>22low</subscript></entry>
- <entry>Y'<subscript>22high</subscript></entry>
- <entry>Y'<subscript>23low</subscript></entry>
- <entry>Y'<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30low</subscript></entry>
- <entry>Y'<subscript>30high</subscript></entry>
- <entry>Y'<subscript>31low</subscript></entry>
- <entry>Y'<subscript>31high</subscript></entry>
- <entry>Y'<subscript>32low</subscript></entry>
- <entry>Y'<subscript>32high</subscript></entry>
- <entry>Y'<subscript>33low</subscript></entry>
- <entry>Y'<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y10b.xml b/Documentation/DocBook/media/v4l/pixfmt-y10b.xml
deleted file mode 100644
index adb0ad808c93..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y10b.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y10BPACK">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y10BPACK ('Y10B')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y10BPACK</constant></refname>
- <refpurpose>Grey-scale image as a bit-packed array</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a packed grey-scale image format with a depth of 10 bits per
- pixel. Pixels are stored in a bit-packed array of 10bit bits per pixel,
- with no padding between them and with the most significant bits coming
- first from the left.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y10BPACK</constant> 4 pixel data stream taking 5 bytes</title>
-
- <formalpara>
- <title>Bit-packed representation</title>
- <para>pixels cross the byte boundary and have a ratio of 5 bytes for each 4
- pixels.
- <informaltable frame="all">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>Y'<subscript>00[9:2]</subscript></entry>
- <entry>Y'<subscript>00[1:0]</subscript>Y'<subscript>01[9:4]</subscript></entry>
- <entry>Y'<subscript>01[3:0]</subscript>Y'<subscript>02[9:6]</subscript></entry>
- <entry>Y'<subscript>02[5:0]</subscript>Y'<subscript>03[9:8]</subscript></entry>
- <entry>Y'<subscript>03[7:0]</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y12.xml b/Documentation/DocBook/media/v4l/pixfmt-y12.xml
deleted file mode 100644
index ff417b858cc9..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y12.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y12">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y12 ('Y12 ')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y12</constant></refname>
- <refpurpose>Grey-scale image</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 12 bits per pixel. Pixels
-are stored in 16-bit words with unused high bits padded with 0. The least
-significant byte is stored at lower memory addresses (little-endian).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y12</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00low</subscript></entry>
- <entry>Y'<subscript>00high</subscript></entry>
- <entry>Y'<subscript>01low</subscript></entry>
- <entry>Y'<subscript>01high</subscript></entry>
- <entry>Y'<subscript>02low</subscript></entry>
- <entry>Y'<subscript>02high</subscript></entry>
- <entry>Y'<subscript>03low</subscript></entry>
- <entry>Y'<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10low</subscript></entry>
- <entry>Y'<subscript>10high</subscript></entry>
- <entry>Y'<subscript>11low</subscript></entry>
- <entry>Y'<subscript>11high</subscript></entry>
- <entry>Y'<subscript>12low</subscript></entry>
- <entry>Y'<subscript>12high</subscript></entry>
- <entry>Y'<subscript>13low</subscript></entry>
- <entry>Y'<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20low</subscript></entry>
- <entry>Y'<subscript>20high</subscript></entry>
- <entry>Y'<subscript>21low</subscript></entry>
- <entry>Y'<subscript>21high</subscript></entry>
- <entry>Y'<subscript>22low</subscript></entry>
- <entry>Y'<subscript>22high</subscript></entry>
- <entry>Y'<subscript>23low</subscript></entry>
- <entry>Y'<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30low</subscript></entry>
- <entry>Y'<subscript>30high</subscript></entry>
- <entry>Y'<subscript>31low</subscript></entry>
- <entry>Y'<subscript>31high</subscript></entry>
- <entry>Y'<subscript>32low</subscript></entry>
- <entry>Y'<subscript>32high</subscript></entry>
- <entry>Y'<subscript>33low</subscript></entry>
- <entry>Y'<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y12i.xml b/Documentation/DocBook/media/v4l/pixfmt-y12i.xml
deleted file mode 100644
index 4a2d1e5f67e4..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y12i.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y12I">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y12I ('Y12I')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y12I</constant></refname>
- <refpurpose>Interleaved grey-scale image, e.g. from a stereo-pair</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 12 bits per pixel, but with
-pixels from 2 sources interleaved and bit-packed. Each pixel is stored in a
-24-bit word in the little-endian order. On a little-endian machine these pixels
-can be deinterlaced using</para>
-
-<para>
-<programlisting>
-__u8 *buf;
-left0 = 0xfff &amp; *(__u16 *)buf;
-right0 = *(__u16 *)(buf + 1) >> 4;
-</programlisting>
-</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y12I</constant> 2 pixel data stream taking 3 bytes</title>
-
- <formalpara>
- <title>Bit-packed representation</title>
- <para>pixels cross the byte boundary and have a ratio of 3 bytes for each
- interleaved pixel.
- <informaltable frame="all">
- <tgroup cols="3" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>Y'<subscript>0left[7:0]</subscript></entry>
- <entry>Y'<subscript>0right[3:0]</subscript>Y'<subscript>0left[11:8]</subscript></entry>
- <entry>Y'<subscript>0right[11:4]</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y16-be.xml b/Documentation/DocBook/media/v4l/pixfmt-y16-be.xml
deleted file mode 100644
index cea53e1eaa43..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y16-be.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y16-BE">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y16_BE ('Y16 ' | (1 &lt;&lt; 31))</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y16_BE</constant></refname>
- <refpurpose>Grey-scale image</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 16 bits per
-pixel. The most significant byte is stored at lower memory addresses
-(big-endian). Note the actual sampling precision may be lower than
-16 bits, for example 10 bits per pixel with values in range 0 to
-1023.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y16_BE</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00high</subscript></entry>
- <entry>Y'<subscript>00low</subscript></entry>
- <entry>Y'<subscript>01high</subscript></entry>
- <entry>Y'<subscript>01low</subscript></entry>
- <entry>Y'<subscript>02high</subscript></entry>
- <entry>Y'<subscript>02low</subscript></entry>
- <entry>Y'<subscript>03high</subscript></entry>
- <entry>Y'<subscript>03low</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10high</subscript></entry>
- <entry>Y'<subscript>10low</subscript></entry>
- <entry>Y'<subscript>11high</subscript></entry>
- <entry>Y'<subscript>11low</subscript></entry>
- <entry>Y'<subscript>12high</subscript></entry>
- <entry>Y'<subscript>12low</subscript></entry>
- <entry>Y'<subscript>13high</subscript></entry>
- <entry>Y'<subscript>13low</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20high</subscript></entry>
- <entry>Y'<subscript>20low</subscript></entry>
- <entry>Y'<subscript>21high</subscript></entry>
- <entry>Y'<subscript>21low</subscript></entry>
- <entry>Y'<subscript>22high</subscript></entry>
- <entry>Y'<subscript>22low</subscript></entry>
- <entry>Y'<subscript>23high</subscript></entry>
- <entry>Y'<subscript>23low</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30high</subscript></entry>
- <entry>Y'<subscript>30low</subscript></entry>
- <entry>Y'<subscript>31high</subscript></entry>
- <entry>Y'<subscript>31low</subscript></entry>
- <entry>Y'<subscript>32high</subscript></entry>
- <entry>Y'<subscript>32low</subscript></entry>
- <entry>Y'<subscript>33high</subscript></entry>
- <entry>Y'<subscript>33low</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y16.xml b/Documentation/DocBook/media/v4l/pixfmt-y16.xml
deleted file mode 100644
index ff4f727d5624..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y16.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y16">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y16 ('Y16 ')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y16</constant></refname>
- <refpurpose>Grey-scale image</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 16 bits per
-pixel. The least significant byte is stored at lower memory addresses
-(little-endian). Note the actual sampling precision may be lower than
-16 bits, for example 10 bits per pixel with values in range 0 to
-1023.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y16</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00low</subscript></entry>
- <entry>Y'<subscript>00high</subscript></entry>
- <entry>Y'<subscript>01low</subscript></entry>
- <entry>Y'<subscript>01high</subscript></entry>
- <entry>Y'<subscript>02low</subscript></entry>
- <entry>Y'<subscript>02high</subscript></entry>
- <entry>Y'<subscript>03low</subscript></entry>
- <entry>Y'<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10low</subscript></entry>
- <entry>Y'<subscript>10high</subscript></entry>
- <entry>Y'<subscript>11low</subscript></entry>
- <entry>Y'<subscript>11high</subscript></entry>
- <entry>Y'<subscript>12low</subscript></entry>
- <entry>Y'<subscript>12high</subscript></entry>
- <entry>Y'<subscript>13low</subscript></entry>
- <entry>Y'<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20low</subscript></entry>
- <entry>Y'<subscript>20high</subscript></entry>
- <entry>Y'<subscript>21low</subscript></entry>
- <entry>Y'<subscript>21high</subscript></entry>
- <entry>Y'<subscript>22low</subscript></entry>
- <entry>Y'<subscript>22high</subscript></entry>
- <entry>Y'<subscript>23low</subscript></entry>
- <entry>Y'<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30low</subscript></entry>
- <entry>Y'<subscript>30high</subscript></entry>
- <entry>Y'<subscript>31low</subscript></entry>
- <entry>Y'<subscript>31high</subscript></entry>
- <entry>Y'<subscript>32low</subscript></entry>
- <entry>Y'<subscript>32high</subscript></entry>
- <entry>Y'<subscript>33low</subscript></entry>
- <entry>Y'<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y41p.xml b/Documentation/DocBook/media/v4l/pixfmt-y41p.xml
deleted file mode 100644
index 98dcb91d2917..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y41p.xml
+++ /dev/null
@@ -1,149 +0,0 @@
- <refentry id="V4L2-PIX-FMT-Y41P">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y41P ('Y41P')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y41P</constant></refname>
- <refpurpose>Format with &frac14; horizontal chroma
-resolution, also known as YUV 4:1:1</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>In this format each 12 bytes is eight pixels. In the
-twelve bytes are two CbCr pairs and eight Y's. The first CbCr pair
-goes with the first four Y's, and the second CbCr pair goes with the
-other four Y's. The Cb and Cr components have one fourth the
-horizontal resolution of the Y component.</para>
-
- <para>Do not confuse this format with <link
-linkend="V4L2-PIX-FMT-YUV411P"><constant>V4L2_PIX_FMT_YUV411P</constant></link>.
-Y41P is derived from "YUV 4:1:1 <emphasis>packed</emphasis>", while
-YUV411P stands for "YUV 4:1:1 <emphasis>planar</emphasis>".</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y41P</constant> 8 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="13" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- <entry>Y'<subscript>04</subscript></entry>
- <entry>Y'<subscript>05</subscript></entry>
- <entry>Y'<subscript>06</subscript></entry>
- <entry>Y'<subscript>07</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- <entry>Y'<subscript>14</subscript></entry>
- <entry>Y'<subscript>15</subscript></entry>
- <entry>Y'<subscript>16</subscript></entry>
- <entry>Y'<subscript>17</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- <entry>Y'<subscript>24</subscript></entry>
- <entry>Y'<subscript>25</subscript></entry>
- <entry>Y'<subscript>26</subscript></entry>
- <entry>Y'<subscript>27</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;36:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- <entry>Y'<subscript>34</subscript></entry>
- <entry>Y'<subscript>35</subscript></entry>
- <entry>Y'<subscript>36</subscript></entry>
- <entry>Y'<subscript>37</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable></para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="15" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry><entry></entry>
- <entry>4</entry><entry></entry><entry>5</entry><entry></entry>
- <entry>6</entry><entry></entry><entry>7</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-y8i.xml b/Documentation/DocBook/media/v4l/pixfmt-y8i.xml
deleted file mode 100644
index 99f389d4c6c8..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-y8i.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Y8I">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Y8I ('Y8I ')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Y8I</constant></refname>
- <refpurpose>Interleaved grey-scale image, e.g. from a stereo-pair</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a grey-scale image with a depth of 8 bits per pixel, but with
-pixels from 2 sources interleaved. Each pixel is stored in a 16-bit word. E.g.
-the R200 RealSense camera stores pixel from the left sensor in lower and from
-the right sensor in the higher 8 bits.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Y8I</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00left</subscript></entry>
- <entry>Y'<subscript>00right</subscript></entry>
- <entry>Y'<subscript>01left</subscript></entry>
- <entry>Y'<subscript>01right</subscript></entry>
- <entry>Y'<subscript>02left</subscript></entry>
- <entry>Y'<subscript>02right</subscript></entry>
- <entry>Y'<subscript>03left</subscript></entry>
- <entry>Y'<subscript>03right</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10left</subscript></entry>
- <entry>Y'<subscript>10right</subscript></entry>
- <entry>Y'<subscript>11left</subscript></entry>
- <entry>Y'<subscript>11right</subscript></entry>
- <entry>Y'<subscript>12left</subscript></entry>
- <entry>Y'<subscript>12right</subscript></entry>
- <entry>Y'<subscript>13left</subscript></entry>
- <entry>Y'<subscript>13right</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20left</subscript></entry>
- <entry>Y'<subscript>20right</subscript></entry>
- <entry>Y'<subscript>21left</subscript></entry>
- <entry>Y'<subscript>21right</subscript></entry>
- <entry>Y'<subscript>22left</subscript></entry>
- <entry>Y'<subscript>22right</subscript></entry>
- <entry>Y'<subscript>23left</subscript></entry>
- <entry>Y'<subscript>23right</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30left</subscript></entry>
- <entry>Y'<subscript>30right</subscript></entry>
- <entry>Y'<subscript>31left</subscript></entry>
- <entry>Y'<subscript>31right</subscript></entry>
- <entry>Y'<subscript>32left</subscript></entry>
- <entry>Y'<subscript>32right</subscript></entry>
- <entry>Y'<subscript>33left</subscript></entry>
- <entry>Y'<subscript>33right</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv410.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv410.xml
deleted file mode 100644
index 0869dce5f92c..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv410.xml
+++ /dev/null
@@ -1,133 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YVU410 ('YVU9'), V4L2_PIX_FMT_YUV410 ('YUV9')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-YVU410"><constant>V4L2_PIX_FMT_YVU410</constant></refname>
- <refname id="V4L2-PIX-FMT-YUV410"><constant>V4L2_PIX_FMT_YUV410</constant></refname>
- <refpurpose>Planar formats with &frac14; horizontal and
-vertical chroma resolution, also known as YUV 4:1:0</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These are planar formats, as opposed to a packed format.
-The three components are separated into three sub-images or planes.
-The Y plane is first. The Y plane has one byte per pixel. For
-<constant>V4L2_PIX_FMT_YVU410</constant>, the Cr plane immediately
-follows the Y plane in memory. The Cr plane is &frac14; the width and
-&frac14; the height of the Y plane (and of the image). Each Cr belongs
-to 16 pixels, a four-by-four square of the image. Following the Cr
-plane is the Cb plane, just like the Cr plane.
-<constant>V4L2_PIX_FMT_YUV410</constant> is the same, except the Cb
-plane comes first, then the Cr plane.</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cr
-and Cb planes have &frac14; as many pad bytes after their rows. In
-other words, four Cx rows (including padding) are exactly as long as
-one Y row (including padding).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YVU410</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;17:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry></entry><entry></entry><entry>C</entry>
- <entry></entry><entry></entry><entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml
deleted file mode 100644
index 086dc731bf02..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv411p.xml
+++ /dev/null
@@ -1,147 +0,0 @@
- <refentry id="V4L2-PIX-FMT-YUV411P">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV411P ('411P')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_YUV411P</constant></refname>
- <refpurpose>Format with &frac14; horizontal chroma resolution,
-also known as YUV 4:1:1. Planar layout as opposed to
-<constant>V4L2_PIX_FMT_Y41P</constant></refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This format is not commonly used. This is a planar
-format similar to the 4:2:2 planar format except with half as many
-chroma. The three components are separated into three sub-images or
-planes. The Y plane is first. The Y plane has one byte per pixel. The
-Cb plane immediately follows the Y plane in memory. The Cb plane is
-&frac14; the width of the Y plane (and of the image). Each Cb belongs
-to 4 pixels all on the same row. For example,
-Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
-Y'<subscript>01</subscript>, Y'<subscript>02</subscript> and
-Y'<subscript>03</subscript>. Following the Cb plane is the Cr plane,
-just like the Cb plane.</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cr
-and Cb planes have &frac14; as many pad bytes after their rows. In
-other words, four C x rows (including padding) is exactly as long as
-one Y row (including padding).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUV411P</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;17:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;18:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;19:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;21:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;22:</entry>
- <entry>Cr<subscript>20</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;23:</entry>
- <entry>Cr<subscript>30</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry>C</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420.xml
deleted file mode 100644
index 48649fac1596..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv420.xml
+++ /dev/null
@@ -1,149 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YVU420 ('YV12'), V4L2_PIX_FMT_YUV420 ('YU12')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-YVU420"><constant>V4L2_PIX_FMT_YVU420</constant></refname>
- <refname id="V4L2-PIX-FMT-YUV420"><constant>V4L2_PIX_FMT_YUV420</constant></refname>
- <refpurpose>Planar formats with &frac12; horizontal and
-vertical chroma resolution, also known as YUV 4:2:0</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>These are planar formats, as opposed to a packed format.
-The three components are separated into three sub- images or planes.
-The Y plane is first. The Y plane has one byte per pixel. For
-<constant>V4L2_PIX_FMT_YVU420</constant>, the Cr plane immediately
-follows the Y plane in memory. The Cr plane is half the width and half
-the height of the Y plane (and of the image). Each Cr belongs to four
-pixels, a two-by-two square of the image. For example,
-Cr<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
-Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
-Y'<subscript>11</subscript>. Following the Cr plane is the Cb plane,
-just like the Cr plane. <constant>V4L2_PIX_FMT_YUV420</constant> is
-the same except the Cb plane comes first, then the Cr plane.</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cr
-and Cb planes have half as many pad bytes after their rows. In other
-words, two Cx rows (including padding) is exactly as long as one Y row
-(including padding).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YVU420</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;18:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;22:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
deleted file mode 100644
index 7d13fe96657d..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
+++ /dev/null
@@ -1,162 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12'), V4L2_PIX_FMT_YVU420M ('YM21')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-YUV420M"><constant>V4L2_PIX_FMT_YUV420M</constant></refname>
- <refname id="V4L2-PIX-FMT-YVU420M"><constant>V4L2_PIX_FMT_YVU420M</constant></refname>
- <refpurpose>Variation of <constant>V4L2_PIX_FMT_YUV420</constant> and
- <constant>V4L2_PIX_FMT_YVU420</constant> with planes non contiguous
- in memory.</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>This is a multi-planar format, as opposed to a packed format.
-The three components are separated into three sub-images or planes.</para>
-
- <para>The Y plane is first. The Y plane has one byte per pixel.
-For <constant>V4L2_PIX_FMT_YUV420M</constant> the Cb data
-constitutes the second plane which is half the width and half
-the height of the Y plane (and of the image). Each Cb belongs to four
-pixels, a two-by-two square of the image. For example,
-Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
-Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
-Y'<subscript>11</subscript>. The Cr data, just like the Cb plane, is
-in the third plane.</para>
-
- <para><constant>V4L2_PIX_FMT_YVU420M</constant> is the same except
-the Cr data is stored in the second plane and the Cb data in the third plane.
-</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cb
-and Cr planes have half as many pad bytes after their rows. In other
-words, two Cx rows (including padding) is exactly as long as one Y row
-(including padding).</para>
-
- <para><constant>V4L2_PIX_FMT_YUV420M</constant> and
-<constant>V4L2_PIX_FMT_YVU420M</constant> are intended to be
-used only in drivers and applications that support the multi-planar API,
-described in <xref linkend="planar-apis"/>. </para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUV420M</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start0&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start1&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;2:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start2&nbsp;+&nbsp;0:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;2:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry><entry>C</entry><entry></entry><entry></entry>
- <entry></entry><entry>C</entry><entry></entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry></entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml
deleted file mode 100644
index dd502802cb75..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv422m.xml
+++ /dev/null
@@ -1,166 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV422M ('YM16'), V4L2_PIX_FMT_YVU422M ('YM61')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-YUV422M"><constant>V4L2_PIX_FMT_YUV422M</constant></refname>
- <refname id="V4L2-PIX-FMT-YVU422M"><constant>V4L2_PIX_FMT_YVU422M</constant></refname>
- <refpurpose>Planar formats with &frac12; horizontal resolution, also
- known as YUV and YVU 4:2:2</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>This is a multi-planar format, as opposed to a packed format.
-The three components are separated into three sub-images or planes.</para>
-
- <para>The Y plane is first. The Y plane has one byte per pixel.
-For <constant>V4L2_PIX_FMT_YUV422M</constant> the Cb data
-constitutes the second plane which is half the width of the Y plane (and of the
-image). Each Cb belongs to two pixels. For example,
-Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
-Y'<subscript>01</subscript>. The Cr data, just like the Cb plane, is
-in the third plane. </para>
-
- <para><constant>V4L2_PIX_FMT_YVU422M</constant> is the same except
-the Cr data is stored in the second plane and the Cb data in the third plane.
-</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cb
-and Cr planes have half as many pad bytes after their rows. In other
-words, two Cx rows (including padding) is exactly as long as one Y row
-(including padding).</para>
-
- <para><constant>V4L2_PIX_FMT_YUV422M</constant> and
-<constant>V4L2_PIX_FMT_YVU422M</constant> are intended to be
-used only in drivers and applications that support the multi-planar API,
-described in <xref linkend="planar-apis"/>. </para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUV422M</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start0&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start1&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;2:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;4:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;6:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start2&nbsp;+&nbsp;0:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;2:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;4:</entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;6:</entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml
deleted file mode 100644
index 4ce6463fe0a5..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv422p.xml
+++ /dev/null
@@ -1,153 +0,0 @@
- <refentry id="V4L2-PIX-FMT-YUV422P">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV422P ('422P')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_YUV422P</constant></refname>
- <refpurpose>Format with &frac12; horizontal chroma resolution,
-also known as YUV 4:2:2. Planar layout as opposed to
-<constant>V4L2_PIX_FMT_YUYV</constant></refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This format is not commonly used. This is a planar
-version of the YUYV format. The three components are separated into
-three sub-images or planes. The Y plane is first. The Y plane has one
-byte per pixel. The Cb plane immediately follows the Y plane in
-memory. The Cb plane is half the width of the Y plane (and of the
-image). Each Cb belongs to two pixels. For example,
-Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
-Y'<subscript>01</subscript>. Following the Cb plane is the Cr plane,
-just like the Cb plane.</para>
-
- <para>If the Y plane has pad bytes after each row, then the Cr
-and Cb planes have half as many pad bytes after their rows. In other
-words, two Cx rows (including padding) is exactly as long as one Y row
-(including padding).</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUV422P</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;18:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;20:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;22:</entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;26:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;28:</entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;30:</entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml
deleted file mode 100644
index 1b7335940bc7..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv444m.xml
+++ /dev/null
@@ -1,177 +0,0 @@
- <refentry>
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV444M ('YM24'), V4L2_PIX_FMT_YVU444M ('YM42')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname id="V4L2-PIX-FMT-YUV444M"><constant>V4L2_PIX_FMT_YUV444M</constant></refname>
- <refname id="V4L2-PIX-FMT-YVU444M"><constant>V4L2_PIX_FMT_YVU444M</constant></refname>
- <refpurpose>Planar formats with full horizontal resolution, also
- known as YUV and YVU 4:4:4</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>This is a multi-planar format, as opposed to a packed format.
-The three components are separated into three sub-images or planes.</para>
-
- <para>The Y plane is first. The Y plane has one byte per pixel.
-For <constant>V4L2_PIX_FMT_YUV444M</constant> the Cb data
-constitutes the second plane which is the same width and height as the Y plane
-(and as the image). The Cr data, just like the Cb plane, is in the third plane.
-</para>
-
- <para><constant>V4L2_PIX_FMT_YVU444M</constant> is the same except
-the Cr data is stored in the second plane and the Cb data in the third plane.
-</para>
- <para>If the Y plane has pad bytes after each row, then the Cb
-and Cr planes have the same number of pad bytes after their rows.</para>
-
- <para><constant>V4L2_PIX_FMT_YUV444M</constant> and
-<constant>V4L2_PIX_FMT_YUV444M</constant> are intended to be
-used only in drivers and applications that support the multi-planar API,
-described in <xref linkend="planar-apis"/>. </para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUV444M</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="5" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start0&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;4:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start0&nbsp;+&nbsp;12:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start1&nbsp;+&nbsp;0:</entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Cb<subscript>02</subscript></entry>
- <entry>Cb<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;4:</entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Cb<subscript>12</subscript></entry>
- <entry>Cb<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;8:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Cb<subscript>22</subscript></entry>
- <entry>Cb<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start1&nbsp;+&nbsp;12:</entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Cb<subscript>32</subscript></entry>
- <entry>Cb<subscript>33</subscript></entry>
- </row>
- <row><entry></entry></row>
- <row>
- <entry>start2&nbsp;+&nbsp;0:</entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Cr<subscript>02</subscript></entry>
- <entry>Cr<subscript>03</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;4:</entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Cr<subscript>12</subscript></entry>
- <entry>Cr<subscript>13</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;8:</entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Cr<subscript>22</subscript></entry>
- <entry>Cr<subscript>23</subscript></entry>
- </row>
- <row>
- <entry>start2&nbsp;+&nbsp;12:</entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Cr<subscript>32</subscript></entry>
- <entry>Cr<subscript>33</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
- <entry>YC</entry><entry></entry><entry>YC</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
- <entry>YC</entry><entry></entry><entry>YC</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
- <entry>YC</entry><entry></entry><entry>YC</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>YC</entry><entry></entry><entry>YC</entry><entry></entry>
- <entry>YC</entry><entry></entry><entry>YC</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuyv.xml b/Documentation/DocBook/media/v4l/pixfmt-yuyv.xml
deleted file mode 100644
index 58384092251a..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yuyv.xml
+++ /dev/null
@@ -1,120 +0,0 @@
- <refentry id="V4L2-PIX-FMT-YUYV">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUYV ('YUYV')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_YUYV</constant></refname>
- <refpurpose>Packed format with &frac12; horizontal chroma
-resolution, also known as YUV 4:2:2</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>In this format each four bytes is two pixels. Each four
-bytes is two Y's, a Cb and a Cr. Each Y goes to one of the pixels, and
-the Cb and Cr belong to both pixels. As you can see, the Cr and Cb
-components have half the horizontal resolution of the Y component.
-<constant>V4L2_PIX_FMT_YUYV </constant> is known in the Windows
-environment as YUY2.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YUYV</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yvyu.xml b/Documentation/DocBook/media/v4l/pixfmt-yvyu.xml
deleted file mode 100644
index bfffdc76d3da..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-yvyu.xml
+++ /dev/null
@@ -1,120 +0,0 @@
- <refentry id="V4L2-PIX-FMT-YVYU">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_YVYU ('YVYU')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_YVYU</constant></refname>
- <refpurpose>Variation of
-<constant>V4L2_PIX_FMT_YUYV</constant> with different order of samples
-in memory</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>In this format each four bytes is two pixels. Each four
-bytes is two Y's, a Cb and a Cr. Each Y goes to one of the pixels, and
-the Cb and Cr belong to both pixels. As you can see, the Cr and Cb
-components have half the horizontal resolution of the Y
-component.</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_YVYU</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Y'<subscript>00</subscript></entry>
- <entry>Cr<subscript>00</subscript></entry>
- <entry>Y'<subscript>01</subscript></entry>
- <entry>Cb<subscript>00</subscript></entry>
- <entry>Y'<subscript>02</subscript></entry>
- <entry>Cr<subscript>01</subscript></entry>
- <entry>Y'<subscript>03</subscript></entry>
- <entry>Cb<subscript>01</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Y'<subscript>10</subscript></entry>
- <entry>Cr<subscript>10</subscript></entry>
- <entry>Y'<subscript>11</subscript></entry>
- <entry>Cb<subscript>10</subscript></entry>
- <entry>Y'<subscript>12</subscript></entry>
- <entry>Cr<subscript>11</subscript></entry>
- <entry>Y'<subscript>13</subscript></entry>
- <entry>Cb<subscript>11</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Y'<subscript>20</subscript></entry>
- <entry>Cr<subscript>20</subscript></entry>
- <entry>Y'<subscript>21</subscript></entry>
- <entry>Cb<subscript>20</subscript></entry>
- <entry>Y'<subscript>22</subscript></entry>
- <entry>Cr<subscript>21</subscript></entry>
- <entry>Y'<subscript>23</subscript></entry>
- <entry>Cb<subscript>21</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Y'<subscript>30</subscript></entry>
- <entry>Cr<subscript>30</subscript></entry>
- <entry>Y'<subscript>31</subscript></entry>
- <entry>Cb<subscript>30</subscript></entry>
- <entry>Y'<subscript>32</subscript></entry>
- <entry>Cr<subscript>31</subscript></entry>
- <entry>Y'<subscript>33</subscript></entry>
- <entry>Cb<subscript>31</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
-
- <formalpara>
- <title>Color Sample Location.</title>
- <para>
- <informaltable frame="none">
- <tgroup cols="7" align="center">
- <tbody valign="top">
- <row>
- <entry></entry>
- <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
- <entry>2</entry><entry></entry><entry>3</entry>
- </row>
- <row>
- <entry>0</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>2</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- <row>
- <entry>3</entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry><entry></entry>
- <entry>Y</entry><entry>C</entry><entry>Y</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
- </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-z16.xml b/Documentation/DocBook/media/v4l/pixfmt-z16.xml
deleted file mode 100644
index 1d9cb1684bd3..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt-z16.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<refentry id="V4L2-PIX-FMT-Z16">
- <refmeta>
- <refentrytitle>V4L2_PIX_FMT_Z16 ('Z16 ')</refentrytitle>
- &manvol;
- </refmeta>
- <refnamediv>
- <refname><constant>V4L2_PIX_FMT_Z16</constant></refname>
- <refpurpose>16-bit depth data with distance values at each pixel</refpurpose>
- </refnamediv>
- <refsect1>
- <title>Description</title>
-
- <para>This is a 16-bit format, representing depth data. Each pixel is a
-distance to the respective point in the image coordinates. Distance unit can
-vary and has to be negotiated with the device separately. Each pixel is stored
-in a 16-bit word in the little endian byte order.
-</para>
-
- <example>
- <title><constant>V4L2_PIX_FMT_Z16</constant> 4 &times; 4
-pixel image</title>
-
- <formalpara>
- <title>Byte Order.</title>
- <para>Each cell is one byte.
- <informaltable frame="none">
- <tgroup cols="9" align="center">
- <colspec align="left" colwidth="2*" />
- <tbody valign="top">
- <row>
- <entry>start&nbsp;+&nbsp;0:</entry>
- <entry>Z<subscript>00low</subscript></entry>
- <entry>Z<subscript>00high</subscript></entry>
- <entry>Z<subscript>01low</subscript></entry>
- <entry>Z<subscript>01high</subscript></entry>
- <entry>Z<subscript>02low</subscript></entry>
- <entry>Z<subscript>02high</subscript></entry>
- <entry>Z<subscript>03low</subscript></entry>
- <entry>Z<subscript>03high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;8:</entry>
- <entry>Z<subscript>10low</subscript></entry>
- <entry>Z<subscript>10high</subscript></entry>
- <entry>Z<subscript>11low</subscript></entry>
- <entry>Z<subscript>11high</subscript></entry>
- <entry>Z<subscript>12low</subscript></entry>
- <entry>Z<subscript>12high</subscript></entry>
- <entry>Z<subscript>13low</subscript></entry>
- <entry>Z<subscript>13high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;16:</entry>
- <entry>Z<subscript>20low</subscript></entry>
- <entry>Z<subscript>20high</subscript></entry>
- <entry>Z<subscript>21low</subscript></entry>
- <entry>Z<subscript>21high</subscript></entry>
- <entry>Z<subscript>22low</subscript></entry>
- <entry>Z<subscript>22high</subscript></entry>
- <entry>Z<subscript>23low</subscript></entry>
- <entry>Z<subscript>23high</subscript></entry>
- </row>
- <row>
- <entry>start&nbsp;+&nbsp;24:</entry>
- <entry>Z<subscript>30low</subscript></entry>
- <entry>Z<subscript>30high</subscript></entry>
- <entry>Z<subscript>31low</subscript></entry>
- <entry>Z<subscript>31high</subscript></entry>
- <entry>Z<subscript>32low</subscript></entry>
- <entry>Z<subscript>32high</subscript></entry>
- <entry>Z<subscript>33low</subscript></entry>
- <entry>Z<subscript>33high</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </formalpara>
- </example>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
deleted file mode 100644
index 5a08aeea4360..000000000000
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ /dev/null
@@ -1,2003 +0,0 @@
- <title>Image Formats</title>
-
- <para>The V4L2 API was primarily designed for devices exchanging
-image data with applications. The
-<structname>v4l2_pix_format</structname> and <structname>v4l2_pix_format_mplane
-</structname> structures define the format and layout of an image in memory.
-The former is used with the single-planar API, while the latter is used with the
-multi-planar version (see <xref linkend="planar-apis"/>). Image formats are
-negotiated with the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video
-capturing and output, for overlay frame buffer formats see also
-&VIDIOC-G-FBUF;.)</para>
-
-<section>
- <title>Single-planar format structure</title>
- <table pgwide="1" frame="none" id="v4l2-pix-format">
- <title>struct <structname>v4l2_pix_format</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Image width in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Image height in pixels. If <structfield>field</structfield> is
- one of <constant>V4L2_FIELD_TOP</constant>, <constant>V4L2_FIELD_BOTTOM</constant>
- or <constant>V4L2_FIELD_ALTERNATE</constant> then height refers to the
- number of lines in the field, otherwise it refers to the number of
- lines in the frame (which is twice the field height for interlaced
- formats).</entry>
- </row>
- <row>
- <entry spanname="hspan">Applications set these fields to
-request an image size, drivers return the closest possible values. In
-case of planar formats the <structfield>width</structfield> and
-<structfield>height</structfield> applies to the largest plane. To
-avoid ambiguities drivers must return values rounded up to a multiple
-of the scale factor of any smaller planes. For example when the image
-format is YUV 4:2:0, <structfield>width</structfield> and
-<structfield>height</structfield> must be multiples of two.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixelformat</structfield></entry>
- <entry>The pixel format or type of compression, set by the
-application. This is a little endian <link
-linkend="v4l2-fourcc">four character code</link>. V4L2 defines
-standard RGB formats in <xref linkend="rgb-formats" />, YUV formats in <xref
-linkend="yuv-formats" />, and reserved codes in <xref
-linkend="reserved-formats" /></entry>
- </row>
- <row>
- <entry>&v4l2-field;</entry>
- <entry><structfield>field</structfield></entry>
- <entry>Video images are typically interlaced. Applications
-can request to capture or output only the top or bottom field, or both
-fields interlaced or sequentially stored in one buffer or alternating
-in separate buffers. Drivers return the actual field order selected.
-For more details on fields see <xref linkend="field-order" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>bytesperline</structfield></entry>
- <entry>Distance in bytes between the leftmost pixels in two
-adjacent lines.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>Both applications and drivers
-can set this field to request padding bytes at the end of each line.
-Drivers however may ignore the value requested by the application,
-returning <structfield>width</structfield> times bytes per pixel or a
-larger value required by the hardware. That implies applications can
-just set this field to zero to get a reasonable
-default.</para><para>Video hardware may access padding bytes,
-therefore they must reside in accessible memory. Consider cases where
-padding bytes after the last line of an image cross a system page
-boundary. Input devices may write padding bytes, the value is
-undefined. Output devices ignore the contents of padding
-bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the first
-plane and is divided by the same factor as the
-<structfield>width</structfield> field for the other planes. For
-example the Cb and Cr planes of a YUV 4:2:0 image have half as many
-padding bytes following each line as the Y plane. To avoid ambiguities
-drivers must return a <structfield>bytesperline</structfield> value
-rounded up to a multiple of the scale factor.</para>
-<para>For compressed formats the <structfield>bytesperline</structfield>
-value makes no sense. Applications and drivers must set this to 0 in
-that case.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sizeimage</structfield></entry>
- <entry>Size in bytes of the buffer to hold a complete image,
-set by the driver. Usually this is
-<structfield>bytesperline</structfield> times
-<structfield>height</structfield>. When the image consists of variable
-length compressed data this is the maximum number of bytes required to
-hold an image.</entry>
- </row>
- <row>
- <entry>&v4l2-colorspace;</entry>
- <entry><structfield>colorspace</structfield></entry>
- <entry>This information supplements the
-<structfield>pixelformat</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>priv</structfield></entry>
- <entry><para>This field indicates whether the remaining fields of the
-<structname>v4l2_pix_format</structname> structure, also called the extended
-fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
-indicates that the extended fields have been correctly initialized. When set to
-any other value it indicates that the extended fields contain undefined values.
-</para>
-<para>Applications that wish to use the pixel format extended fields must first
-ensure that the feature is supported by querying the device for the
-<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
-capability. If the capability isn't set the pixel format extended fields are not
-supported and using the extended fields will lead to undefined results.</para>
-<para>To use the extended fields, applications must set the
-<structfield>priv</structfield> field to
-<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
-and zero the unused bytes of the <structname>v4l2_format</structname>
-<structfield>raw_data</structfield> field.</para>
-<para>When the <structfield>priv</structfield> field isn't set to
-<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
-extended fields were set to zero. On return drivers must set the
-<structfield>priv</structfield> field to
-<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended fields to
-applicable values.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags set by the application or driver, see <xref
-linkend="format-flags" />.</entry>
- </row>
- <row>
- <entry>&v4l2-ycbcr-encoding;</entry>
- <entry><structfield>ycbcr_enc</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-quantization;</entry>
- <entry><structfield>quantization</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-xfer-func;</entry>
- <entry><structfield>xfer_func</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-</section>
-
-<section>
- <title>Multi-planar format structures</title>
- <para>The <structname>v4l2_plane_pix_format</structname> structures define
- size and layout for each of the planes in a multi-planar format.
- The <structname>v4l2_pix_format_mplane</structname> structure contains
- information common to all planes (such as image width and height) and
- 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>v4l2_plane_pix_format</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>sizeimage</structfield></entry>
- <entry>Maximum size in bytes required for image data in this plane.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>bytesperline</structfield></entry>
- <entry>Distance in bytes between the leftmost pixels in two adjacent
- lines. See &v4l2-pix-format;.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>reserved[6]</structfield></entry>
- <entry>Reserved for future extensions. Should be zeroed by drivers and
- applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table pgwide="1" frame="none" id="v4l2-pix-format-mplane">
- <title>struct <structname>v4l2_pix_format_mplane</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Image width in pixels. See &v4l2-pix-format;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Image height in pixels. See &v4l2-pix-format;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixelformat</structfield></entry>
- <entry>The pixel format. Both single- and multi-planar four character
-codes can be used.</entry>
- </row>
- <row>
- <entry>&v4l2-field;</entry>
- <entry><structfield>field</structfield></entry>
- <entry>See &v4l2-pix-format;.</entry>
- </row>
- <row>
- <entry>&v4l2-colorspace;</entry>
- <entry><structfield>colorspace</structfield></entry>
- <entry>See &v4l2-pix-format;.</entry>
- </row>
- <row>
- <entry>&v4l2-plane-pix-format;</entry>
- <entry><structfield>plane_fmt[VIDEO_MAX_PLANES]</structfield></entry>
- <entry>An array of structures describing format of each plane this
- pixel format consists of. The number of valid entries in this array
- has to be put in the <structfield>num_planes</structfield>
- field.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>num_planes</structfield></entry>
- <entry>Number of planes (i.e. separate memory buffers) for this format
- and the number of valid entries in the
- <structfield>plane_fmt</structfield> array.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags set by the application or driver, see <xref
-linkend="format-flags" />.</entry>
- </row>
- <row>
- <entry>&v4l2-ycbcr-encoding;</entry>
- <entry><structfield>ycbcr_enc</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-quantization;</entry>
- <entry><structfield>quantization</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-xfer-func;</entry>
- <entry><structfield>xfer_func</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>reserved[7]</structfield></entry>
- <entry>Reserved for future extensions. Should be zeroed by drivers
- and applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-</section>
-
- <section>
- <title>Standard Image Formats</title>
-
- <para>In order to exchange images between drivers and
-applications, it is necessary to have standard image data formats
-which both sides will interpret the same way. V4L2 includes several
-such formats, and this section is intended to be an unambiguous
-specification of the standard image data formats in V4L2.</para>
-
- <para>V4L2 drivers are not limited to these formats, however.
-Driver-specific formats are possible. In that case the application may
-depend on a codec to convert images to one of the standard formats
-when needed. But the data can still be stored and retrieved in the
-proprietary format. For example, a device may support a proprietary
-compressed format. Applications can still capture and save the data in
-the compressed format, saving much disk space, and later use a codec
-to convert the images to the X Windows screen format when the video is
-to be displayed.</para>
-
- <para>Even so, ultimately, some standard formats are needed, so
-the V4L2 specification would not be complete without well-defined
-standard formats.</para>
-
- <para>The V4L2 standard formats are mainly uncompressed formats. The
-pixels are always arranged in memory from left to right, and from top
-to bottom. The first byte of data in the image buffer is always for
-the leftmost pixel of the topmost row. Following that is the pixel
-immediately to its right, and so on until the end of the top row of
-pixels. Following the rightmost pixel of the row there may be zero or
-more bytes of padding to guarantee that each row of pixel data has a
-certain alignment. Following the pad bytes, if any, is data for the
-leftmost pixel of the second row from the top, and so on. The last row
-has just as many pad bytes after it as the other rows.</para>
-
- <para>In V4L2 each format has an identifier which looks like
-<constant>PIX_FMT_XXX</constant>, defined in the <link
-linkend="videodev">videodev2.h</link> header file. These identifiers
-represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
-which are also listed below, however they are not the same as those
-used in the Windows world.</para>
-
- <para>For some formats, data is stored in separate, discontiguous
-memory buffers. Those formats are identified by a separate set of FourCC codes
-and are referred to as "multi-planar formats". For example, a YUV422 frame is
-normally stored in one memory buffer, but it can also be placed in two or three
-separate buffers, with Y component in one buffer and CbCr components in another
-in the 2-planar version or with each component in its own buffer in the
-3-planar case. Those sub-buffers are referred to as "planes".</para>
- </section>
-
- <section id="colorspaces">
- <title>Colorspaces</title>
-
- <para>'Color' is a very complex concept and depends on physics, chemistry and
-biology. Just because you have three numbers that describe the 'red', 'green'
-and 'blue' components of the color of a pixel does not mean that you can accurately
-display that color. A colorspace defines what it actually <emphasis>means</emphasis>
-to have an RGB value of e.g. (255,&nbsp;0,&nbsp;0). That is, which color should be
-reproduced on the screen in a perfectly calibrated environment.</para>
-
- <para>In order to do that we first need to have a good definition of
-color, i.e. some way to uniquely and unambiguously define a color so that someone
-else can reproduce it. Human color vision is trichromatic since the human eye has
-color receptors that are sensitive to three different wavelengths of light. Hence
-the need to use three numbers to describe color. Be glad you are not a mantis shrimp
-as those are sensitive to 12 different wavelengths, so instead of RGB we would be
-using the ABCDEFGHIJKL colorspace...</para>
-
- <para>Color exists only in the eye and brain and is the result of how strongly
-color receptors are stimulated. This is based on the Spectral
-Power Distribution (SPD) which is a graph showing the intensity (radiant power)
-of the light at wavelengths covering the visible spectrum as it enters the eye.
-The science of colorimetry is about the relationship between the SPD and color as
-perceived by the human brain.</para>
-
- <para>Since the human eye has only three color receptors it is perfectly
-possible that different SPDs will result in the same stimulation of those receptors
-and are perceived as the same color, even though the SPD of the light is
-different.</para>
-
- <para>In the 1920s experiments were devised to determine the relationship
-between SPDs and the perceived color and that resulted in the CIE 1931 standard
-that defines spectral weighting functions that model the perception of color.
-Specifically that standard defines functions that can take an SPD and calculate
-the stimulus for each color receptor. After some further mathematical transforms
-these stimuli are known as the <emphasis>CIE XYZ tristimulus</emphasis> values
-and these X, Y and Z values describe a color as perceived by a human unambiguously.
-These X, Y and Z values are all in the range [0&hellip;1].</para>
-
- <para>The Y value in the CIE XYZ colorspace corresponds to luminance. Often
-the CIE XYZ colorspace is transformed to the normalized CIE xyY colorspace:</para>
-
- <para>x = X / (X + Y + Z)</para>
- <para>y = Y / (X + Y + Z)</para>
-
- <para>The x and y values are the chromaticity coordinates and can be used to
-define a color without the luminance component Y. It is very confusing to
-have such similar names for these colorspaces. Just be aware that if colors
-are specified with lower case 'x' and 'y', then the CIE xyY colorspace is
-used. Upper case 'X' and 'Y' refer to the CIE XYZ colorspace. Also, y has nothing
-to do with luminance. Together x and y specify a color, and Y the luminance.
-That is really all you need to remember from a practical point of view. At
-the end of this section you will find reading resources that go into much more
-detail if you are interested.
-</para>
-
- <para>A monitor or TV will reproduce colors by emitting light at three
-different wavelengths, the combination of which will stimulate the color receptors
-in the eye and thus cause the perception of color. Historically these wavelengths
-were defined by the red, green and blue phosphors used in the displays. These
-<emphasis>color primaries</emphasis> are part of what defines a colorspace.</para>
-
- <para>Different display devices will have different primaries and some
-primaries are more suitable for some display technologies than others. This has
-resulted in a variety of colorspaces that are used for different display
-technologies or uses. To define a colorspace you need to define the three
-color primaries (these are typically defined as x,&nbsp;y chromaticity coordinates
-from the CIE xyY colorspace) but also the white reference: that is the color obtained
-when all three primaries are at maximum power. This determines the relative power
-or energy of the primaries. This is usually chosen to be close to daylight which has
-been defined as the CIE D65 Illuminant.</para>
-
- <para>To recapitulate: the CIE XYZ colorspace uniquely identifies colors.
-Other colorspaces are defined by three chromaticity coordinates defined in the
-CIE xyY colorspace. Based on those a 3x3 matrix can be constructed that
-transforms CIE XYZ colors to colors in the new colorspace.
-</para>
-
- <para>Both the CIE XYZ and the RGB colorspace that are derived from the
-specific chromaticity primaries are linear colorspaces. But neither the eye,
-nor display technology is linear. Doubling the values of all components in
-the linear colorspace will not be perceived as twice the intensity of the color.
-So each colorspace also defines a transfer function that takes a linear color
-component value and transforms it to the non-linear component value, which is a
-closer match to the non-linear performance of both the eye and displays. Linear
-component values are denoted RGB, non-linear are denoted as R'G'B'. In general
-colors used in graphics are all R'G'B', except in openGL which uses linear RGB.
-Special care should be taken when dealing with openGL to provide linear RGB colors
-or to use the built-in openGL support to apply the inverse transfer function.</para>
-
- <para>The final piece that defines a colorspace is a function that
-transforms non-linear R'G'B' to non-linear Y'CbCr. This function is determined
-by the so-called luma coefficients. There may be multiple possible Y'CbCr
-encodings allowed for the same colorspace. Many encodings of color
-prefer to use luma (Y') and chroma (CbCr) instead of R'G'B'. Since the human
-eye is more sensitive to differences in luminance than in color this encoding
-allows one to reduce the amount of color information compared to the luma
-data. Note that the luma (Y') is unrelated to the Y in the CIE XYZ colorspace.
-Also note that Y'CbCr is often called YCbCr or YUV even though these are
-strictly speaking wrong.</para>
-
- <para>Sometimes people confuse Y'CbCr as being a colorspace. This is not
-correct, it is just an encoding of an R'G'B' color into luma and chroma
-values. The underlying colorspace that is associated with the R'G'B' color
-is also associated with the Y'CbCr color.</para>
-
- <para>The final step is how the RGB, R'G'B' or Y'CbCr values are
-quantized. The CIE XYZ colorspace where X, Y and Z are in the range
-[0&hellip;1] describes all colors that humans can perceive, but the transform to
-another colorspace will produce colors that are outside the [0&hellip;1] range.
-Once clamped to the [0&hellip;1] range those colors can no longer be reproduced
-in that colorspace. This clamping is what reduces the extent or gamut of the
-colorspace. How the range of [0&hellip;1] is translated to integer values in the
-range of [0&hellip;255] (or higher, depending on the color depth) is called the
-quantization. This is <emphasis>not</emphasis> part of the colorspace
-definition. In practice RGB or R'G'B' values are full range, i.e. they
-use the full [0&hellip;255] range. Y'CbCr values on the other hand are limited
-range with Y' using [16&hellip;235] and Cb and Cr using [16&hellip;240].</para>
-
- <para>Unfortunately, in some cases limited range RGB is also used
-where the components use the range [16&hellip;235]. And full range Y'CbCr also exists
-using the [0&hellip;255] range.</para>
-
- <para>In order to correctly interpret a color you need to know the
-quantization range, whether it is R'G'B' or Y'CbCr, the used Y'CbCr encoding
-and the colorspace.
-From that information you can calculate the corresponding CIE XYZ color
-and map that again to whatever colorspace your display device uses.</para>
-
- <para>The colorspace definition itself consists of the three
-chromaticity primaries, the white reference chromaticity, a transfer
-function and the luma coefficients needed to transform R'G'B' to Y'CbCr. While
-some colorspace standards correctly define all four, quite often the colorspace
-standard only defines some, and you have to rely on other standards for
-the missing pieces. The fact that colorspaces are often a mix of different
-standards also led to very confusing naming conventions where the name of
-a standard was used to name a colorspace when in fact that standard was
-part of various other colorspaces as well.</para>
-
- <para>If you want to read more about colors and colorspaces, then the
-following resources are useful: <xref linkend="poynton" /> is a good practical
-book for video engineers, <xref linkend="colimg" /> has a much broader scope and
-describes many more aspects of color (physics, chemistry, biology, etc.).
-The <ulink url="http://www.brucelindbloom.com">http://www.brucelindbloom.com</ulink>
-website is an excellent resource, especially with respect to the mathematics behind
-colorspace conversions. The wikipedia <ulink url="http://en.wikipedia.org/wiki/CIE_1931_color_space#CIE_xy_chromaticity_diagram_and_the_CIE_xyY_color_space">CIE 1931 colorspace</ulink> article
-is also very useful.</para>
- </section>
-
- <section>
- <title>Defining Colorspaces in V4L2</title>
- <para>In V4L2 colorspaces are defined by four values. The first is the colorspace
-identifier (&v4l2-colorspace;) which defines the chromaticities, the default transfer
-function, the default Y'CbCr encoding and the default quantization method. The second
-is the transfer function identifier (&v4l2-xfer-func;) to specify non-standard
-transfer functions. The third is the Y'CbCr encoding identifier (&v4l2-ycbcr-encoding;)
-to specify non-standard Y'CbCr encodings and the fourth is the quantization identifier
-(&v4l2-quantization;) to specify non-standard quantization methods. Most of the time
-only the colorspace field of &v4l2-pix-format; or &v4l2-pix-format-mplane; needs to
-be filled in. Note that the default R'G'B' quantization is full range for all
-colorspaces except for BT.2020 which uses limited range R'G'B' quantization.</para>
-
- <table pgwide="1" frame="none" id="v4l2-colorspace">
- <title>V4L2 Colorspaces</title>
- <tgroup cols="2" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_COLORSPACE_DEFAULT</constant></entry>
- <entry>The default colorspace. This can be used by applications to let the
- driver fill in the colorspace.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_SMPTE170M</constant></entry>
- <entry>See <xref linkend="col-smpte-170m" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_REC709</constant></entry>
- <entry>See <xref linkend="col-rec709" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_SRGB</constant></entry>
- <entry>See <xref linkend="col-srgb" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_ADOBERGB</constant></entry>
- <entry>See <xref linkend="col-adobergb" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_BT2020</constant></entry>
- <entry>See <xref linkend="col-bt2020" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_DCI_P3</constant></entry>
- <entry>See <xref linkend="col-dcip3" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_SMPTE240M</constant></entry>
- <entry>See <xref linkend="col-smpte-240m" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_470_SYSTEM_M</constant></entry>
- <entry>See <xref linkend="col-sysm" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant></entry>
- <entry>See <xref linkend="col-sysbg" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_JPEG</constant></entry>
- <entry>See <xref linkend="col-jpeg" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_COLORSPACE_RAW</constant></entry>
- <entry>The raw colorspace. This is used for raw image capture where
- the image is minimally processed and is using the internal colorspace
- of the device. The software that processes an image using this
- 'colorspace' will have to know the internals of the capture device.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-xfer-func">
- <title>V4L2 Transfer Function</title>
- <tgroup cols="2" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_XFER_FUNC_DEFAULT</constant></entry>
- <entry>Use the default transfer function as defined by the colorspace.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_709</constant></entry>
- <entry>Use the Rec. 709 transfer function.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_SRGB</constant></entry>
- <entry>Use the sRGB transfer function.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_ADOBERGB</constant></entry>
- <entry>Use the AdobeRGB transfer function.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_SMPTE240M</constant></entry>
- <entry>Use the SMPTE 240M transfer function.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_NONE</constant></entry>
- <entry>Do not use a transfer function (i.e. use linear RGB values).</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_DCI_P3</constant></entry>
- <entry>Use the DCI-P3 transfer function.</entry>
- </row>
- <row>
- <entry><constant>V4L2_XFER_FUNC_SMPTE2084</constant></entry>
- <entry>Use the SMPTE 2084 transfer function.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-ycbcr-encoding">
- <title>V4L2 Y'CbCr Encodings</title>
- <tgroup cols="2" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_YCBCR_ENC_DEFAULT</constant></entry>
- <entry>Use the default Y'CbCr encoding as defined by the colorspace.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_601</constant></entry>
- <entry>Use the BT.601 Y'CbCr encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_709</constant></entry>
- <entry>Use the Rec. 709 Y'CbCr encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_XV601</constant></entry>
- <entry>Use the extended gamut xvYCC BT.601 encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_XV709</constant></entry>
- <entry>Use the extended gamut xvYCC Rec. 709 encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_SYCC</constant></entry>
- <entry>Use the extended gamut sYCC encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_BT2020</constant></entry>
- <entry>Use the default non-constant luminance BT.2020 Y'CbCr encoding.</entry>
- </row>
- <row>
- <entry><constant>V4L2_YCBCR_ENC_BT2020_CONST_LUM</constant></entry>
- <entry>Use the constant luminance BT.2020 Yc'CbcCrc encoding.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-quantization">
- <title>V4L2 Quantization Methods</title>
- <tgroup cols="2" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_QUANTIZATION_DEFAULT</constant></entry>
- <entry>Use the default quantization encoding as defined by the colorspace.
-This is always full range for R'G'B' (except for the BT.2020 colorspace) and usually
-limited range for Y'CbCr.</entry>
- </row>
- <row>
- <entry><constant>V4L2_QUANTIZATION_FULL_RANGE</constant></entry>
- <entry>Use the full range quantization encoding. I.e. the range [0&hellip;1]
-is mapped to [0&hellip;255] (with possible clipping to [1&hellip;254] to avoid the
-0x00 and 0xff values). Cb and Cr are mapped from [-0.5&hellip;0.5] to [0&hellip;255]
-(with possible clipping to [1&hellip;254] to avoid the 0x00 and 0xff values).</entry>
- </row>
- <row>
- <entry><constant>V4L2_QUANTIZATION_LIM_RANGE</constant></entry>
- <entry>Use the limited range quantization encoding. I.e. the range [0&hellip;1]
-is mapped to [16&hellip;235]. Cb and Cr are mapped from [-0.5&hellip;0.5] to [16&hellip;240].
-</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Detailed Colorspace Descriptions</title>
- <section id="col-smpte-170m">
- <title>Colorspace SMPTE 170M (<constant>V4L2_COLORSPACE_SMPTE170M</constant>)</title>
- <para>The <xref linkend="smpte170m" /> standard defines the colorspace used by NTSC and PAL and by SDTV
-in general. The default transfer function is <constant>V4L2_XFER_FUNC_709</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>.
-The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and
-the white reference are:</para>
- <table frame="none">
- <title>SMPTE 170M Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.630</entry>
- <entry>0.340</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.310</entry>
- <entry>0.595</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.155</entry>
- <entry>0.070</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>The red, green and blue chromaticities are also often referred to
-as the SMPTE C set, so this colorspace is sometimes called SMPTE C as well.</para>
- <variablelist>
- <varlistentry>
- <term>The transfer function defined for SMPTE 170M is the same as the
-one defined in Rec. 709.</term>
- <listitem>
- <para>L' = -1.099(-L)<superscript>0.45</superscript>&nbsp;+&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&le;&nbsp;-0.018</para>
- <para>L' = 4.5L&nbsp;for&nbsp;-0.018&nbsp;&lt;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
- <para>L' = 1.099L<superscript>0.45</superscript>&nbsp;-&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&ge;&nbsp;0.018</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = -((L'&nbsp;-&nbsp;0.099)&nbsp;/&nbsp;-1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&le;&nbsp;-0.081</para>
- <para>L = L'&nbsp;/&nbsp;4.5&nbsp;for&nbsp;-0.081&nbsp;&lt;&nbsp;L'&nbsp;&lt;&nbsp;0.081</para>
- <para>L = ((L'&nbsp;+&nbsp;0.099)&nbsp;/&nbsp;1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.081</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with
-the following <constant>V4L2_YCBCR_ENC_601</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B'</para>
- <para>Cb&nbsp;=&nbsp;-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5]. This conversion to Y'CbCr is identical to the one
-defined in the <xref linkend="itu601" /> standard and this colorspace is sometimes called BT.601 as well, even
-though BT.601 does not mention any color primaries.</para>
- <para>The default quantization is limited range, but full range is possible although
-rarely seen.</para>
- </section>
-
- <section id="col-rec709">
- <title>Colorspace Rec. 709 (<constant>V4L2_COLORSPACE_REC709</constant>)</title>
- <para>The <xref linkend="itu709" /> standard defines the colorspace used by HDTV in general.
-The default transfer function is <constant>V4L2_XFER_FUNC_709</constant>. The default
-Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_709</constant>. The default Y'CbCr quantization is
-limited range. The chromaticities of the primary colors and the white reference are:</para>
- <table frame="none">
- <title>Rec. 709 Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.640</entry>
- <entry>0.330</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.300</entry>
- <entry>0.600</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.150</entry>
- <entry>0.060</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>The full name of this standard is Rec. ITU-R BT.709-5.</para>
- <variablelist>
- <varlistentry>
- <term>Transfer function. Normally L is in the range [0&hellip;1], but for the extended
-gamut xvYCC encoding values outside that range are allowed.</term>
- <listitem>
- <para>L' = -1.099(-L)<superscript>0.45</superscript>&nbsp;+&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&le;&nbsp;-0.018</para>
- <para>L' = 4.5L&nbsp;for&nbsp;-0.018&nbsp;&lt;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
- <para>L' = 1.099L<superscript>0.45</superscript>&nbsp;-&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&ge;&nbsp;0.018</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = -((L'&nbsp;-&nbsp;0.099)&nbsp;/&nbsp;-1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&le;&nbsp;-0.081</para>
- <para>L = L'&nbsp;/&nbsp;4.5&nbsp;for&nbsp;-0.081&nbsp;&lt;&nbsp;L'&nbsp;&lt;&nbsp;0.081</para>
- <para>L = ((L'&nbsp;+&nbsp;0.099)&nbsp;/&nbsp;1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.081</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the following
-<constant>V4L2_YCBCR_ENC_709</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B'</para>
- <para>Cb&nbsp;=&nbsp;-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5].</para>
- <para>The default quantization is limited range, but full range is possible although
-rarely seen.</para>
- <para>The <constant>V4L2_YCBCR_ENC_709</constant> encoding described above is the default
-for this colorspace, but it can be overridden with <constant>V4L2_YCBCR_ENC_601</constant>, in which
-case the BT.601 Y'CbCr encoding is used.</para>
- <para>Two additional extended gamut Y'CbCr encodings are also possible with this colorspace:</para>
- <variablelist>
- <varlistentry>
- <term>The xvYCC 709 encoding (<constant>V4L2_YCBCR_ENC_XV709</constant>, <xref linkend="xvycc" />)
-is similar to the Rec. 709 encoding, but it allows for R', G' and B' values that are outside the range
-[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
- <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B')</para>
- <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B')</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The xvYCC 601 encoding (<constant>V4L2_YCBCR_ENC_XV601</constant>, <xref linkend="xvycc" />) is similar
-to the BT.601 encoding, but it allows for R', G' and B' values that are outside the range
-[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
- <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B')</para>
- <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B')</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The non-standard xvYCC 709 or xvYCC 601 encodings can be used by
-selecting <constant>V4L2_YCBCR_ENC_XV709</constant> or <constant>V4L2_YCBCR_ENC_XV601</constant>.
-The xvYCC encodings always use full range quantization.</para>
- </section>
-
- <section id="col-srgb">
- <title>Colorspace sRGB (<constant>V4L2_COLORSPACE_SRGB</constant>)</title>
- <para>The <xref linkend="srgb" /> standard defines the colorspace used by most webcams
-and computer graphics. The default transfer function is <constant>V4L2_XFER_FUNC_SRGB</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SYCC</constant>. The default Y'CbCr
-quantization is full range. The chromaticities of the primary colors and the white
-reference are:</para>
- <table frame="none">
- <title>sRGB Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.640</entry>
- <entry>0.330</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.300</entry>
- <entry>0.600</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.150</entry>
- <entry>0.060</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>These chromaticities are identical to the Rec. 709 colorspace.</para>
- <variablelist>
- <varlistentry>
- <term>Transfer function. Note that negative values for L are only used by the Y'CbCr conversion.</term>
- <listitem>
- <para>L' = -1.055(-L)<superscript>1/2.4</superscript>&nbsp;+&nbsp;0.055&nbsp;for&nbsp;L&nbsp;&lt;&nbsp;-0.0031308</para>
- <para>L' = 12.92L&nbsp;for&nbsp;-0.0031308&nbsp;&le;&nbsp;L&nbsp;&le;&nbsp;0.0031308</para>
- <para>L' = 1.055L<superscript>1/2.4</superscript>&nbsp;-&nbsp;0.055&nbsp;for&nbsp;0.0031308&nbsp;&lt;&nbsp;L&nbsp;&le;&nbsp;1</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = -((-L'&nbsp;+&nbsp;0.055)&nbsp;/&nbsp;1.055)<superscript>2.4</superscript>&nbsp;for&nbsp;L'&nbsp;&lt;&nbsp;-0.04045</para>
- <para>L = L'&nbsp;/&nbsp;12.92&nbsp;for&nbsp;-0.04045&nbsp;&le;&nbsp;L'&nbsp;&le;&nbsp;0.04045</para>
- <para>L = ((L'&nbsp;+&nbsp;0.055)&nbsp;/&nbsp;1.055)<superscript>2.4</superscript>&nbsp;for&nbsp;L'&nbsp;&gt;&nbsp;0.04045</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the following
-<constant>V4L2_YCBCR_ENC_SYCC</constant> encoding as defined by <xref linkend="sycc" />:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.2990R'&nbsp;+&nbsp;0.5870G'&nbsp;+&nbsp;0.1140B'</para>
- <para>Cb&nbsp;=&nbsp;-0.1687R'&nbsp;-&nbsp;0.3313G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4187G'&nbsp;-&nbsp;0.0813B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The <constant>V4L2_YCBCR_ENC_SYCC</constant> quantization is always
-full range. Although this Y'CbCr encoding looks very similar to the <constant>V4L2_YCBCR_ENC_XV601</constant>
-encoding, it is not. The <constant>V4L2_YCBCR_ENC_XV601</constant> scales and offsets the Y'CbCr
-values before quantization, but this encoding does not do that.</para>
- </section>
-
- <section id="col-adobergb">
- <title>Colorspace Adobe RGB (<constant>V4L2_COLORSPACE_ADOBERGB</constant>)</title>
- <para>The <xref linkend="adobergb" /> standard defines the colorspace used by computer graphics
-that use the AdobeRGB colorspace. This is also known as the <xref linkend="oprgb" /> standard.
-The default transfer function is <constant>V4L2_XFER_FUNC_ADOBERGB</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr
-quantization is limited range. The chromaticities of the primary colors and the white reference
-are:</para>
- <table frame="none">
- <title>Adobe RGB Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.6400</entry>
- <entry>0.3300</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.2100</entry>
- <entry>0.7100</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.1500</entry>
- <entry>0.0600</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <variablelist>
- <varlistentry>
- <term>Transfer function:</term>
- <listitem>
- <para>L' = L<superscript>1/2.19921875</superscript></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'<superscript>2.19921875</superscript></para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
-following <constant>V4L2_YCBCR_ENC_601</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B'</para>
- <para>Cb&nbsp;=&nbsp;-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5]. This transform is identical to one defined in
-SMPTE 170M/BT.601. The Y'CbCr quantization is limited range.</para>
- </section>
-
- <section id="col-bt2020">
- <title>Colorspace BT.2020 (<constant>V4L2_COLORSPACE_BT2020</constant>)</title>
- <para>The <xref linkend="itu2020" /> standard defines the colorspace used by Ultra-high definition
-television (UHDTV). The default transfer function is <constant>V4L2_XFER_FUNC_709</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_BT2020</constant>.
-The default R'G'B' quantization is limited range (!), and so is the default Y'CbCr quantization.
-The chromaticities of the primary colors and the white reference are:</para>
- <table frame="none">
- <title>BT.2020 Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.708</entry>
- <entry>0.292</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.170</entry>
- <entry>0.797</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.131</entry>
- <entry>0.046</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <variablelist>
- <varlistentry>
- <term>Transfer function (same as Rec. 709):</term>
- <listitem>
- <para>L' = 4.5L&nbsp;for&nbsp;0&nbsp;&le;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
- <para>L' = 1.099L<superscript>0.45</superscript>&nbsp;-&nbsp;0.099&nbsp;for&nbsp;0.018&nbsp;&le;&nbsp;L&nbsp;&le;&nbsp;1</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'&nbsp;/&nbsp;4.5&nbsp;for&nbsp;L'&nbsp;&lt;&nbsp;0.081</para>
- <para>L = ((L'&nbsp;+&nbsp;0.099)&nbsp;/&nbsp;1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.081</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
-following <constant>V4L2_YCBCR_ENC_BT2020</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.2627R'&nbsp;+&nbsp;0.6780G'&nbsp;+&nbsp;0.0593B'</para>
- <para>Cb&nbsp;=&nbsp;-0.1396R'&nbsp;-&nbsp;0.3604G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4598G'&nbsp;-&nbsp;0.0402B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.</para>
- <para>There is also an alternate constant luminance R'G'B' to Yc'CbcCrc
-(<constant>V4L2_YCBCR_ENC_BT2020_CONST_LUM</constant>) encoding:</para>
- <variablelist>
- <varlistentry>
- <term>Luma:</term>
- <listitem>
- <para>Yc'&nbsp;=&nbsp;(0.2627R&nbsp;+&nbsp;0.6780G&nbsp;+&nbsp;0.0593B)'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>B'&nbsp;-&nbsp;Yc'&nbsp;&le;&nbsp;0:</term>
- <listitem>
- <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.9404</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>B'&nbsp;-&nbsp;Yc'&nbsp;&gt;&nbsp;0:</term>
- <listitem>
- <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.5816</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>R'&nbsp;-&nbsp;Yc'&nbsp;&le;&nbsp;0:</term>
- <listitem>
- <para>Crc&nbsp;=&nbsp;(R'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;1.7184</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>R'&nbsp;-&nbsp;Yc'&nbsp;&gt;&nbsp;0:</term>
- <listitem>
- <para>Crc&nbsp;=&nbsp;(R'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;0.9936</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Yc' is clamped to the range [0&hellip;1] and Cbc and Crc are
-clamped to the range [-0.5&hellip;0.5]. The Yc'CbcCrc quantization is limited range.</para>
- </section>
-
- <section id="col-dcip3">
- <title>Colorspace DCI-P3 (<constant>V4L2_COLORSPACE_DCI_P3</constant>)</title>
- <para>The <xref linkend="smpte431" /> standard defines the colorspace used by cinema
-projectors that use the DCI-P3 colorspace.
-The default transfer function is <constant>V4L2_XFER_FUNC_DCI_P3</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_709</constant>. Note that this
-colorspace does not specify a Y'CbCr encoding since it is not meant to be encoded
-to Y'CbCr. So this default Y'CbCr encoding was picked because it is the HDTV
-encoding. The default Y'CbCr quantization is limited range. The chromaticities of
-the primary colors and the white reference are:</para>
- <table frame="none">
- <title>DCI-P3 Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.6800</entry>
- <entry>0.3200</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.2650</entry>
- <entry>0.6900</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.1500</entry>
- <entry>0.0600</entry>
- </row>
- <row>
- <entry>White Reference</entry>
- <entry>0.3140</entry>
- <entry>0.3510</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <variablelist>
- <varlistentry>
- <term>Transfer function:</term>
- <listitem>
- <para>L' = L<superscript>1/2.6</superscript></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'<superscript>2.6</superscript></para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y'CbCr encoding is not specified. V4L2 defaults to Rec. 709.</para>
- </section>
-
- <section id="col-smpte-240m">
- <title>Colorspace SMPTE 240M (<constant>V4L2_COLORSPACE_SMPTE240M</constant>)</title>
- <para>The <xref linkend="smpte240m" /> standard was an interim standard used during
-the early days of HDTV (1988-1998). It has been superseded by Rec. 709.
-The default transfer function is <constant>V4L2_XFER_FUNC_SMPTE240M</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SMPTE240M</constant>.
-The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and the
-white reference are:</para>
- <table frame="none">
- <title>SMPTE 240M Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.630</entry>
- <entry>0.340</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.310</entry>
- <entry>0.595</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.155</entry>
- <entry>0.070</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>These chromaticities are identical to the SMPTE 170M colorspace.</para>
- <variablelist>
- <varlistentry>
- <term>Transfer function:</term>
- <listitem>
- <para>L' = 4L&nbsp;for&nbsp;0&nbsp;&le;&nbsp;L&nbsp;&lt;&nbsp;0.0228</para>
- <para>L' = 1.1115L<superscript>0.45</superscript>&nbsp;-&nbsp;0.1115&nbsp;for&nbsp;0.0228&nbsp;&le;&nbsp;L&nbsp;&le;&nbsp;1</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'&nbsp;/&nbsp;4&nbsp;for&nbsp;0&nbsp;&le;&nbsp;L'&nbsp;&lt;&nbsp;0.0913</para>
- <para>L = ((L'&nbsp;+&nbsp;0.1115)&nbsp;/&nbsp;1.1115)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.0913</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
-following <constant>V4L2_YCBCR_ENC_SMPTE240M</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.2122R'&nbsp;+&nbsp;0.7013G'&nbsp;+&nbsp;0.0865B'</para>
- <para>Cb&nbsp;=&nbsp;-0.1161R'&nbsp;-&nbsp;0.3839G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4451G'&nbsp;-&nbsp;0.0549B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Yc' is clamped to the range [0&hellip;1] and Cbc and Crc are
-clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.</para>
- </section>
-
- <section id="col-sysm">
- <title>Colorspace NTSC 1953 (<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant>)</title>
- <para>This standard defines the colorspace used by NTSC in 1953. In practice this
-colorspace is obsolete and SMPTE 170M should be used instead.
-The default transfer function is <constant>V4L2_XFER_FUNC_709</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>.
-The default Y'CbCr quantization is limited range.
-The chromaticities of the primary colors and the white reference are:</para>
- <table frame="none">
- <title>NTSC 1953 Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.67</entry>
- <entry>0.33</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.21</entry>
- <entry>0.71</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.14</entry>
- <entry>0.08</entry>
- </row>
- <row>
- <entry>White Reference (C)</entry>
- <entry>0.310</entry>
- <entry>0.316</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>Note that this colorspace uses Illuminant C instead of D65 as the
-white reference. To correctly convert an image in this colorspace to another
-that uses D65 you need to apply a chromatic adaptation algorithm such as the
-Bradford method.</para>
- <variablelist>
- <varlistentry>
- <term>The transfer function was never properly defined for NTSC 1953. The
-Rec. 709 transfer function is recommended in the literature:</term>
- <listitem>
- <para>L' = 4.5L&nbsp;for&nbsp;0&nbsp;&le;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
- <para>L' = 1.099L<superscript>0.45</superscript>&nbsp;-&nbsp;0.099&nbsp;for&nbsp;0.018&nbsp;&le;&nbsp;L&nbsp;&le;&nbsp;1</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'&nbsp;/&nbsp;4.5&nbsp;for&nbsp;L'&nbsp;&lt;&nbsp;0.081</para>
- <para>L = ((L'&nbsp;+&nbsp;0.099)&nbsp;/&nbsp;1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.081</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
-following <constant>V4L2_YCBCR_ENC_601</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B'</para>
- <para>Cb&nbsp;=&nbsp;-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.
-This transform is identical to one defined in SMPTE 170M/BT.601.</para>
- </section>
-
- <section id="col-sysbg">
- <title>Colorspace EBU Tech. 3213 (<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant>)</title>
- <para>The <xref linkend="tech3213" /> standard defines the colorspace used by PAL/SECAM in 1975. In practice this
-colorspace is obsolete and SMPTE 170M should be used instead.
-The default transfer function is <constant>V4L2_XFER_FUNC_709</constant>.
-The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>.
-The default Y'CbCr quantization is limited range.
-The chromaticities of the primary colors and the white reference are:</para>
- <table frame="none">
- <title>EBU Tech. 3213 Chromaticities</title>
- <tgroup cols="3" align="left">
- &cs-str;
- <thead>
- <row>
- <entry>Color</entry>
- <entry>x</entry>
- <entry>y</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Red</entry>
- <entry>0.64</entry>
- <entry>0.33</entry>
- </row>
- <row>
- <entry>Green</entry>
- <entry>0.29</entry>
- <entry>0.60</entry>
- </row>
- <row>
- <entry>Blue</entry>
- <entry>0.15</entry>
- <entry>0.06</entry>
- </row>
- <row>
- <entry>White Reference (D65)</entry>
- <entry>0.3127</entry>
- <entry>0.3290</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <variablelist>
- <varlistentry>
- <term>The transfer function was never properly defined for this colorspace.
-The Rec. 709 transfer function is recommended in the literature:</term>
- <listitem>
- <para>L' = 4.5L&nbsp;for&nbsp;0&nbsp;&le;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
- <para>L' = 1.099L<superscript>0.45</superscript>&nbsp;-&nbsp;0.099&nbsp;for&nbsp;0.018&nbsp;&le;&nbsp;L&nbsp;&le;&nbsp;1</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = L'&nbsp;/&nbsp;4.5&nbsp;for&nbsp;L'&nbsp;&lt;&nbsp;0.081</para>
- <para>L = ((L'&nbsp;+&nbsp;0.099)&nbsp;/&nbsp;1.099)<superscript>1/0.45</superscript>&nbsp;for&nbsp;L'&nbsp;&ge;&nbsp;0.081</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
-following <constant>V4L2_YCBCR_ENC_601</constant> encoding:</term>
- <listitem>
- <para>Y'&nbsp;=&nbsp;0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B'</para>
- <para>Cb&nbsp;=&nbsp;-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B'</para>
- <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B'</para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are
-clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.
-This transform is identical to one defined in SMPTE 170M/BT.601.</para>
- </section>
-
- <section id="col-jpeg">
- <title>Colorspace JPEG (<constant>V4L2_COLORSPACE_JPEG</constant>)</title>
- <para>This colorspace defines the colorspace used by most (Motion-)JPEG formats. The chromaticities
-of the primary colors and the white reference are identical to sRGB. The transfer
-function use is <constant>V4L2_XFER_FUNC_SRGB</constant>. The Y'CbCr encoding is
-<constant>V4L2_YCBCR_ENC_601</constant> with full range quantization where
-Y' is scaled to [0&hellip;255] and Cb/Cr are scaled to [-128&hellip;128] and
-then clipped to [-128&hellip;127].</para>
- <para>Note that the JPEG standard does not actually store colorspace information.
-So if something other than sRGB is used, then the driver will have to set that information
-explicitly. Effectively <constant>V4L2_COLORSPACE_JPEG</constant> can be considered to be
-an abbreviation for <constant>V4L2_COLORSPACE_SRGB</constant>, <constant>V4L2_YCBCR_ENC_601</constant>
-and <constant>V4L2_QUANTIZATION_FULL_RANGE</constant>.</para>
- </section>
-
- </section>
-
- <section>
- <title>Detailed Transfer Function Descriptions</title>
- <section id="xf-smpte-2084">
- <title>Transfer Function SMPTE 2084 (<constant>V4L2_XFER_FUNC_SMPTE2084</constant>)</title>
- <para>The <xref linkend="smpte2084" /> standard defines the transfer function used by
-High Dynamic Range content.</para>
- <variablelist>
- <varlistentry>
- <term>Constants:</term>
- <listitem>
- <para>m1 = (2610 / 4096) / 4</para>
- <para>m2 = (2523 / 4096) * 128</para>
- <para>c1 = 3424 / 4096</para>
- <para>c2 = (2413 / 4096) * 32</para>
- <para>c3 = (2392 / 4096) * 32</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Transfer function:</term>
- <listitem>
- <para>L' = ((c1 + c2 * L<superscript>m1</superscript>) / (1 + c3 * L<superscript>m1</superscript>))<superscript>m2</superscript></para>
- </listitem>
- </varlistentry>
- </variablelist>
- <variablelist>
- <varlistentry>
- <term>Inverse Transfer function:</term>
- <listitem>
- <para>L = (max(L'<superscript>1/m2</superscript> - c1, 0) / (c2 - c3 * L'<superscript>1/m2</superscript>))<superscript>1/m1</superscript></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </section>
- </section>
-
- <section id="pixfmt-indexed">
- <title>Indexed Format</title>
-
- <para>In this format each pixel is represented by an 8 bit index
-into a 256 entry ARGB palette. It is intended for <link
-linkend="osd">Video Output Overlays</link> only. There are no ioctls to
-access the palette, this must be done with ioctls of the Linux framebuffer API.</para>
-
- <table pgwide="0" frame="none">
- <title>Indexed Image Format</title>
- <tgroup cols="37" align="center">
- <colspec colname="id" align="left" />
- <colspec colname="fourcc" />
- <colspec colname="bit" />
-
- <colspec colnum="4" colname="b07" align="center" />
- <colspec colnum="5" colname="b06" align="center" />
- <colspec colnum="6" colname="b05" align="center" />
- <colspec colnum="7" colname="b04" align="center" />
- <colspec colnum="8" colname="b03" align="center" />
- <colspec colnum="9" colname="b02" align="center" />
- <colspec colnum="10" colname="b01" align="center" />
- <colspec colnum="11" colname="b00" align="center" />
-
- <spanspec namest="b07" nameend="b00" spanname="b0" />
- <spanspec namest="b17" nameend="b10" spanname="b1" />
- <spanspec namest="b27" nameend="b20" spanname="b2" />
- <spanspec namest="b37" nameend="b30" spanname="b3" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>&nbsp;</entry>
- <entry spanname="b0">Byte&nbsp;0</entry>
- </row>
- <row>
- <entry>&nbsp;</entry>
- <entry>&nbsp;</entry>
- <entry>Bit</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="V4L2-PIX-FMT-PAL8">
- <entry><constant>V4L2_PIX_FMT_PAL8</constant></entry>
- <entry>'PAL8'</entry>
- <entry></entry>
- <entry>i<subscript>7</subscript></entry>
- <entry>i<subscript>6</subscript></entry>
- <entry>i<subscript>5</subscript></entry>
- <entry>i<subscript>4</subscript></entry>
- <entry>i<subscript>3</subscript></entry>
- <entry>i<subscript>2</subscript></entry>
- <entry>i<subscript>1</subscript></entry>
- <entry>i<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="pixfmt-rgb">
- <title>RGB Formats</title>
-
- &sub-packed-rgb;
- &sub-sbggr8;
- &sub-sgbrg8;
- &sub-sgrbg8;
- &sub-srggb8;
- &sub-sbggr16;
- &sub-srggb10;
- &sub-srggb10p;
- &sub-srggb10alaw8;
- &sub-srggb10dpcm8;
- &sub-srggb12;
- </section>
-
- <section id="yuv-formats">
- <title>YUV Formats</title>
-
- <para>YUV is the format native to TV broadcast and composite video
-signals. It separates the brightness information (Y) from the color
-information (U and V or Cb and Cr). The color information consists of
-red and blue <emphasis>color difference</emphasis> signals, this way
-the green component can be reconstructed by subtracting from the
-brightness component. See <xref linkend="colorspaces" /> for conversion
-examples. YUV was chosen because early television would only transmit
-brightness information. To add color in a way compatible with existing
-receivers a new signal carrier was added to transmit the color
-difference signals. Secondary in the YUV format the U and V components
-usually have lower resolution than the Y component. This is an analog
-video compression technique taking advantage of a property of the
-human visual system, being more sensitive to brightness
-information.</para>
-
- &sub-packed-yuv;
- &sub-grey;
- &sub-y10;
- &sub-y12;
- &sub-y10b;
- &sub-y16;
- &sub-y16-be;
- &sub-y8i;
- &sub-y12i;
- &sub-uv8;
- &sub-yuyv;
- &sub-uyvy;
- &sub-yvyu;
- &sub-vyuy;
- &sub-y41p;
- &sub-yuv420;
- &sub-yuv420m;
- &sub-yuv422m;
- &sub-yuv444m;
- &sub-yuv410;
- &sub-yuv422p;
- &sub-yuv411p;
- &sub-nv12;
- &sub-nv12m;
- &sub-nv12mt;
- &sub-nv16;
- &sub-nv16m;
- &sub-nv24;
- &sub-m420;
- </section>
-
- <section id="depth-formats">
- <title>Depth Formats</title>
- <para>Depth data provides distance to points, mapped onto the image plane
- </para>
-
- &sub-z16;
- </section>
-
- <section>
- <title>Compressed Formats</title>
-
- <table pgwide="1" frame="none" id="compressed-formats">
- <title>Compressed Image Formats</title>
- <tgroup cols="3" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="V4L2-PIX-FMT-JPEG">
- <entry><constant>V4L2_PIX_FMT_JPEG</constant></entry>
- <entry>'JPEG'</entry>
- <entry>TBD. See also &VIDIOC-G-JPEGCOMP;,
- &VIDIOC-S-JPEGCOMP;.</entry>
- </row>
- <row id="V4L2-PIX-FMT-MPEG">
- <entry><constant>V4L2_PIX_FMT_MPEG</constant></entry>
- <entry>'MPEG'</entry>
- <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-H264-MVC">
- <entry><constant>V4L2_PIX_FMT_H264_MVC</constant></entry>
- <entry>'M264'</entry>
- <entry>H264 MVC video elementary stream.</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>
- <row id="V4L2-PIX-FMT-VP8">
- <entry><constant>V4L2_PIX_FMT_VP8</constant></entry>
- <entry>'VP80'</entry>
- <entry>VP8 video elementary stream.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="sdr-formats">
- <title>SDR Formats</title>
-
- <para>These formats are used for <link linkend="sdr">SDR</link>
-interface only.</para>
-
- &sub-sdr-cu08;
- &sub-sdr-cu16le;
- &sub-sdr-cs08;
- &sub-sdr-cs14le;
- &sub-sdr-ru12le;
-
- </section>
-
- <section id="pixfmt-reserved">
- <title>Reserved Format Identifiers</title>
-
- <para>These formats are not defined by this specification, they
-are just listed for reference and to avoid naming conflicts. If you
-want to register your own format, send an e-mail to the linux-media mailing
-list &v4l-ml; for inclusion in the <filename>videodev2.h</filename>
-file. If you want to share your format with other developers add a
-link to your documentation and send a copy to the linux-media mailing list
-for inclusion in this section. If you think your format should be listed
-in a standard format section please make a proposal on the linux-media mailing
-list.</para>
-
- <table pgwide="1" frame="none" id="reserved-formats">
- <title>Reserved Image Formats</title>
- <tgroup cols="3" align="left">
- &cs-def;
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>Details</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="V4L2-PIX-FMT-DV">
- <entry><constant>V4L2_PIX_FMT_DV</constant></entry>
- <entry>'dvsd'</entry>
- <entry>unknown</entry>
- </row>
- <row id="V4L2-PIX-FMT-ET61X251">
- <entry><constant>V4L2_PIX_FMT_ET61X251</constant></entry>
- <entry>'E625'</entry>
- <entry>Compressed format of the ET61X251 driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-HI240">
- <entry><constant>V4L2_PIX_FMT_HI240</constant></entry>
- <entry>'HI24'</entry>
- <entry><para>8 bit RGB format used by the BTTV driver.</para></entry>
- </row>
- <row id="V4L2-PIX-FMT-HM12">
- <entry><constant>V4L2_PIX_FMT_HM12</constant></entry>
- <entry>'HM12'</entry>
- <entry><para>YUV 4:2:0 format used by the
-IVTV driver, <ulink url="http://www.ivtvdriver.org/">
-http://www.ivtvdriver.org/</ulink></para><para>The format is documented in the
-kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm12</filename>
-</para></entry>
- </row>
- <row id="V4L2-PIX-FMT-CPIA1">
- <entry><constant>V4L2_PIX_FMT_CPIA1</constant></entry>
- <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>
- <entry>YUYV per line used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SPCA505">
- <entry><constant>V4L2_PIX_FMT_SPCA505</constant></entry>
- <entry>'S505'</entry>
- <entry>YYUV per line used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SPCA508">
- <entry><constant>V4L2_PIX_FMT_SPCA508</constant></entry>
- <entry>'S508'</entry>
- <entry>YUVY per line used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SPCA561">
- <entry><constant>V4L2_PIX_FMT_SPCA561</constant></entry>
- <entry>'S561'</entry>
- <entry>Compressed GBRG Bayer format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-PAC207">
- <entry><constant>V4L2_PIX_FMT_PAC207</constant></entry>
- <entry>'P207'</entry>
- <entry>Compressed BGGR Bayer format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-MR97310A">
- <entry><constant>V4L2_PIX_FMT_MR97310A</constant></entry>
- <entry>'M310'</entry>
- <entry>Compressed BGGR Bayer format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-JL2005BCD">
- <entry><constant>V4L2_PIX_FMT_JL2005BCD</constant></entry>
- <entry>'JL20'</entry>
- <entry>JPEG compressed RGGB Bayer format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-OV511">
- <entry><constant>V4L2_PIX_FMT_OV511</constant></entry>
- <entry>'O511'</entry>
- <entry>OV511 JPEG format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-OV518">
- <entry><constant>V4L2_PIX_FMT_OV518</constant></entry>
- <entry>'O518'</entry>
- <entry>OV518 JPEG format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-PJPG">
- <entry><constant>V4L2_PIX_FMT_PJPG</constant></entry>
- <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>
- <entry>Compressed RGGB bayer format used by the gspca driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-MJPEG">
- <entry><constant>V4L2_PIX_FMT_MJPEG</constant></entry>
- <entry>'MJPG'</entry>
- <entry>Compressed format used by the Zoran driver</entry>
- </row>
- <row id="V4L2-PIX-FMT-PWC1">
- <entry><constant>V4L2_PIX_FMT_PWC1</constant></entry>
- <entry>'PWC1'</entry>
- <entry>Compressed format of the PWC driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-PWC2">
- <entry><constant>V4L2_PIX_FMT_PWC2</constant></entry>
- <entry>'PWC2'</entry>
- <entry>Compressed format of the PWC driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SN9C10X">
- <entry><constant>V4L2_PIX_FMT_SN9C10X</constant></entry>
- <entry>'S910'</entry>
- <entry>Compressed format of the SN9C102 driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SN9C20X-I420">
- <entry><constant>V4L2_PIX_FMT_SN9C20X_I420</constant></entry>
- <entry>'S920'</entry>
- <entry>YUV 4:2:0 format of the gspca sn9c20x driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-SN9C2028">
- <entry><constant>V4L2_PIX_FMT_SN9C2028</constant></entry>
- <entry>'SONX'</entry>
- <entry>Compressed GBRG bayer format of the gspca sn9c2028 driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-STV0680">
- <entry><constant>V4L2_PIX_FMT_STV0680</constant></entry>
- <entry>'S680'</entry>
- <entry>Bayer format of the gspca stv0680 driver.</entry>
- </row>
- <row id="V4L2-PIX-FMT-WNVA">
- <entry><constant>V4L2_PIX_FMT_WNVA</constant></entry>
- <entry>'WNVA'</entry>
- <entry><para>Used by the Winnov Videum driver, <ulink
-url="http://www.thedirks.org/winnov/">
-http://www.thedirks.org/winnov/</ulink></para></entry>
- </row>
- <row id="V4L2-PIX-FMT-TM6000">
- <entry><constant>V4L2_PIX_FMT_TM6000</constant></entry>
- <entry>'TM60'</entry>
- <entry><para>Used by Trident tm6000</para></entry>
- </row>
- <row id="V4L2-PIX-FMT-CIT-YYVYUY">
- <entry><constant>V4L2_PIX_FMT_CIT_YYVYUY</constant></entry>
- <entry>'CITV'</entry>
- <entry><para>Used by xirlink CIT, found at IBM webcams.</para>
- <para>Uses one line of Y then 1 line of VYUY</para>
- </entry>
- </row>
- <row id="V4L2-PIX-FMT-KONICA420">
- <entry><constant>V4L2_PIX_FMT_KONICA420</constant></entry>
- <entry>'KONI'</entry>
- <entry><para>Used by Konica webcams.</para>
- <para>YUV420 planar in blocks of 256 pixels.</para>
- </entry>
- </row>
- <row id="V4L2-PIX-FMT-YYUV">
- <entry><constant>V4L2_PIX_FMT_YYUV</constant></entry>
- <entry>'YYUV'</entry>
- <entry>unknown</entry>
- </row>
- <row id="V4L2-PIX-FMT-Y4">
- <entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
- <entry>'Y04 '</entry>
- <entry>Old 4-bit greyscale format. Only the most significant 4 bits of each byte are used,
-the other bits are set to 0.</entry>
- </row>
- <row id="V4L2-PIX-FMT-Y6">
- <entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
- <entry>'Y06 '</entry>
- <entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
-the other bits are set to 0.</entry>
- </row>
- <row id="V4L2-PIX-FMT-S5C-UYVY-JPG">
- <entry><constant>V4L2_PIX_FMT_S5C_UYVY_JPG</constant></entry>
- <entry>'S5CI'</entry>
- <entry>Two-planar format used by Samsung S5C73MX cameras. The
-first plane contains interleaved JPEG and UYVY image data, followed by meta data
-in form of an array of offsets to the UYVY data blocks. The actual pointer array
-follows immediately the interleaved JPEG/UYVY data, the number of entries in
-this array equals the height of the UYVY image. Each entry is a 4-byte unsigned
-integer in big endian order and it's an offset to a single pixel line of the
-UYVY image. The first plane can start either with JPEG or UYVY data chunk. The
-size of a single UYVY block equals the UYVY image's width multiplied by 2. The
-size of a JPEG chunk depends on the image and can vary with each line.
-<para>The second plane, at an offset of 4084 bytes, contains a 4-byte offset to
-the pointer array in the first plane. This offset is followed by a 4-byte value
-indicating size of the pointer array. All numbers in the second plane are also
-in big endian order. Remaining data in the second plane is undefined. The
-information in the second plane allows to easily find location of the pointer
-array, which can be different for each frame. The size of the pointer array is
-constant for given UYVY image height.</para>
-<para>In order to extract UYVY and JPEG frames an application can initially set
-a data pointer to the start of first plane and then add an offset from the first
-entry of the pointers table. Such a pointer indicates start of an UYVY image
-pixel line. Whole UYVY line can be copied to a separate buffer. These steps
-should be repeated for each line, i.e. the number of entries in the pointer
-array. Anything what's in between the UYVY lines is JPEG data and should be
-concatenated to form the JPEG stream. </para>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="format-flags">
- <title>Format Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_PIX_FMT_FLAG_PREMUL_ALPHA</constant></entry>
- <entry>0x00000001</entry>
- <entry>The color values are premultiplied by the alpha channel
-value. For example, if a light blue pixel with 50% transparency was described by
-RGBA values (128, 192, 255, 128), the same pixel described with premultiplied
-colors would be described by RGBA values (64, 96, 128, 128) </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
diff --git a/Documentation/DocBook/media/v4l/planar-apis.xml b/Documentation/DocBook/media/v4l/planar-apis.xml
deleted file mode 100644
index 878ce2040488..000000000000
--- a/Documentation/DocBook/media/v4l/planar-apis.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<section id="planar-apis">
- <title>Single- and multi-planar APIs</title>
-
- <para>Some devices require data for each input or output video frame
- to be placed in discontiguous memory buffers. In such cases, one
- video frame has to be addressed using more than one memory address, i.e. one
- pointer per "plane". A plane is a sub-buffer of the current frame. For
- examples of such formats see <xref linkend="pixfmt" />.</para>
-
- <para>Initially, V4L2 API did not support multi-planar buffers and a set of
- extensions has been introduced to handle them. Those extensions constitute
- what is being referred to as the "multi-planar API".</para>
-
- <para>Some of the V4L2 API calls and structures are interpreted differently,
- depending on whether single- or multi-planar API is being used. An application
- can choose whether to use one or the other by passing a corresponding buffer
- type to its ioctl calls. Multi-planar versions of buffer types are suffixed
- with an `_MPLANE' string. For a list of available multi-planar buffer types
- see &v4l2-buf-type;.
- </para>
-
- <section>
- <title>Multi-planar formats</title>
- <para>Multi-planar API introduces new multi-planar formats. Those formats
- use a separate set of FourCC codes. It is important to distinguish between
- the multi-planar API and a multi-planar format. Multi-planar API calls can
- handle all single-planar formats as well (as long as they are passed in
- multi-planar API structures), while the single-planar API cannot
- handle multi-planar formats.</para>
- </section>
-
- <section>
- <title>Calls that distinguish between single and multi-planar APIs</title>
- <variablelist>
- <varlistentry>
- <term>&VIDIOC-QUERYCAP;</term>
- <listitem><para>Two additional multi-planar capabilities are added. They can
- be set together with non-multi-planar ones for devices that handle
- both single- and multi-planar formats.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term>&VIDIOC-G-FMT;, &VIDIOC-S-FMT;, &VIDIOC-TRY-FMT;</term>
- <listitem><para>New structures for describing multi-planar formats are added:
- &v4l2-pix-format-mplane; and &v4l2-plane-pix-format;. Drivers may
- define new multi-planar formats, which have distinct FourCC codes from
- the existing single-planar ones.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>&VIDIOC-QBUF;, &VIDIOC-DQBUF;, &VIDIOC-QUERYBUF;</term>
- <listitem><para>A new &v4l2-plane; structure for describing planes is added.
- Arrays of this structure are passed in the new
- <structfield>m.planes</structfield> field of &v4l2-buffer;.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>&VIDIOC-REQBUFS;</term>
- <listitem><para>Will allocate multi-planar buffers as requested.</para></listitem>
- </varlistentry>
- </variablelist>
- </section>
-</section>
diff --git a/Documentation/DocBook/media/v4l/remote_controllers.xml b/Documentation/DocBook/media/v4l/remote_controllers.xml
deleted file mode 100644
index b86844e80257..000000000000
--- a/Documentation/DocBook/media/v4l/remote_controllers.xml
+++ /dev/null
@@ -1,320 +0,0 @@
-<partinfo>
-<authorgroup>
-<author>
-<firstname>Mauro</firstname>
-<surname>Chehab</surname>
-<othername role="mi">Carvalho</othername>
-<affiliation><address><email>m.chehab@samsung.com</email></address></affiliation>
-<contrib>Initial version.</contrib>
-</author>
-</authorgroup>
-<copyright>
- <year>2009-2014</year>
- <holder>Mauro Carvalho Chehab</holder>
-</copyright>
-
-<revhistory>
-<!-- Put document revisions here, newest first. -->
-<revision>
-<revnumber>3.15</revnumber>
-<date>2014-02-06</date>
-<authorinitials>mcc</authorinitials>
-<revremark>Added the interface description and the RC sysfs class description.</revremark>
-</revision>
-<revision>
-<revnumber>1.0</revnumber>
-<date>2009-09-06</date>
-<authorinitials>mcc</authorinitials>
-<revremark>Initial revision</revremark>
-</revision>
-</revhistory>
-</partinfo>
-
- <title>Remote Controller API</title>
- <chapter id="remote_controllers">
-
-<title>Remote Controllers</title>
-
-<section id="Remote_controllers_Intro">
-<title>Introduction</title>
-
-<para>Currently, most analog and digital devices have a Infrared input for remote controllers. Each
-manufacturer has their own type of control. It is not rare for the same manufacturer to ship different
-types of controls, depending on the device.</para>
-<para>A Remote Controller interface is mapped as a normal evdev/input interface, just like a keyboard or a mouse.
-So, it uses all ioctls already defined for any other input devices.</para>
-<para>However, remove controllers are more flexible than a normal input device, as the IR
-receiver (and/or transmitter) can be used in conjunction with a wide variety of different IR remotes.</para>
-<para>In order to allow flexibility, the Remote Controller subsystem allows controlling the
-RC-specific attributes via <link linkend="remote_controllers_sysfs_nodes">the sysfs class nodes</link>.</para>
-</section>
-
-<section id="remote_controllers_sysfs_nodes">
-<title>Remote Controller's sysfs nodes</title>
-<para>As defined at <constant>Documentation/ABI/testing/sysfs-class-rc</constant>, those are the sysfs nodes that control the Remote Controllers:</para>
-
-<section id="sys_class_rc">
-<title>/sys/class/rc/</title>
-<para>The <constant>/sys/class/rc/</constant> class sub-directory belongs to the Remote Controller
-core and provides a sysfs interface for configuring infrared remote controller receivers.
-</para>
-
-</section>
-<section id="sys_class_rc_rcN">
-<title>/sys/class/rc/rcN/</title>
-<para>A <constant>/sys/class/rc/rcN</constant> directory is created for each remote
- control receiver device where N is the number of the receiver.</para>
-
-</section>
-<section id="sys_class_rc_rcN_protocols">
-<title>/sys/class/rc/rcN/protocols</title>
-<para>Reading this file returns a list of available protocols, something like:</para>
-<para><constant>rc5 [rc6] nec jvc [sony]</constant></para>
-<para>Enabled protocols are shown in [] brackets.</para>
-<para>Writing "+proto" will add a protocol to the list of enabled protocols.</para>
-<para>Writing "-proto" will remove a protocol from the list of enabled protocols.</para>
-<para>Writing "proto" will enable only "proto".</para>
-<para>Writing "none" will disable all protocols.</para>
-<para>Write fails with EINVAL if an invalid protocol combination or unknown protocol name is used.</para>
-
-</section>
-<section id="sys_class_rc_rcN_filter">
-<title>/sys/class/rc/rcN/filter</title>
-<para>Sets the scancode filter expected value.</para>
-<para>Use in combination with <constant>/sys/class/rc/rcN/filter_mask</constant> to set the
-expected value of the bits set in the filter mask.
-If the hardware supports it then scancodes which do not match
-the filter will be ignored. Otherwise the write will fail with
-an error.</para>
-<para>This value may be reset to 0 if the current protocol is altered.</para>
-
-</section>
-<section id="sys_class_rc_rcN_filter_mask">
-<title>/sys/class/rc/rcN/filter_mask</title>
-<para>Sets the scancode filter mask of bits to compare.
-Use in combination with <constant>/sys/class/rc/rcN/filter</constant> to set the bits
-of the scancode which should be compared against the expected
-value. A value of 0 disables the filter to allow all valid
-scancodes to be processed.</para>
-<para>If the hardware supports it then scancodes which do not match
-the filter will be ignored. Otherwise the write will fail with
-an error.</para>
-<para>This value may be reset to 0 if the current protocol is altered.</para>
-
-</section>
-<section id="sys_class_rc_rcN_wakeup_protocols">
-<title>/sys/class/rc/rcN/wakeup_protocols</title>
-<para>Reading this file returns a list of available protocols to use for the
-wakeup filter, something like:</para>
-<para><constant>rc5 rc6 nec jvc [sony]</constant></para>
-<para>The enabled wakeup protocol is shown in [] brackets.</para>
-<para>Writing "+proto" will add a protocol to the list of enabled wakeup
-protocols.</para>
-<para>Writing "-proto" will remove a protocol from the list of enabled wakeup
-protocols.</para>
-<para>Writing "proto" will use "proto" for wakeup events.</para>
-<para>Writing "none" will disable wakeup.</para>
-<para>Write fails with EINVAL if an invalid protocol combination or unknown
-protocol name is used, or if wakeup is not supported by the hardware.</para>
-
-</section>
-<section id="sys_class_rc_rcN_wakeup_filter">
-<title>/sys/class/rc/rcN/wakeup_filter</title>
-<para>Sets the scancode wakeup filter expected value.
-Use in combination with <constant>/sys/class/rc/rcN/wakeup_filter_mask</constant> to
-set the expected value of the bits set in the wakeup filter mask
-to trigger a system wake event.</para>
-<para>If the hardware supports it and wakeup_filter_mask is not 0 then
-scancodes which match the filter will wake the system from e.g.
-suspend to RAM or power off.
-Otherwise the write will fail with an error.</para>
-<para>This value may be reset to 0 if the wakeup protocol is altered.</para>
-
-</section>
-<section id="sys_class_rc_rcN_wakeup_filter_mask">
-<title>/sys/class/rc/rcN/wakeup_filter_mask</title>
-<para>Sets the scancode wakeup filter mask of bits to compare.
-Use in combination with <constant>/sys/class/rc/rcN/wakeup_filter</constant> to set
-the bits of the scancode which should be compared against the
-expected value to trigger a system wake event.</para>
-<para>If the hardware supports it and wakeup_filter_mask is not 0 then
-scancodes which match the filter will wake the system from e.g.
-suspend to RAM or power off.
-Otherwise the write will fail with an error.</para>
-<para>This value may be reset to 0 if the wakeup protocol is altered.</para>
-</section>
-</section>
-
-<section id="Remote_controllers_tables">
-<title>Remote controller tables</title>
-<para>Unfortunately, for several years, there was no effort to create uniform IR keycodes for
-different devices. This caused the same IR keyname to be mapped completely differently on
-different IR devices. This resulted that the same IR keyname to be mapped completely different on
-different IR's. Due to that, V4L2 API now specifies a standard for mapping Media keys on IR.</para>
-<para>This standard should be used by both V4L/DVB drivers and userspace applications</para>
-<para>The modules register the remote as keyboard within the linux input layer. This means that the IR key strokes will look like normal keyboard key strokes (if CONFIG_INPUT_KEYBOARD is enabled). Using the event devices (CONFIG_INPUT_EVDEV) it is possible for applications to access the remote via /dev/input/event devices.</para>
-
-<table pgwide="1" frame="none" id="rc_standard_keymap">
-<title>IR default keymapping</title>
-<tgroup cols="3">
-&cs-str;
-<tbody valign="top">
-<row>
-<entry>Key code</entry>
-<entry>Meaning</entry>
-<entry>Key examples on IR</entry>
-</row>
-
-<row><entry><emphasis role="bold">Numeric keys</emphasis></entry></row>
-
-<row><entry><constant>KEY_0</constant></entry><entry>Keyboard digit 0</entry><entry>0</entry></row>
-<row><entry><constant>KEY_1</constant></entry><entry>Keyboard digit 1</entry><entry>1</entry></row>
-<row><entry><constant>KEY_2</constant></entry><entry>Keyboard digit 2</entry><entry>2</entry></row>
-<row><entry><constant>KEY_3</constant></entry><entry>Keyboard digit 3</entry><entry>3</entry></row>
-<row><entry><constant>KEY_4</constant></entry><entry>Keyboard digit 4</entry><entry>4</entry></row>
-<row><entry><constant>KEY_5</constant></entry><entry>Keyboard digit 5</entry><entry>5</entry></row>
-<row><entry><constant>KEY_6</constant></entry><entry>Keyboard digit 6</entry><entry>6</entry></row>
-<row><entry><constant>KEY_7</constant></entry><entry>Keyboard digit 7</entry><entry>7</entry></row>
-<row><entry><constant>KEY_8</constant></entry><entry>Keyboard digit 8</entry><entry>8</entry></row>
-<row><entry><constant>KEY_9</constant></entry><entry>Keyboard digit 9</entry><entry>9</entry></row>
-
-<row><entry><emphasis role="bold">Movie play control</emphasis></entry></row>
-
-<row><entry><constant>KEY_FORWARD</constant></entry><entry>Instantly advance in time</entry><entry>&gt;&gt; / FORWARD</entry></row>
-<row><entry><constant>KEY_BACK</constant></entry><entry>Instantly go back in time</entry><entry>&lt;&lt;&lt; / BACK</entry></row>
-<row><entry><constant>KEY_FASTFORWARD</constant></entry><entry>Play movie faster</entry><entry>&gt;&gt;&gt; / FORWARD</entry></row>
-<row><entry><constant>KEY_REWIND</constant></entry><entry>Play movie back</entry><entry>REWIND / BACKWARD</entry></row>
-<row><entry><constant>KEY_NEXT</constant></entry><entry>Select next chapter / sub-chapter / interval</entry><entry>NEXT / SKIP</entry></row>
-<row><entry><constant>KEY_PREVIOUS</constant></entry><entry>Select previous chapter / sub-chapter / interval</entry><entry>&lt;&lt; / PREV / PREVIOUS</entry></row>
-<row><entry><constant>KEY_AGAIN</constant></entry><entry>Repeat the video or a video interval</entry><entry>REPEAT / LOOP / RECALL</entry></row>
-<row><entry><constant>KEY_PAUSE</constant></entry><entry>Pause sroweam</entry><entry>PAUSE / FREEZE</entry></row>
-<row><entry><constant>KEY_PLAY</constant></entry><entry>Play movie at the normal timeshift</entry><entry>NORMAL TIMESHIFT / LIVE / &gt;</entry></row>
-<row><entry><constant>KEY_PLAYPAUSE</constant></entry><entry>Alternate between play and pause</entry><entry>PLAY / PAUSE</entry></row>
-<row><entry><constant>KEY_STOP</constant></entry><entry>Stop sroweam</entry><entry>STOP</entry></row>
-<row><entry><constant>KEY_RECORD</constant></entry><entry>Start/stop recording sroweam</entry><entry>CAPTURE / REC / RECORD/PAUSE</entry></row>
-<row><entry><constant>KEY_CAMERA</constant></entry><entry>Take a picture of the image</entry><entry>CAMERA ICON / CAPTURE / SNAPSHOT</entry></row>
-<row><entry><constant>KEY_SHUFFLE</constant></entry><entry>Enable shuffle mode</entry><entry>SHUFFLE</entry></row>
-<row><entry><constant>KEY_TIME</constant></entry><entry>Activate time shift mode</entry><entry>TIME SHIFT</entry></row>
-<row><entry><constant>KEY_TITLE</constant></entry><entry>Allow changing the chapter</entry><entry>CHAPTER</entry></row>
-<row><entry><constant>KEY_SUBTITLE</constant></entry><entry>Allow changing the subtitle</entry><entry>SUBTITLE</entry></row>
-
-<row><entry><emphasis role="bold">Image control</emphasis></entry></row>
-
-<row><entry><constant>KEY_BRIGHTNESSDOWN</constant></entry><entry>Decrease Brightness</entry><entry>BRIGHTNESS DECREASE</entry></row>
-<row><entry><constant>KEY_BRIGHTNESSUP</constant></entry><entry>Increase Brightness</entry><entry>BRIGHTNESS INCREASE</entry></row>
-
-<row><entry><constant>KEY_ANGLE</constant></entry><entry>Switch video camera angle (on videos with more than one angle stored)</entry><entry>ANGLE / SWAP</entry></row>
-<row><entry><constant>KEY_EPG</constant></entry><entry>Open the Elecrowonic Play Guide (EPG)</entry><entry>EPG / GUIDE</entry></row>
-<row><entry><constant>KEY_TEXT</constant></entry><entry>Activate/change closed caption mode</entry><entry>CLOSED CAPTION/TELETEXT / DVD TEXT / TELETEXT / TTX</entry></row>
-
-<row><entry><emphasis role="bold">Audio control</emphasis></entry></row>
-
-<row><entry><constant>KEY_AUDIO</constant></entry><entry>Change audio source</entry><entry>AUDIO SOURCE / AUDIO / MUSIC</entry></row>
-<row><entry><constant>KEY_MUTE</constant></entry><entry>Mute/unmute audio</entry><entry>MUTE / DEMUTE / UNMUTE</entry></row>
-<row><entry><constant>KEY_VOLUMEDOWN</constant></entry><entry>Decrease volume</entry><entry>VOLUME- / VOLUME DOWN</entry></row>
-<row><entry><constant>KEY_VOLUMEUP</constant></entry><entry>Increase volume</entry><entry>VOLUME+ / VOLUME UP</entry></row>
-<row><entry><constant>KEY_MODE</constant></entry><entry>Change sound mode</entry><entry>MONO/STEREO</entry></row>
-<row><entry><constant>KEY_LANGUAGE</constant></entry><entry>Select Language</entry><entry>1ST / 2ND LANGUAGE / DVD LANG / MTS/SAP / MTS SEL</entry></row>
-
-<row><entry><emphasis role="bold">Channel control</emphasis></entry></row>
-
-<row><entry><constant>KEY_CHANNEL</constant></entry><entry>Go to the next favorite channel</entry><entry>ALT / CHANNEL / CH SURFING / SURF / FAV</entry></row>
-<row><entry><constant>KEY_CHANNELDOWN</constant></entry><entry>Decrease channel sequencially</entry><entry>CHANNEL - / CHANNEL DOWN / DOWN</entry></row>
-<row><entry><constant>KEY_CHANNELUP</constant></entry><entry>Increase channel sequencially</entry><entry>CHANNEL + / CHANNEL UP / UP</entry></row>
-<row><entry><constant>KEY_DIGITS</constant></entry><entry>Use more than one digit for channel</entry><entry>PLUS / 100/ 1xx / xxx / -/-- / Single Double Triple Digit</entry></row>
-<row><entry><constant>KEY_SEARCH</constant></entry><entry>Start channel autoscan</entry><entry>SCAN / AUTOSCAN</entry></row>
-
-<row><entry><emphasis role="bold">Colored keys</emphasis></entry></row>
-
-<row><entry><constant>KEY_BLUE</constant></entry><entry>IR Blue key</entry><entry>BLUE</entry></row>
-<row><entry><constant>KEY_GREEN</constant></entry><entry>IR Green Key</entry><entry>GREEN</entry></row>
-<row><entry><constant>KEY_RED</constant></entry><entry>IR Red key</entry><entry>RED</entry></row>
-<row><entry><constant>KEY_YELLOW</constant></entry><entry>IR Yellow key</entry><entry> YELLOW</entry></row>
-
-<row><entry><emphasis role="bold">Media selection</emphasis></entry></row>
-
-<row><entry><constant>KEY_CD</constant></entry><entry>Change input source to Compact Disc</entry><entry>CD</entry></row>
-<row><entry><constant>KEY_DVD</constant></entry><entry>Change input to DVD</entry><entry>DVD / DVD MENU</entry></row>
-<row><entry><constant>KEY_EJECTCLOSECD</constant></entry><entry>Open/close the CD/DVD player</entry><entry>-&gt; ) / CLOSE / OPEN</entry></row>
-
-<row><entry><constant>KEY_MEDIA</constant></entry><entry>Turn on/off Media application</entry><entry>PC/TV / TURN ON/OFF APP</entry></row>
-<row><entry><constant>KEY_PC</constant></entry><entry>Selects from TV to PC</entry><entry>PC</entry></row>
-<row><entry><constant>KEY_RADIO</constant></entry><entry>Put into AM/FM radio mode</entry><entry>RADIO / TV/FM / TV/RADIO / FM / FM/RADIO</entry></row>
-<row><entry><constant>KEY_TV</constant></entry><entry>Select tv mode</entry><entry>TV / LIVE TV</entry></row>
-<row><entry><constant>KEY_TV2</constant></entry><entry>Select Cable mode</entry><entry>AIR/CBL</entry></row>
-<row><entry><constant>KEY_VCR</constant></entry><entry>Select VCR mode</entry><entry>VCR MODE / DTR</entry></row>
-<row><entry><constant>KEY_VIDEO</constant></entry><entry>Alternate between input modes</entry><entry>SOURCE / SELECT / DISPLAY / SWITCH INPUTS / VIDEO</entry></row>
-
-<row><entry><emphasis role="bold">Power control</emphasis></entry></row>
-
-<row><entry><constant>KEY_POWER</constant></entry><entry>Turn on/off computer</entry><entry>SYSTEM POWER / COMPUTER POWER</entry></row>
-<row><entry><constant>KEY_POWER2</constant></entry><entry>Turn on/off application</entry><entry>TV ON/OFF / POWER</entry></row>
-<row><entry><constant>KEY_SLEEP</constant></entry><entry>Activate sleep timer</entry><entry>SLEEP / SLEEP TIMER</entry></row>
-<row><entry><constant>KEY_SUSPEND</constant></entry><entry>Put computer into suspend mode</entry><entry>STANDBY / SUSPEND</entry></row>
-
-<row><entry><emphasis role="bold">Window control</emphasis></entry></row>
-
-<row><entry><constant>KEY_CLEAR</constant></entry><entry>Stop sroweam and return to default input video/audio</entry><entry>CLEAR / RESET / BOSS KEY</entry></row>
-<row><entry><constant>KEY_CYCLEWINDOWS</constant></entry><entry>Minimize windows and move to the next one</entry><entry>ALT-TAB / MINIMIZE / DESKTOP</entry></row>
-<row><entry><constant>KEY_FAVORITES</constant></entry><entry>Open the favorites sroweam window</entry><entry>TV WALL / Favorites</entry></row>
-<row><entry><constant>KEY_MENU</constant></entry><entry>Call application menu</entry><entry>2ND CONTROLS (USA: MENU) / DVD/MENU / SHOW/HIDE CTRL</entry></row>
-<row><entry><constant>KEY_NEW</constant></entry><entry>Open/Close Picture in Picture</entry><entry>PIP</entry></row>
-<row><entry><constant>KEY_OK</constant></entry><entry>Send a confirmation code to application</entry><entry>OK / ENTER / RETURN</entry></row>
-<row><entry><constant>KEY_SCREEN</constant></entry><entry>Select screen aspect ratio</entry><entry>4:3 16:9 SELECT</entry></row>
-<row><entry><constant>KEY_ZOOM</constant></entry><entry>Put device into zoom/full screen mode</entry><entry>ZOOM / FULL SCREEN / ZOOM+ / HIDE PANNEL / SWITCH</entry></row>
-
-<row><entry><emphasis role="bold">Navigation keys</emphasis></entry></row>
-
-<row><entry><constant>KEY_ESC</constant></entry><entry>Cancel current operation</entry><entry>CANCEL / BACK</entry></row>
-<row><entry><constant>KEY_HELP</constant></entry><entry>Open a Help window</entry><entry>HELP</entry></row>
-<row><entry><constant>KEY_HOMEPAGE</constant></entry><entry>Navigate to Homepage</entry><entry>HOME</entry></row>
-<row><entry><constant>KEY_INFO</constant></entry><entry>Open On Screen Display</entry><entry>DISPLAY INFORMATION / OSD</entry></row>
-<row><entry><constant>KEY_WWW</constant></entry><entry>Open the default browser</entry><entry>WEB</entry></row>
-<row><entry><constant>KEY_UP</constant></entry><entry>Up key</entry><entry>UP</entry></row>
-<row><entry><constant>KEY_DOWN</constant></entry><entry>Down key</entry><entry>DOWN</entry></row>
-<row><entry><constant>KEY_LEFT</constant></entry><entry>Left key</entry><entry>LEFT</entry></row>
-<row><entry><constant>KEY_RIGHT</constant></entry><entry>Right key</entry><entry>RIGHT</entry></row>
-
-<row><entry><emphasis role="bold">Miscellaneous keys</emphasis></entry></row>
-
-<row><entry><constant>KEY_DOT</constant></entry><entry>Return a dot</entry><entry>.</entry></row>
-<row><entry><constant>KEY_FN</constant></entry><entry>Select a function</entry><entry>FUNCTION</entry></row>
-
-</tbody>
-</tgroup>
-</table>
-
-<para>It should be noted that, sometimes, there some fundamental missing keys at some cheaper IR's. Due to that, it is recommended to:</para>
-
-<table pgwide="1" frame="none" id="rc_keymap_notes">
-<title>Notes</title>
-<tgroup cols="1">
-&cs-str;
-<tbody valign="top">
-<row>
-<entry>On simpler IR's, without separate channel keys, you need to map UP as <constant>KEY_CHANNELUP</constant></entry>
-</row><row>
-<entry>On simpler IR's, without separate channel keys, you need to map DOWN as <constant>KEY_CHANNELDOWN</constant></entry>
-</row><row>
-<entry>On simpler IR's, without separate volume keys, you need to map LEFT as <constant>KEY_VOLUMEDOWN</constant></entry>
-</row><row>
-<entry>On simpler IR's, without separate volume keys, you need to map RIGHT as <constant>KEY_VOLUMEUP</constant></entry>
-</row>
-</tbody>
-</tgroup>
-</table>
-
-</section>
-
-<section id="Remote_controllers_table_change">
-<title>Changing default Remote Controller mappings</title>
-<para>The event interface provides two ioctls to be used against
-the /dev/input/event device, to allow changing the default
-keymapping.</para>
-
-<para>This program demonstrates how to replace the keymap tables.</para>
-&sub-keytable-c;
-</section>
-
-&sub-lirc_device_interface;
-</chapter>
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
deleted file mode 100644
index b764cba150d1..000000000000
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ /dev/null
@@ -1,317 +0,0 @@
-<section id="selection-api">
-
- <title>API for cropping, composing and scaling</title>
-
- <section>
- <title>Introduction</title>
-
-<para>Some video capture devices can sample a subsection of a picture and
-shrink or enlarge it to an image of arbitrary size. Next, the devices can
-insert the image into larger one. Some video output devices can crop part of an
-input image, scale it up or down and insert it at an arbitrary scan line and
-horizontal offset into a video signal. We call these abilities cropping,
-scaling and composing.</para>
-
-<para>On a video <emphasis>capture</emphasis> device the source is a video
-signal, and the cropping target determine the area actually sampled. The sink
-is an image stored in a memory buffer. The composing area specifies which part
-of the buffer is actually written to by the hardware. </para>
-
-<para>On a video <emphasis>output</emphasis> device the source is an image in a
-memory buffer, and the cropping target is a part of an image to be shown on a
-display. The sink is the display or the graphics screen. The application may
-select the part of display where the image should be displayed. The size and
-position of such a window is controlled by the compose target.</para>
-
-<para>Rectangles for all cropping and composing targets are defined even if the
-device does supports neither cropping nor composing. Their size and position
-will be fixed in such a case. If the device does not support scaling then the
-cropping and composing rectangles have the same size.</para>
-
- </section>
-
- <section>
- <title>Selection targets</title>
-
- <para>
- <figure id="sel-targets-capture">
- <title>Cropping and composing targets</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="selection.png" format="PNG" />
- </imageobject>
- <textobject>
- <phrase>Targets used by a cropping, composing and scaling
- process</phrase>
- </textobject>
- </mediaobject>
- </figure>
- </para>
-
- <para>See <xref linkend="v4l2-selection-targets" /> for more
- information.</para>
- </section>
-
- <section>
-
- <title>Configuration</title>
-
-<para>Applications can use the <link linkend="vidioc-g-selection">selection
-API</link> to select an area in a video signal or a buffer, and to query for
-default settings and hardware limits.</para>
-
-<para>Video hardware can have various cropping, composing and scaling
-limitations. It may only scale up or down, support only discrete scaling
-factors, or have different scaling abilities in the horizontal and vertical
-directions. Also it may not support scaling at all. At the same time the
-cropping/composing rectangles may have to be aligned, and both the source and
-the sink may have arbitrary upper and lower size limits. Therefore, as usual,
-drivers are expected to adjust the requested parameters and return the actual
-values selected. An application can control the rounding behaviour using <link
-linkend="v4l2-selection-flags"> constraint flags </link>.</para>
-
- <section>
-
- <title>Configuration of video capture</title>
-
-<para>See figure <xref linkend="sel-targets-capture" /> for examples of the
-selection targets available for a video capture device. It is recommended to
-configure the cropping targets before to the composing targets.</para>
-
-<para>The range of coordinates of the top left corner, width and height of
-areas that can be sampled is given by the <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>
-target. It is recommended for the driver developers to put the
-top/left corner at position <constant>(0,0)</constant>. The rectangle's
-coordinates are expressed in pixels.</para>
-
-<para>The top left corner, width and height of the source rectangle, that is
-the area actually sampled, is given by the <constant>V4L2_SEL_TGT_CROP</constant>
-target. It uses the same coordinate system as <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
-The active cropping area must lie completely inside the capture boundaries. The
-driver may further adjust the requested size and/or position according to hardware
-limitations.</para>
-
-<para>Each capture device has a default source rectangle, given by the
-<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant> target. This rectangle shall
-over what the driver writer considers the complete picture. Drivers shall set
-the active crop rectangle to the default when the driver is first loaded, but
-not later.</para>
-
-<para>The composing targets refer to a memory buffer. The limits of composing
-coordinates are obtained using <constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant>.
-All coordinates are expressed in pixels. The rectangle's top/left
-corner must be located at position <constant>(0,0)</constant>. The width and
-height are equal to the image size set by <constant>VIDIOC_S_FMT</constant>.
-</para>
-
-<para>The part of a buffer into which the image is inserted by the hardware is
-controlled by the <constant>V4L2_SEL_TGT_COMPOSE</constant> target.
-The rectangle's coordinates are also expressed in the same coordinate system as
-the bounds rectangle. The composing rectangle must lie completely inside bounds
-rectangle. The driver must adjust the composing rectangle to fit to the
-bounding limits. Moreover, the driver can perform other adjustments according
-to hardware limitations. The application can control rounding behaviour using
-<link linkend="v4l2-selection-flags"> constraint flags</link>.</para>
-
-<para>For capture devices the default composing rectangle is queried using
-<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant>. It is usually equal to the
-bounding rectangle.</para>
-
-<para>The part of a buffer that is modified by the hardware is given by
-<constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>. It contains all pixels
-defined using <constant>V4L2_SEL_TGT_COMPOSE</constant> plus all
-padding data modified by hardware during insertion process. All pixels outside
-this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
-content of pixels that lie inside the padded area but outside active area is
-undefined. The application can use the padded and active rectangles to detect
-where the rubbish pixels are located and remove them if needed.</para>
-
- </section>
-
- <section>
-
- <title>Configuration of video output</title>
-
-<para>For output devices targets and ioctls are used similarly to the video
-capture case. The <emphasis>composing</emphasis> rectangle refers to the
-insertion of an image into a video signal. The cropping rectangles refer to a
-memory buffer. It is recommended to configure the composing targets before to
-the cropping targets.</para>
-
-<para>The cropping targets refer to the memory buffer that contains an image to
-be inserted into a video signal or graphical screen. The limits of cropping
-coordinates are obtained using <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
-All coordinates are expressed in pixels. The top/left corner is always point
-<constant>(0,0)</constant>. The width and height is equal to the image size
-specified using <constant>VIDIOC_S_FMT</constant> ioctl.</para>
-
-<para>The top left corner, width and height of the source rectangle, that is
-the area from which image date are processed by the hardware, is given by the
-<constant>V4L2_SEL_TGT_CROP</constant>. Its coordinates are expressed
-in in the same coordinate system as the bounds rectangle. The active cropping
-area must lie completely inside the crop boundaries and the driver may further
-adjust the requested size and/or position according to hardware
-limitations.</para>
-
-<para>For output devices the default cropping rectangle is queried using
-<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant>. It is usually equal to the
-bounding rectangle.</para>
-
-<para>The part of a video signal or graphics display where the image is
-inserted by the hardware is controlled by <constant>V4L2_SEL_TGT_COMPOSE</constant>
-target. The rectangle's coordinates are expressed in pixels. The composing
-rectangle must lie completely inside the bounds rectangle. The driver must
-adjust the area to fit to the bounding limits. Moreover, the driver can
-perform other adjustments according to hardware limitations.</para>
-
-<para>The device has a default composing rectangle, given by the
-<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant> target. This rectangle shall cover what
-the driver writer considers the complete picture. It is recommended for the
-driver developers to put the top/left corner at position <constant>(0,0)</constant>.
-Drivers shall set the active composing rectangle to the default
-one when the driver is first loaded.</para>
-
-<para>The devices may introduce additional content to video signal other than
-an image from memory buffers. It includes borders around an image. However,
-such a padded area is driver-dependent feature not covered by this document.
-Driver developers are encouraged to keep padded rectangle equal to active one.
-The padded target is accessed by the <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>
-identifier. It must contain all pixels from the <constant>V4L2_SEL_TGT_COMPOSE</constant>
-target.</para>
-
- </section>
-
- <section>
-
- <title>Scaling control</title>
-
-<para>An application can detect if scaling is performed by comparing the width
-and the height of rectangles obtained using <constant>V4L2_SEL_TGT_CROP</constant>
-and <constant>V4L2_SEL_TGT_COMPOSE</constant> targets. If
-these are not equal then the scaling is applied. The application can compute
-the scaling ratios using these values.</para>
-
- </section>
-
- </section>
-
- <section>
-
- <title>Comparison with old cropping API</title>
-
-<para>The selection API was introduced to cope with deficiencies of previous
-<link linkend="crop"> API</link>, that was designed to control simple capture
-devices. Later the cropping API was adopted by video output drivers. The ioctls
-are used to select a part of the display were the video signal is inserted. It
-should be considered as an API abuse because the described operation is
-actually the composing. The selection API makes a clear distinction between
-composing and cropping operations by setting the appropriate targets. The V4L2
-API lacks any support for composing to and cropping from an image inside a
-memory buffer. The application could configure a capture device to fill only a
-part of an image by abusing V4L2 API. Cropping a smaller image from a larger
-one is achieved by setting the field
-&v4l2-pix-format;<structfield>::bytesperline</structfield>. Introducing an image offsets
-could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield>
-before calling <constant>VIDIOC_QBUF</constant>. Those
-operations should be avoided because they are not portable (endianness), and do
-not work for macroblock and Bayer formats and mmap buffers. The selection API
-deals with configuration of buffer cropping/composing in a clear, intuitive and
-portable way. Next, with the selection API the concepts of the padded target
-and constraints flags are introduced. Finally, &v4l2-crop; and &v4l2-cropcap;
-have no reserved fields. Therefore there is no way to extend their functionality.
-The new &v4l2-selection; provides a lot of place for future
-extensions. Driver developers are encouraged to implement only selection API.
-The former cropping API would be simulated using the new one.</para>
-
- </section>
-
- <section>
- <title>Examples</title>
- <example>
- <title>Resetting the cropping parameters</title>
-
- <para>(A video capture device is assumed; change
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other devices; change target to
-<constant>V4L2_SEL_TGT_COMPOSE_*</constant> family to configure composing
-area)</para>
-
- <programlisting>
-
- &v4l2-selection; sel = {
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- .target = V4L2_SEL_TGT_CROP_DEFAULT,
- };
- ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel);
- if (ret)
- exit(-1);
- sel.target = V4L2_SEL_TGT_CROP;
- ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
- if (ret)
- exit(-1);
-
- </programlisting>
- </example>
-
- <example>
- <title>Simple downscaling</title>
- <para>Setting a composing area on output of size of <emphasis> at most
-</emphasis> half of limit placed at a center of a display.</para>
- <programlisting>
-
- &v4l2-selection; sel = {
- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
- .target = V4L2_SEL_TGT_COMPOSE_BOUNDS,
- };
- struct v4l2_rect r;
-
- ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;sel);
- if (ret)
- exit(-1);
- /* setting smaller compose rectangle */
- r.width = sel.r.width / 2;
- r.height = sel.r.height / 2;
- r.left = sel.r.width / 4;
- r.top = sel.r.height / 4;
- sel.r = r;
- sel.target = V4L2_SEL_TGT_COMPOSE;
- sel.flags = V4L2_SEL_FLAG_LE;
- ret = ioctl(fd, &VIDIOC-S-SELECTION;, &amp;sel);
- if (ret)
- exit(-1);
-
- </programlisting>
- </example>
-
- <example>
- <title>Querying for scaling factors</title>
- <para>A video output device is assumed; change
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> for other devices</para>
- <programlisting>
-
- &v4l2-selection; compose = {
- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
- .target = V4L2_SEL_TGT_COMPOSE,
- };
- &v4l2-selection; crop = {
- .type = V4L2_BUF_TYPE_VIDEO_OUTPUT,
- .target = V4L2_SEL_TGT_CROP,
- };
- double hscale, vscale;
-
- ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;compose);
- if (ret)
- exit(-1);
- ret = ioctl(fd, &VIDIOC-G-SELECTION;, &amp;crop);
- if (ret)
- exit(-1);
-
- /* computing scaling factors */
- hscale = (double)compose.r.width / crop.r.width;
- vscale = (double)compose.r.height / crop.r.height;
-
- </programlisting>
- </example>
-
- </section>
-
-</section>
diff --git a/Documentation/DocBook/media/v4l/selections-common.xml b/Documentation/DocBook/media/v4l/selections-common.xml
deleted file mode 100644
index d6d56fb6f9c0..000000000000
--- a/Documentation/DocBook/media/v4l/selections-common.xml
+++ /dev/null
@@ -1,180 +0,0 @@
-<section id="v4l2-selections-common">
-
- <title>Common selection definitions</title>
-
- <para>While the <link linkend="selection-api">V4L2 selection
- API</link> and <link linkend="v4l2-subdev-selections">V4L2 subdev
- selection APIs</link> are very similar, there's one fundamental
- difference between the two. On sub-device API, the selection
- rectangle refers to the media bus format, and is bound to a
- sub-device's pad. On the V4L2 interface the selection rectangles
- refer to the in-memory pixel format.</para>
-
- <para>This section defines the common definitions of the
- selection interfaces on the two APIs.</para>
-
- <section id="v4l2-selection-targets">
-
- <title>Selection targets</title>
-
- <para>The precise meaning of the selection targets may be
- dependent on which of the two interfaces they are used.</para>
-
- <table pgwide="1" frame="none" id="v4l2-selection-targets-table">
- <title>Selection target definitions</title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- &cs-def;
- <thead>
- <row rowsep="1">
- <entry align="left">Target name</entry>
- <entry align="left">id</entry>
- <entry align="left">Definition</entry>
- <entry align="left">Valid for V4L2</entry>
- <entry align="left">Valid for V4L2 subdev</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_SEL_TGT_CROP</constant></entry>
- <entry>0x0000</entry>
- <entry>Crop rectangle. Defines the cropped area.</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_CROP_DEFAULT</constant></entry>
- <entry>0x0001</entry>
- <entry>Suggested cropping rectangle that covers the "whole picture".</entry>
- <entry>Yes</entry>
- <entry>No</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_CROP_BOUNDS</constant></entry>
- <entry>0x0002</entry>
- <entry>Bounds of the crop rectangle. All valid crop
- rectangles fit inside the crop bounds rectangle.
- </entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_NATIVE_SIZE</constant></entry>
- <entry>0x0003</entry>
- <entry>The native size of the device, e.g. a sensor's
- pixel array. <structfield>left</structfield> and
- <structfield>top</structfield> fields are zero for this
- target. Setting the native size will generally only make
- sense for memory to memory devices where the software can
- create a canvas of a given size in which for example a
- video frame can be composed. In that case
- V4L2_SEL_TGT_NATIVE_SIZE can be used to configure the size
- of that canvas.
- </entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_COMPOSE</constant></entry>
- <entry>0x0100</entry>
- <entry>Compose rectangle. Used to configure scaling
- and composition.</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant></entry>
- <entry>0x0101</entry>
- <entry>Suggested composition rectangle that covers the "whole picture".</entry>
- <entry>Yes</entry>
- <entry>No</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant></entry>
- <entry>0x0102</entry>
- <entry>Bounds of the compose rectangle. All valid compose
- rectangles fit inside the compose bounds rectangle.</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant></entry>
- <entry>0x0103</entry>
- <entry>The active area and all padding pixels that are inserted or
- modified by hardware.</entry>
- <entry>Yes</entry>
- <entry>No</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
- <section id="v4l2-selection-flags">
-
- <title>Selection flags</title>
-
- <table pgwide="1" frame="none" id="v4l2-selection-flags-table">
- <title>Selection flag definitions</title>
- <tgroup cols="5">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- &cs-def;
- <thead>
- <row rowsep="1">
- <entry align="left">Flag name</entry>
- <entry align="left">id</entry>
- <entry align="left">Definition</entry>
- <entry align="left">Valid for V4L2</entry>
- <entry align="left">Valid for V4L2 subdev</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_SEL_FLAG_GE</constant></entry>
- <entry>(1 &lt;&lt; 0)</entry>
- <entry>Suggest the driver it should choose greater or
- equal rectangle (in size) than was requested. Albeit the
- driver may choose a lesser size, it will only do so due to
- hardware limitations. Without this flag (and
- <constant>V4L2_SEL_FLAG_LE</constant>) the
- behaviour is to choose the closest possible
- rectangle.</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_FLAG_LE</constant></entry>
- <entry>(1 &lt;&lt; 1)</entry>
- <entry>Suggest the driver it
- should choose lesser or equal rectangle (in size) than was
- requested. Albeit the driver may choose a greater size, it
- will only do so due to hardware limitations.</entry>
- <entry>Yes</entry>
- <entry>Yes</entry>
- </row>
- <row>
- <entry><constant>V4L2_SEL_FLAG_KEEP_CONFIG</constant></entry>
- <entry>(1 &lt;&lt; 2)</entry>
- <entry>The configuration must not be propagated to any
- further processing steps. If this flag is not given, the
- configuration is propagated inside the subdevice to all
- further processing steps.</entry>
- <entry>No</entry>
- <entry>Yes</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </section>
-
-</section>
diff --git a/Documentation/DocBook/media/v4l/subdev-formats.xml b/Documentation/DocBook/media/v4l/subdev-formats.xml
deleted file mode 100644
index 199c84e3aede..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-formats.xml
+++ /dev/null
@@ -1,4040 +0,0 @@
-<section id="v4l2-mbus-format">
- <title>Media Bus Formats</title>
-
- <table pgwide="1" frame="none" id="v4l2-mbus-framefmt">
- <title>struct <structname>v4l2_mbus_framefmt</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Image width, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Image height, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>code</structfield></entry>
- <entry>Format code, from &v4l2-mbus-pixelcode;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>field</structfield></entry>
- <entry>Field order, from &v4l2-field;. See
- <xref linkend="field-order" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>colorspace</structfield></entry>
- <entry>Image colorspace, from &v4l2-colorspace;. See
- <xref linkend="colorspaces" /> for details.</entry>
- </row>
- <row>
- <entry>&v4l2-ycbcr-encoding;</entry>
- <entry><structfield>ycbcr_enc</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-quantization;</entry>
- <entry><structfield>quantization</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>&v4l2-xfer-func;</entry>
- <entry><structfield>xfer_func</structfield></entry>
- <entry>This information supplements the
-<structfield>colorspace</structfield> and must be set by the driver for
-capture streams and by the application for output streams,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>reserved</structfield>[11]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <section id="v4l2-mbus-pixelcode">
- <title>Media Bus Pixel Codes</title>
-
- <para>The media bus pixel codes describe image formats as flowing over
- physical busses (both between separate physical components and inside SoC
- devices). This should not be confused with the V4L2 pixel formats that
- describe, using four character codes, image formats as stored in memory.
- </para>
-
- <para>While there is a relationship between image formats on busses and
- image formats in memory (a raw Bayer image won't be magically converted to
- JPEG just by storing it to memory), there is no one-to-one correspondance
- between them.</para>
-
- <section>
- <title>Packed RGB Formats</title>
-
- <para>Those formats transfer pixel data as red, green and blue components.
- The format code is made of the following information.
- <itemizedlist>
- <listitem><para>The red, green and blue components order code, as encoded in a
- pixel sample. Possible values are RGB and BGR.</para></listitem>
- <listitem><para>The number of bits per component, for each component. The values
- can be different for all components. Common values are 555 and 565.</para>
- </listitem>
- <listitem><para>The number of bus samples per pixel. Pixels that are wider than
- the bus width must be transferred in multiple samples. Common values are
- 1 and 2.</para></listitem>
- <listitem><para>The bus width.</para></listitem>
- <listitem><para>For formats where the total number of bits per pixel is smaller
- than the number of bus samples per pixel times the bus width, a padding
- value stating if the bytes are padded in their most high order bits
- (PADHI) or low order bits (PADLO). A "C" prefix is used for component-wise
- padding in the most high order bits (CPADHI) or low order bits (CPADLO)
- of each separate component.</para></listitem>
- <listitem><para>For formats where the number of bus samples per pixel is larger
- than 1, an endianness value stating if the pixel is transferred MSB first
- (BE) or LSB first (LE).</para></listitem>
- </itemizedlist>
- </para>
-
- <para>For instance, a format where pixels are encoded as 5-bits red, 5-bits
- green and 5-bit blue values padded on the high bit, transferred as 2 8-bit
- samples per pixel with the most significant bits (padding, red and half of
- the green value) transferred first will be named
- <constant>MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE</constant>.
- </para>
-
- <para>The following tables list existing packed RGB formats.</para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb">
- <title>RGB formats</title>
- <tgroup cols="27">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="center"/>
- <colspec colname="bit" />
- <colspec colnum="4" colname="b31" align="center" />
- <colspec colnum="5" colname="b20" align="center" />
- <colspec colnum="6" colname="b29" align="center" />
- <colspec colnum="7" colname="b28" align="center" />
- <colspec colnum="8" colname="b27" align="center" />
- <colspec colnum="9" colname="b26" align="center" />
- <colspec colnum="10" colname="b25" align="center" />
- <colspec colnum="11" colname="b24" align="center" />
- <colspec colnum="12" colname="b23" align="center" />
- <colspec colnum="13" colname="b22" align="center" />
- <colspec colnum="14" colname="b21" align="center" />
- <colspec colnum="15" colname="b20" align="center" />
- <colspec colnum="16" colname="b19" align="center" />
- <colspec colnum="17" colname="b18" align="center" />
- <colspec colnum="18" colname="b17" align="center" />
- <colspec colnum="19" colname="b16" align="center" />
- <colspec colnum="20" colname="b15" align="center" />
- <colspec colnum="21" colname="b14" align="center" />
- <colspec colnum="22" colname="b13" align="center" />
- <colspec colnum="23" colname="b12" align="center" />
- <colspec colnum="24" colname="b11" align="center" />
- <colspec colnum="25" colname="b10" align="center" />
- <colspec colnum="26" colname="b09" align="center" />
- <colspec colnum="27" colname="b08" align="center" />
- <colspec colnum="28" colname="b07" align="center" />
- <colspec colnum="29" colname="b06" align="center" />
- <colspec colnum="30" colname="b05" align="center" />
- <colspec colnum="31" colname="b04" align="center" />
- <colspec colnum="32" colname="b03" align="center" />
- <colspec colnum="33" colname="b02" align="center" />
- <colspec colnum="34" colname="b01" align="center" />
- <colspec colnum="35" colname="b00" align="center" />
- <spanspec namest="b31" nameend="b00" spanname="b0" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry></entry>
- <entry spanname="b0">Data organization</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Bit</entry>
- <entry>31</entry>
- <entry>30</entry>
- <entry>29</entry>
- <entry>28</entry>
- <entry>27</entry>
- <entry>26</entry>
- <entry>25</entry>
- <entry>24</entry>
- <entry>23</entry>
- <entry>22</entry>
- <entry>21</entry>
- <entry>20</entry>
- <entry>19</entry>
- <entry>18</entry>
- <entry>17</entry>
- <entry>16</entry>
- <entry>15</entry>
- <entry>14</entry>
- <entry>13</entry>
- <entry>12</entry>
- <entry>11</entry>
- <entry>10</entry>
- <entry>9</entry>
- <entry>8</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-RGB444-1X12">
- <entry>MEDIA_BUS_FMT_RGB444_1X12</entry>
- <entry>0x1016</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB444-2X8-PADHI-BE">
- <entry>MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE</entry>
- <entry>0x1001</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB444-2X8-PADHI-LE">
- <entry>MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE</entry>
- <entry>0x1002</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB555-2X8-PADHI-BE">
- <entry>MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE</entry>
- <entry>0x1003</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>0</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB555-2X8-PADHI-LE">
- <entry>MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE</entry>
- <entry>0x1004</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>0</entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB565-1X16">
- <entry>MEDIA_BUS_FMT_RGB565_1X16</entry>
- <entry>0x1017</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-BGR565-2X8-BE">
- <entry>MEDIA_BUS_FMT_BGR565_2X8_BE</entry>
- <entry>0x1005</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-BGR565-2X8-LE">
- <entry>MEDIA_BUS_FMT_BGR565_2X8_LE</entry>
- <entry>0x1006</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB565-2X8-BE">
- <entry>MEDIA_BUS_FMT_RGB565_2X8_BE</entry>
- <entry>0x1007</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB565-2X8-LE">
- <entry>MEDIA_BUS_FMT_RGB565_2X8_LE</entry>
- <entry>0x1008</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB666-1X18">
- <entry>MEDIA_BUS_FMT_RGB666_1X18</entry>
- <entry>0x1009</entry>
- <entry></entry>
- &dash-ent-14;
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RBG888-1X24">
- <entry>MEDIA_BUS_FMT_RBG888_1X24</entry>
- <entry>0x100e</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB666-1X24_CPADHI">
- <entry>MEDIA_BUS_FMT_RGB666_1X24_CPADHI</entry>
- <entry>0x1015</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>0</entry>
- <entry>0</entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-BGR888-1X24">
- <entry>MEDIA_BUS_FMT_BGR888_1X24</entry>
- <entry>0x1013</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-GBR888-1X24">
- <entry>MEDIA_BUS_FMT_GBR888_1X24</entry>
- <entry>0x1014</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-1X24">
- <entry>MEDIA_BUS_FMT_RGB888_1X24</entry>
- <entry>0x100a</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-2X12-BE">
- <entry>MEDIA_BUS_FMT_RGB888_2X12_BE</entry>
- <entry>0x100b</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-2X12-LE">
- <entry>MEDIA_BUS_FMT_RGB888_2X12_LE</entry>
- <entry>0x100c</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-ARGB888-1X32">
- <entry>MEDIA_BUS_FMT_ARGB888_1X32</entry>
- <entry>0x100d</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-1X32-PADHI">
- <entry>MEDIA_BUS_FMT_RGB888_1X32_PADHI</entry>
- <entry>0x100f</entry>
- <entry></entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>On LVDS buses, usually each sample is transferred serialized in
- seven time slots per pixel clock, on three (18-bit) or four (24-bit)
- differential data pairs at the same time. The remaining bits are used for
- control signals as defined by SPWG/PSWG/VESA or JEIDA standards.
- The 24-bit RGB format serialized in seven time slots on four lanes using
- JEIDA defined bit mapping will be named
- <constant>MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA</constant>, for example.
- </para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb-lvds">
- <title>LVDS RGB formats</title>
- <tgroup cols="8">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="center" />
- <colspec colname="slot" align="center" />
- <colspec colname="lane" />
- <colspec colnum="5" colname="l03" align="center" />
- <colspec colnum="6" colname="l02" align="center" />
- <colspec colnum="7" colname="l01" align="center" />
- <colspec colnum="8" colname="l00" align="center" />
- <spanspec namest="l03" nameend="l00" spanname="l0" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry></entry>
- <entry></entry>
- <entry spanname="l0">Data organization</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Timeslot</entry>
- <entry>Lane</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-RGB666-1X7X3-SPWG">
- <entry>MEDIA_BUS_FMT_RGB666_1X7X3_SPWG</entry>
- <entry>0x1010</entry>
- <entry>0</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>d</entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>1</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>d</entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>2</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>d</entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>3</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>4</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>5</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>6</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-1X7X4-SPWG">
- <entry>MEDIA_BUS_FMT_RGB888_1X7X4_SPWG</entry>
- <entry>0x1011</entry>
- <entry>0</entry>
- <entry></entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>1</entry>
- <entry></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>d</entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>2</entry>
- <entry></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>d</entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>3</entry>
- <entry></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>4</entry>
- <entry></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>5</entry>
- <entry></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>6</entry>
- <entry></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-RGB888-1X7X4-JEIDA">
- <entry>MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA</entry>
- <entry>0x1012</entry>
- <entry>0</entry>
- <entry></entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>1</entry>
- <entry></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>d</entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>2</entry>
- <entry></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>d</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>3</entry>
- <entry></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>4</entry>
- <entry></entry>
- <entry>g<subscript>0</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>5</entry>
- <entry></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>6</entry>
- <entry></entry>
- <entry>r<subscript>0</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Bayer Formats</title>
-
- <para>Those formats transfer pixel data as red, green and blue components.
- The format code is made of the following information.
- <itemizedlist>
- <listitem><para>The red, green and blue components order code, as encoded in a
- pixel sample. The possible values are shown in <xref
- linkend="bayer-patterns" />.</para></listitem>
- <listitem><para>The number of bits per pixel component. All components are
- transferred on the same number of bits. Common values are 8, 10 and 12.</para>
- </listitem>
- <listitem><para>The compression (optional). If the pixel components are
- ALAW- or DPCM-compressed, a mention of the compression scheme and the
- number of bits per compressed pixel component.</para></listitem>
- <listitem><para>The number of bus samples per pixel. Pixels that are wider than
- the bus width must be transferred in multiple samples. Common values are
- 1 and 2.</para></listitem>
- <listitem><para>The bus width.</para></listitem>
- <listitem><para>For formats where the total number of bits per pixel is smaller
- than the number of bus samples per pixel times the bus width, a padding
- value stating if the bytes are padded in their most high order bits
- (PADHI) or low order bits (PADLO).</para></listitem>
- <listitem><para>For formats where the number of bus samples per pixel is larger
- than 1, an endianness value stating if the pixel is transferred MSB first
- (BE) or LSB first (LE).</para></listitem>
- </itemizedlist>
- </para>
-
- <para>For instance, a format with uncompressed 10-bit Bayer components
- arranged in a red, green, green, blue pattern transferred as 2 8-bit
- samples per pixel with the least significant bits transferred first will
- be named <constant>MEDIA_BUS_FMT_SRGGB10_2X8_PADHI_LE</constant>.
- </para>
-
- <figure id="bayer-patterns">
- <title>Bayer Patterns</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="bayer.png" format="PNG" />
- </imageobject>
- <textobject>
- <phrase>Bayer filter color patterns</phrase>
- </textobject>
- </mediaobject>
- </figure>
-
- <para>The following table lists existing packed Bayer formats. The data
- organization is given as an example for the first pixel only.</para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-bayer">
- <title>Bayer Formats</title>
- <tgroup cols="15">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="center"/>
- <colspec colname="bit" />
- <colspec colnum="4" colname="b11" align="center" />
- <colspec colnum="5" colname="b10" align="center" />
- <colspec colnum="6" colname="b09" align="center" />
- <colspec colnum="7" colname="b08" align="center" />
- <colspec colnum="8" colname="b07" align="center" />
- <colspec colnum="9" colname="b06" align="center" />
- <colspec colnum="10" colname="b05" align="center" />
- <colspec colnum="11" colname="b04" align="center" />
- <colspec colnum="12" colname="b03" align="center" />
- <colspec colnum="13" colname="b02" align="center" />
- <colspec colnum="14" colname="b01" align="center" />
- <colspec colnum="15" colname="b00" align="center" />
- <spanspec namest="b11" nameend="b00" spanname="b0" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry></entry>
- <entry spanname="b0">Data organization</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Bit</entry>
- <entry>11</entry>
- <entry>10</entry>
- <entry>9</entry>
- <entry>8</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-SBGGR8-1X8">
- <entry>MEDIA_BUS_FMT_SBGGR8_1X8</entry>
- <entry>0x3001</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGBRG8-1X8">
- <entry>MEDIA_BUS_FMT_SGBRG8_1X8</entry>
- <entry>0x3013</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGRBG8-1X8">
- <entry>MEDIA_BUS_FMT_SGRBG8_1X8</entry>
- <entry>0x3002</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SRGGB8-1X8">
- <entry>MEDIA_BUS_FMT_SRGGB8_1X8</entry>
- <entry>0x3014</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-ALAW8-1X8">
- <entry>MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8</entry>
- <entry>0x3015</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGBRG10-ALAW8-1X8">
- <entry>MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8</entry>
- <entry>0x3016</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGRBG10-ALAW8-1X8">
- <entry>MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8</entry>
- <entry>0x3017</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SRGGB10-ALAW8-1X8">
- <entry>MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8</entry>
- <entry>0x3018</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-DPCM8-1X8">
- <entry>MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8</entry>
- <entry>0x300b</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGBRG10-DPCM8-1X8">
- <entry>MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8</entry>
- <entry>0x300c</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGRBG10-DPCM8-1X8">
- <entry>MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8</entry>
- <entry>0x3009</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SRGGB10-DPCM8-1X8">
- <entry>MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8</entry>
- <entry>0x300d</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-2X8-PADHI-BE">
- <entry>MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE</entry>
- <entry>0x3003</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-2X8-PADHI-LE">
- <entry>MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE</entry>
- <entry>0x3004</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-2X8-PADLO-BE">
- <entry>MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE</entry>
- <entry>0x3005</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-2X8-PADLO-LE">
- <entry>MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE</entry>
- <entry>0x3006</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR10-1X10">
- <entry>MEDIA_BUS_FMT_SBGGR10_1X10</entry>
- <entry>0x3007</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGBRG10-1X10">
- <entry>MEDIA_BUS_FMT_SGBRG10_1X10</entry>
- <entry>0x300e</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>9</subscript></entry>
- <entry>g<subscript>8</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGRBG10-1X10">
- <entry>MEDIA_BUS_FMT_SGRBG10_1X10</entry>
- <entry>0x300a</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>g<subscript>9</subscript></entry>
- <entry>g<subscript>8</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SRGGB10-1X10">
- <entry>MEDIA_BUS_FMT_SRGGB10_1X10</entry>
- <entry>0x300f</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>r<subscript>9</subscript></entry>
- <entry>r<subscript>8</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SBGGR12-1X12">
- <entry>MEDIA_BUS_FMT_SBGGR12_1X12</entry>
- <entry>0x3008</entry>
- <entry></entry>
- <entry>b<subscript>11</subscript></entry>
- <entry>b<subscript>10</subscript></entry>
- <entry>b<subscript>9</subscript></entry>
- <entry>b<subscript>8</subscript></entry>
- <entry>b<subscript>7</subscript></entry>
- <entry>b<subscript>6</subscript></entry>
- <entry>b<subscript>5</subscript></entry>
- <entry>b<subscript>4</subscript></entry>
- <entry>b<subscript>3</subscript></entry>
- <entry>b<subscript>2</subscript></entry>
- <entry>b<subscript>1</subscript></entry>
- <entry>b<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGBRG12-1X12">
- <entry>MEDIA_BUS_FMT_SGBRG12_1X12</entry>
- <entry>0x3010</entry>
- <entry></entry>
- <entry>g<subscript>11</subscript></entry>
- <entry>g<subscript>10</subscript></entry>
- <entry>g<subscript>9</subscript></entry>
- <entry>g<subscript>8</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SGRBG12-1X12">
- <entry>MEDIA_BUS_FMT_SGRBG12_1X12</entry>
- <entry>0x3011</entry>
- <entry></entry>
- <entry>g<subscript>11</subscript></entry>
- <entry>g<subscript>10</subscript></entry>
- <entry>g<subscript>9</subscript></entry>
- <entry>g<subscript>8</subscript></entry>
- <entry>g<subscript>7</subscript></entry>
- <entry>g<subscript>6</subscript></entry>
- <entry>g<subscript>5</subscript></entry>
- <entry>g<subscript>4</subscript></entry>
- <entry>g<subscript>3</subscript></entry>
- <entry>g<subscript>2</subscript></entry>
- <entry>g<subscript>1</subscript></entry>
- <entry>g<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-SRGGB12-1X12">
- <entry>MEDIA_BUS_FMT_SRGGB12_1X12</entry>
- <entry>0x3012</entry>
- <entry></entry>
- <entry>r<subscript>11</subscript></entry>
- <entry>r<subscript>10</subscript></entry>
- <entry>r<subscript>9</subscript></entry>
- <entry>r<subscript>8</subscript></entry>
- <entry>r<subscript>7</subscript></entry>
- <entry>r<subscript>6</subscript></entry>
- <entry>r<subscript>5</subscript></entry>
- <entry>r<subscript>4</subscript></entry>
- <entry>r<subscript>3</subscript></entry>
- <entry>r<subscript>2</subscript></entry>
- <entry>r<subscript>1</subscript></entry>
- <entry>r<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>Packed YUV Formats</title>
-
- <para>Those data formats transfer pixel data as (possibly downsampled) Y, U
- and V components. Some formats include dummy bits in some of their samples
- and are collectively referred to as "YDYC" (Y-Dummy-Y-Chroma) formats.
- One cannot rely on the values of these dummy bits as those are undefined.
- </para>
- <para>The format code is made of the following information.
- <itemizedlist>
- <listitem><para>The Y, U and V components order code, as transferred on the
- bus. Possible values are YUYV, UYVY, YVYU and VYUY for formats with no
- dummy bit, and YDYUYDYV, YDYVYDYU, YUYDYVYD and YVYDYUYD for YDYC formats.
- </para></listitem>
- <listitem><para>The number of bits per pixel component. All components are
- transferred on the same number of bits. Common values are 8, 10 and 12.</para>
- </listitem>
- <listitem><para>The number of bus samples per pixel. Pixels that are wider than
- the bus width must be transferred in multiple samples. Common values are
- 1, 1.5 (encoded as 1_5) and 2.</para></listitem>
- <listitem><para>The bus width. When the bus width is larger than the number of
- bits per pixel component, several components are packed in a single bus
- sample. The components are ordered as specified by the order code, with
- components on the left of the code transferred in the high order bits.
- Common values are 8 and 16.</para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>For instance, a format where pixels are encoded as 8-bit YUV values
- downsampled to 4:2:2 and transferred as 2 8-bit bus samples per pixel in the
- U, Y, V, Y order will be named <constant>MEDIA_BUS_FMT_UYVY8_2X8</constant>.
- </para>
-
- <para><xref linkend="v4l2-mbus-pixelcode-yuv8"/> lists existing packed YUV
- formats and describes the organization of each pixel data in each sample.
- When a format pattern is split across multiple samples each of the samples
- in the pattern is described.</para>
-
- <para>The role of each bit transferred over the bus is identified by one
- of the following codes.</para>
-
- <itemizedlist>
- <listitem><para>y<subscript>x</subscript> for luma component bit number x</para></listitem>
- <listitem><para>u<subscript>x</subscript> for blue chroma component bit number x</para></listitem>
- <listitem><para>v<subscript>x</subscript> for red chroma component bit number x</para></listitem>
- <listitem><para>a<subscript>x</subscript> for alpha component bit number x</para></listitem>
- <listitem><para>- for non-available bits (for positions higher than the bus width)</para></listitem>
- <listitem><para>d for dummy bits</para></listitem>
- </itemizedlist>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-yuv8">
- <title>YUV Formats</title>
- <tgroup cols="23">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="center"/>
- <colspec colname="bit" />
- <colspec colnum="4" colname="b31" align="center" />
- <colspec colnum="5" colname="b20" align="center" />
- <colspec colnum="6" colname="b29" align="center" />
- <colspec colnum="7" colname="b28" align="center" />
- <colspec colnum="8" colname="b27" align="center" />
- <colspec colnum="9" colname="b26" align="center" />
- <colspec colnum="10" colname="b25" align="center" />
- <colspec colnum="11" colname="b24" align="center" />
- <colspec colnum="12" colname="b23" align="center" />
- <colspec colnum="13" colname="b22" align="center" />
- <colspec colnum="14" colname="b21" align="center" />
- <colspec colnum="15" colname="b20" align="center" />
- <colspec colnum="16" colname="b19" align="center" />
- <colspec colnum="17" colname="b18" align="center" />
- <colspec colnum="18" colname="b17" align="center" />
- <colspec colnum="19" colname="b16" align="center" />
- <colspec colnum="20" colname="b15" align="center" />
- <colspec colnum="21" colname="b14" align="center" />
- <colspec colnum="22" colname="b13" align="center" />
- <colspec colnum="23" colname="b12" align="center" />
- <colspec colnum="24" colname="b11" align="center" />
- <colspec colnum="25" colname="b10" align="center" />
- <colspec colnum="26" colname="b09" align="center" />
- <colspec colnum="27" colname="b08" align="center" />
- <colspec colnum="28" colname="b07" align="center" />
- <colspec colnum="29" colname="b06" align="center" />
- <colspec colnum="30" colname="b05" align="center" />
- <colspec colnum="31" colname="b04" align="center" />
- <colspec colnum="32" colname="b03" align="center" />
- <colspec colnum="33" colname="b02" align="center" />
- <colspec colnum="34" colname="b01" align="center" />
- <colspec colnum="35" colname="b00" align="center" />
- <spanspec namest="b31" nameend="b00" spanname="b0" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry></entry>
- <entry spanname="b0">Data organization</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Bit</entry>
- <entry>31</entry>
- <entry>30</entry>
- <entry>29</entry>
- <entry>28</entry>
- <entry>27</entry>
- <entry>26</entry>
- <entry>25</entry>
- <entry>24</entry>
- <entry>23</entry>
- <entry>22</entry>
- <entry>21</entry>
- <entry>10</entry>
- <entry>19</entry>
- <entry>18</entry>
- <entry>17</entry>
- <entry>16</entry>
- <entry>15</entry>
- <entry>14</entry>
- <entry>13</entry>
- <entry>12</entry>
- <entry>11</entry>
- <entry>10</entry>
- <entry>9</entry>
- <entry>8</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-Y8-1X8">
- <entry>MEDIA_BUS_FMT_Y8_1X8</entry>
- <entry>0x2001</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UV8-1X8">
- <entry>MEDIA_BUS_FMT_UV8_1X8</entry>
- <entry>0x2015</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY8-1_5X8">
- <entry>MEDIA_BUS_FMT_UYVY8_1_5X8</entry>
- <entry>0x2002</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY8-1_5X8">
- <entry>MEDIA_BUS_FMT_VYUY8_1_5X8</entry>
- <entry>0x2003</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV8-1_5X8">
- <entry>MEDIA_BUS_FMT_YUYV8_1_5X8</entry>
- <entry>0x2004</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU8-1_5X8">
- <entry>MEDIA_BUS_FMT_YVYU8_1_5X8</entry>
- <entry>0x2005</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY8-2X8">
- <entry>MEDIA_BUS_FMT_UYVY8_2X8</entry>
- <entry>0x2006</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY8-2X8">
- <entry>MEDIA_BUS_FMT_VYUY8_2X8</entry>
- <entry>0x2007</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV8-2X8">
- <entry>MEDIA_BUS_FMT_YUYV8_2X8</entry>
- <entry>0x2008</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU8-2X8">
- <entry>MEDIA_BUS_FMT_YVYU8_2X8</entry>
- <entry>0x2009</entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-24;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-Y10-1X10">
- <entry>MEDIA_BUS_FMT_Y10_1X10</entry>
- <entry>0x200a</entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY10-2X10">
- <entry>MEDIA_BUS_FMT_UYVY10_2X10</entry>
- <entry>0x2018</entry>
- <entry></entry>
- &dash-ent-22;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY10-2X10">
- <entry>MEDIA_BUS_FMT_VYUY10_2X10</entry>
- <entry>0x2019</entry>
- <entry></entry>
- &dash-ent-22;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV10-2X10">
- <entry>MEDIA_BUS_FMT_YUYV10_2X10</entry>
- <entry>0x200b</entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU10-2X10">
- <entry>MEDIA_BUS_FMT_YVYU10_2X10</entry>
- <entry>0x200c</entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-22;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-Y12-1X12">
- <entry>MEDIA_BUS_FMT_Y12_1X12</entry>
- <entry>0x2013</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY12-2X12">
- <entry>MEDIA_BUS_FMT_UYVY12_2X12</entry>
- <entry>0x201c</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY12-2X12">
- <entry>MEDIA_BUS_FMT_VYUY12_2X12</entry>
- <entry>0x201d</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV12-2X12">
- <entry>MEDIA_BUS_FMT_YUYV12_2X12</entry>
- <entry>0x201e</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU12-2X12">
- <entry>MEDIA_BUS_FMT_YVYU12_2X12</entry>
- <entry>0x201f</entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-20;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY8-1X16">
- <entry>MEDIA_BUS_FMT_UYVY8_1X16</entry>
- <entry>0x200f</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY8-1X16">
- <entry>MEDIA_BUS_FMT_VYUY8_1X16</entry>
- <entry>0x2010</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV8-1X16">
- <entry>MEDIA_BUS_FMT_YUYV8_1X16</entry>
- <entry>0x2011</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU8-1X16">
- <entry>MEDIA_BUS_FMT_YVYU8_1X16</entry>
- <entry>0x2012</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YDYUYDYV8-1X16">
- <entry>MEDIA_BUS_FMT_YDYUYDYV8_1X16</entry>
- <entry>0x2014</entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- <entry>d</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-16;
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY10-1X20">
- <entry>MEDIA_BUS_FMT_UYVY10_1X20</entry>
- <entry>0x201a</entry>
- <entry></entry>
- &dash-ent-12;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-12;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY10-1X20">
- <entry>MEDIA_BUS_FMT_VYUY10_1X20</entry>
- <entry>0x201b</entry>
- <entry></entry>
- &dash-ent-12;
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-12;
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV10-1X20">
- <entry>MEDIA_BUS_FMT_YUYV10_1X20</entry>
- <entry>0x200d</entry>
- <entry></entry>
- &dash-ent-12;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-12;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU10-1X20">
- <entry>MEDIA_BUS_FMT_YVYU10_1X20</entry>
- <entry>0x200e</entry>
- <entry></entry>
- &dash-ent-12;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-12;
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VUY8-1X24">
- <entry>MEDIA_BUS_FMT_VUY8_1X24</entry>
- <entry>0x201a</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUV8-1X24">
- <entry>MEDIA_BUS_FMT_YUV8_1X24</entry>
- <entry>0x2025</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-UYVY12-1X24">
- <entry>MEDIA_BUS_FMT_UYVY12_1X24</entry>
- <entry>0x2020</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-8;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-VYUY12-1X24">
- <entry>MEDIA_BUS_FMT_VYUY12_1X24</entry>
- <entry>0x2021</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-8;
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUYV12-1X24">
- <entry>MEDIA_BUS_FMT_YUYV12_1X24</entry>
- <entry>0x2022</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-8;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YVYU12-1X24">
- <entry>MEDIA_BUS_FMT_YVYU12_1X24</entry>
- <entry>0x2023</entry>
- <entry></entry>
- &dash-ent-8;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>v<subscript>11</subscript></entry>
- <entry>v<subscript>10</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- &dash-ent-8;
- <entry>y<subscript>11</subscript></entry>
- <entry>y<subscript>10</subscript></entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>11</subscript></entry>
- <entry>u<subscript>10</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-YUV10-1X30">
- <entry>MEDIA_BUS_FMT_YUV10_1X30</entry>
- <entry>0x2016</entry>
- <entry></entry>
- <entry>-</entry>
- <entry>-</entry>
- <entry>y<subscript>9</subscript></entry>
- <entry>y<subscript>8</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>9</subscript></entry>
- <entry>u<subscript>8</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>v<subscript>9</subscript></entry>
- <entry>v<subscript>8</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- <row id="MEDIA-BUS-FMT-AYUV8-1X32">
- <entry>MEDIA_BUS_FMT_AYUV8_1X32</entry>
- <entry>0x2017</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>y<subscript>7</subscript></entry>
- <entry>y<subscript>6</subscript></entry>
- <entry>y<subscript>5</subscript></entry>
- <entry>y<subscript>4</subscript></entry>
- <entry>y<subscript>3</subscript></entry>
- <entry>y<subscript>2</subscript></entry>
- <entry>y<subscript>1</subscript></entry>
- <entry>y<subscript>0</subscript></entry>
- <entry>u<subscript>7</subscript></entry>
- <entry>u<subscript>6</subscript></entry>
- <entry>u<subscript>5</subscript></entry>
- <entry>u<subscript>4</subscript></entry>
- <entry>u<subscript>3</subscript></entry>
- <entry>u<subscript>2</subscript></entry>
- <entry>u<subscript>1</subscript></entry>
- <entry>u<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>HSV/HSL Formats</title>
-
- <para>Those formats transfer pixel data as RGB values in a cylindrical-coordinate
- system using Hue-Saturation-Value or Hue-Saturation-Lightness components. The
- format code is made of the following information.
- <itemizedlist>
- <listitem><para>The hue, saturation, value or lightness and optional alpha
- components order code, as encoded in a pixel sample. The only currently
- supported value is AHSV.
- </para></listitem>
- <listitem><para>The number of bits per component, for each component. The values
- can be different for all components. The only currently supported value is 8888.
- </para></listitem>
- <listitem><para>The number of bus samples per pixel. Pixels that are wider than
- the bus width must be transferred in multiple samples. The only currently
- supported value is 1.</para></listitem>
- <listitem><para>The bus width.</para></listitem>
- <listitem><para>For formats where the total number of bits per pixel is smaller
- than the number of bus samples per pixel times the bus width, a padding
- value stating if the bytes are padded in their most high order bits
- (PADHI) or low order bits (PADLO).</para></listitem>
- <listitem><para>For formats where the number of bus samples per pixel is larger
- than 1, an endianness value stating if the pixel is transferred MSB first
- (BE) or LSB first (LE).</para></listitem>
- </itemizedlist>
- </para>
-
- <para>The following table lists existing HSV/HSL formats.</para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-hsv">
- <title>HSV/HSL formats</title>
- <tgroup cols="27">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="center"/>
- <colspec colname="bit" />
- <colspec colnum="4" colname="b31" align="center" />
- <colspec colnum="5" colname="b20" align="center" />
- <colspec colnum="6" colname="b29" align="center" />
- <colspec colnum="7" colname="b28" align="center" />
- <colspec colnum="8" colname="b27" align="center" />
- <colspec colnum="9" colname="b26" align="center" />
- <colspec colnum="10" colname="b25" align="center" />
- <colspec colnum="11" colname="b24" align="center" />
- <colspec colnum="12" colname="b23" align="center" />
- <colspec colnum="13" colname="b22" align="center" />
- <colspec colnum="14" colname="b21" align="center" />
- <colspec colnum="15" colname="b20" align="center" />
- <colspec colnum="16" colname="b19" align="center" />
- <colspec colnum="17" colname="b18" align="center" />
- <colspec colnum="18" colname="b17" align="center" />
- <colspec colnum="19" colname="b16" align="center" />
- <colspec colnum="20" colname="b15" align="center" />
- <colspec colnum="21" colname="b14" align="center" />
- <colspec colnum="22" colname="b13" align="center" />
- <colspec colnum="23" colname="b12" align="center" />
- <colspec colnum="24" colname="b11" align="center" />
- <colspec colnum="25" colname="b10" align="center" />
- <colspec colnum="26" colname="b09" align="center" />
- <colspec colnum="27" colname="b08" align="center" />
- <colspec colnum="28" colname="b07" align="center" />
- <colspec colnum="29" colname="b06" align="center" />
- <colspec colnum="30" colname="b05" align="center" />
- <colspec colnum="31" colname="b04" align="center" />
- <colspec colnum="32" colname="b03" align="center" />
- <colspec colnum="33" colname="b02" align="center" />
- <colspec colnum="34" colname="b01" align="center" />
- <colspec colnum="35" colname="b00" align="center" />
- <spanspec namest="b31" nameend="b00" spanname="b0" />
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry></entry>
- <entry spanname="b0">Data organization</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Bit</entry>
- <entry>31</entry>
- <entry>30</entry>
- <entry>29</entry>
- <entry>28</entry>
- <entry>27</entry>
- <entry>26</entry>
- <entry>25</entry>
- <entry>24</entry>
- <entry>23</entry>
- <entry>22</entry>
- <entry>21</entry>
- <entry>20</entry>
- <entry>19</entry>
- <entry>18</entry>
- <entry>17</entry>
- <entry>16</entry>
- <entry>15</entry>
- <entry>14</entry>
- <entry>13</entry>
- <entry>12</entry>
- <entry>11</entry>
- <entry>10</entry>
- <entry>9</entry>
- <entry>8</entry>
- <entry>7</entry>
- <entry>6</entry>
- <entry>5</entry>
- <entry>4</entry>
- <entry>3</entry>
- <entry>2</entry>
- <entry>1</entry>
- <entry>0</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-AHSV8888-1X32">
- <entry>MEDIA_BUS_FMT_AHSV8888_1X32</entry>
- <entry>0x6001</entry>
- <entry></entry>
- <entry>a<subscript>7</subscript></entry>
- <entry>a<subscript>6</subscript></entry>
- <entry>a<subscript>5</subscript></entry>
- <entry>a<subscript>4</subscript></entry>
- <entry>a<subscript>3</subscript></entry>
- <entry>a<subscript>2</subscript></entry>
- <entry>a<subscript>1</subscript></entry>
- <entry>a<subscript>0</subscript></entry>
- <entry>h<subscript>7</subscript></entry>
- <entry>h<subscript>6</subscript></entry>
- <entry>h<subscript>5</subscript></entry>
- <entry>h<subscript>4</subscript></entry>
- <entry>h<subscript>3</subscript></entry>
- <entry>h<subscript>2</subscript></entry>
- <entry>h<subscript>1</subscript></entry>
- <entry>h<subscript>0</subscript></entry>
- <entry>s<subscript>7</subscript></entry>
- <entry>s<subscript>6</subscript></entry>
- <entry>s<subscript>5</subscript></entry>
- <entry>s<subscript>4</subscript></entry>
- <entry>s<subscript>3</subscript></entry>
- <entry>s<subscript>2</subscript></entry>
- <entry>s<subscript>1</subscript></entry>
- <entry>s<subscript>0</subscript></entry>
- <entry>v<subscript>7</subscript></entry>
- <entry>v<subscript>6</subscript></entry>
- <entry>v<subscript>5</subscript></entry>
- <entry>v<subscript>4</subscript></entry>
- <entry>v<subscript>3</subscript></entry>
- <entry>v<subscript>2</subscript></entry>
- <entry>v<subscript>1</subscript></entry>
- <entry>v<subscript>0</subscript></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section>
- <title>JPEG Compressed Formats</title>
-
- <para>Those data formats consist of an ordered sequence of 8-bit bytes
- obtained from JPEG compression process. Additionally to the
- <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>
- <listitem><para>The bus width.</para></listitem>
- </itemizedlist>
- </para>
-
- <para>For instance, for a JPEG baseline process and an 8-bit bus width
- the format will be named <constant>MEDIA_BUS_FMT_JPEG_1X8</constant>.
- </para>
-
- <para>The following table lists existing JPEG compressed formats.</para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-jpeg">
- <title>JPEG Formats</title>
- <tgroup cols="3">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="left"/>
- <colspec colname="remarks" align="left"/>
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>Remarks</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-JPEG-1X8">
- <entry>MEDIA_BUS_FMT_JPEG_1X8</entry>
- <entry>0x4001</entry>
- <entry>Besides of its usage for the parallel bus this format is
- recommended for transmission of JPEG data over MIPI CSI bus
- using the User Defined 8-bit Data types.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- <section id="v4l2-mbus-vendor-spec-fmts">
- <title>Vendor and Device Specific Formats</title>
-
- <para>This section lists complex data formats that are either vendor or
- device specific.
- </para>
-
- <para>The following table lists the existing vendor and device specific
- formats.</para>
-
- <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-vendor-specific">
- <title>Vendor and device specific formats</title>
- <tgroup cols="3">
- <colspec colname="id" align="left" />
- <colspec colname="code" align="left"/>
- <colspec colname="remarks" align="left"/>
- <thead>
- <row>
- <entry>Identifier</entry>
- <entry>Code</entry>
- <entry>Comments</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row id="MEDIA-BUS-FMT-S5C-UYVY-JPEG-1X8">
- <entry>MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8</entry>
- <entry>0x5001</entry>
- <entry>
- Interleaved raw UYVY and JPEG image format with embedded
- meta-data used by Samsung S3C73MX camera sensors.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </section>
-
- </section>
-</section>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia
deleted file mode 100644
index e32ba5362e1d..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.dia
+++ /dev/null
@@ -1,614 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
- <dia:diagramdata>
- <dia:attribute name="background">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="pagebreak">
- <dia:color val="#000099"/>
- </dia:attribute>
- <dia:attribute name="paper">
- <dia:composite type="paper">
- <dia:attribute name="name">
- <dia:string>#A4#</dia:string>
- </dia:attribute>
- <dia:attribute name="tmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="bmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="lmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="rmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="is_portrait">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="scaling">
- <dia:real val="0.49000000953674316"/>
- </dia:attribute>
- <dia:attribute name="fitto">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="grid">
- <dia:composite type="grid">
- <dia:attribute name="width_x">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="width_y">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_x">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_y">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:composite type="color"/>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#d8e5e5"/>
- </dia:attribute>
- <dia:attribute name="guides">
- <dia:composite type="guides">
- <dia:attribute name="hguides"/>
- <dia:attribute name="vguides"/>
- </dia:composite>
- </dia:attribute>
- </dia:diagramdata>
- <dia:layer name="Background" visible="true" active="true">
- <dia:object type="Standard - Box" version="0" id="O0">
- <dia:attribute name="obj_pos">
- <dia:point val="-0.4,6.5"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-0.45,6.45;23.1387,16.2"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-0.4,6.5"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="23.48871579904775"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="9.6500000000000004"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O1">
- <dia:attribute name="obj_pos">
- <dia:point val="0.225,9.45"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.175,9.4;8.225,14.7"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="0.225,9.45"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="7.9499999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="5.1999999999999975"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O2">
- <dia:attribute name="obj_pos">
- <dia:point val="3.175,10.55"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.125,10.5;7.925,14.45"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="3.175,10.55"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="4.6999999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.8499999999999979"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O3">
- <dia:attribute name="obj_pos">
- <dia:point val="3.725,11.3875"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.725,10.7925;6.6025,13.14"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink
-crop
-selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="3.725,11.3875"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O4">
- <dia:attribute name="obj_pos">
- <dia:point val="1.475,7.9"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="1.475,7.305;1.475,8.0525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="1.475,7.9"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O5">
- <dia:attribute name="obj_pos">
- <dia:point val="0.426918,7.89569"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.426918,7.30069;3.90942,8.84819"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="0.426918,7.89569"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O6">
- <dia:attribute name="obj_pos">
- <dia:point val="17.4887,7.75"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="17.4887,7.155;21.8112,8.7025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#source media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="17.4887,7.75"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O7">
- <dia:attribute name="obj_pos">
- <dia:point val="17.5244,9.5417"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="17.4744,9.4917;22.2387,13.35"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="17.5244,9.5417"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="4.6643157990477508"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.758300000000002"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O8">
- <dia:attribute name="obj_pos">
- <dia:point val="17.5244,13.3"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.12132,13.2463;17.5781,14.4537"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="17.5244,13.3"/>
- <dia:point val="3.175,14.4"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O7" connection="5"/>
- <dia:connection handle="1" to="O2" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O9">
- <dia:attribute name="obj_pos">
- <dia:point val="17.5244,9.5417"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.12162,9.48832;17.5778,10.6034"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="17.5244,9.5417"/>
- <dia:point val="3.175,10.55"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O7" connection="0"/>
- <dia:connection handle="1" to="O2" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O10">
- <dia:attribute name="obj_pos">
- <dia:point val="22.1887,13.3"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.82132,13.2463;22.2424,14.4537"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="22.1887,13.3"/>
- <dia:point val="7.875,14.4"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O7" connection="7"/>
- <dia:connection handle="1" to="O2" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O11">
- <dia:attribute name="obj_pos">
- <dia:point val="22.1887,9.5417"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.82161,9.48831;22.2421,10.6034"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="22.1887,9.5417"/>
- <dia:point val="7.875,10.55"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O7" connection="2"/>
- <dia:connection handle="1" to="O2" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O12">
- <dia:attribute name="obj_pos">
- <dia:point val="23.23,10.5742"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="23.18,10.5242;24.13,11.4742"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="23.23,10.5742"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O13">
- <dia:attribute name="obj_pos">
- <dia:point val="24.08,10.9992"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.03,10.6388;32.4953,11.3624"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="24.08,10.9992"/>
- <dia:point val="32.3835,11.0007"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O12" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O14">
- <dia:attribute name="obj_pos">
- <dia:point val="25.3454,10.49"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.3454,9.895;29.9904,10.6425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 1 (source)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="25.3454,10.49"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O15">
- <dia:attribute name="obj_pos">
- <dia:point val="-1.44491,11.6506"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-1.49491,11.6006;-0.54491,12.5506"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-1.44491,11.6506"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O16">
- <dia:attribute name="obj_pos">
- <dia:point val="-9.61991,12.09"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-9.67,11.7149;-1.33311,12.4385"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="-9.61991,12.09"/>
- <dia:point val="-1.44491,12.0756"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O15" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O17">
- <dia:attribute name="obj_pos">
- <dia:point val="-7.39291,11.49"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-7.39291,10.895;-3.58791,11.6425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 0 (sink)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="-7.39291,11.49"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- </dia:layer>
-</dia:diagram>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg
deleted file mode 100644
index 18b0f5de9ed2..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-crop.svg
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="43cm" height="10cm" viewBox="-194 128 844 196" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="469.774" height="193"/>
- <g>
- <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="63.5" y="211" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="63.5" y="211" width="94" height="77"/>
- </g>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="74.5" y="227.75">
- <tspan x="74.5" y="227.75">sink</tspan>
- <tspan x="74.5" y="243.75">crop</tspan>
- <tspan x="74.5" y="259.75">selection</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
- <tspan x="29.5" y="158"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
- <tspan x="8.53836" y="157.914">sink media</tspan>
- <tspan x="8.53836" y="173.914">bus format</tspan>
- </text>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="349.774" y="155">
- <tspan x="349.774" y="155">source media</tspan>
- <tspan x="349.774" y="171">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="350.488" y="190.834" width="93.2863" height="75.166"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="350.488" y="190.834" width="93.2863" height="75.166"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="266" x2="63.5" y2="288"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="190.834" x2="63.5" y2="211"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="266" x2="157.5" y2="288"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="190.834" x2="157.5" y2="211"/>
- <g>
- <ellipse style="fill: #ffffff" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="481.6" y1="219.984" x2="637.934" y2="220.012"/>
- <polygon style="fill: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="506.908" y="209.8">
- <tspan x="506.908" y="209.8">pad 1 (source)</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
- <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
- <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
- </text>
-</svg>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia
deleted file mode 100644
index a0d782927840..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-full.dia
+++ /dev/null
@@ -1,1588 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
- <dia:diagramdata>
- <dia:attribute name="background">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="pagebreak">
- <dia:color val="#000099"/>
- </dia:attribute>
- <dia:attribute name="paper">
- <dia:composite type="paper">
- <dia:attribute name="name">
- <dia:string>#A4#</dia:string>
- </dia:attribute>
- <dia:attribute name="tmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="bmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="lmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="rmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="is_portrait">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="scaling">
- <dia:real val="0.49000000953674316"/>
- </dia:attribute>
- <dia:attribute name="fitto">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="grid">
- <dia:composite type="grid">
- <dia:attribute name="width_x">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="width_y">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_x">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_y">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:composite type="color"/>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#d8e5e5"/>
- </dia:attribute>
- <dia:attribute name="guides">
- <dia:composite type="guides">
- <dia:attribute name="hguides"/>
- <dia:attribute name="vguides"/>
- </dia:composite>
- </dia:attribute>
- </dia:diagramdata>
- <dia:layer name="Background" visible="true" active="true">
- <dia:object type="Standard - Box" version="0" id="O0">
- <dia:attribute name="obj_pos">
- <dia:point val="15.945,6.45"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="15.895,6.4;26.4,18.95"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="15.945,6.45"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="10.404999999254942"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="12.449999999999992"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#ff765a"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O1">
- <dia:attribute name="obj_pos">
- <dia:point val="-0.1,3.65"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-0.15,3.6;40.25,20.85"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-0.1,3.65"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="40.300000000000004"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="17.149999999999999"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O2">
- <dia:attribute name="obj_pos">
- <dia:point val="-1.05,7.9106"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-1.1,7.8606;-0.15,8.8106"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-1.05,7.9106"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O3">
- <dia:attribute name="obj_pos">
- <dia:point val="40.3366,9.8342"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="40.2866,9.7842;41.2366,10.7342"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="40.3366,9.8342"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O4">
- <dia:attribute name="obj_pos">
- <dia:point val="-9.225,8.35"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-9.27509,7.97487;-0.938197,8.69848"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="-9.225,8.35"/>
- <dia:point val="-1.05,8.3356"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O2" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O5">
- <dia:attribute name="obj_pos">
- <dia:point val="41.1866,10.2592"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="41.1366,9.89879;49.6019,10.6224"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="41.1866,10.2592"/>
- <dia:point val="49.4901,10.2607"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O3" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O6">
- <dia:attribute name="obj_pos">
- <dia:point val="-6.998,7.75"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-6.998,7.155;-3.193,7.9025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 0 (sink)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="-6.998,7.75"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O7">
- <dia:attribute name="obj_pos">
- <dia:point val="42.452,9.75"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="42.452,9.155;47.097,9.9025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 2 (source)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="42.452,9.75"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O8">
- <dia:attribute name="obj_pos">
- <dia:point val="0.275,6"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.225,5.95;8.275,11.25"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="0.275,6"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="7.9499999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="5.1999999999999975"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O9">
- <dia:attribute name="obj_pos">
- <dia:point val="3.125,6.8"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.075,6.75;7.875,10.7"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="3.125,6.8"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="4.6999999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.8499999999999979"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O10">
- <dia:attribute name="obj_pos">
- <dia:point val="1.525,4.45"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="1.525,3.855;1.525,4.6025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="1.525,4.45"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O11">
- <dia:attribute name="obj_pos">
- <dia:point val="0.476918,4.44569"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.476918,3.85069;3.95942,5.39819"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="0.476918,4.44569"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O12">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.6322,9.23251;24.9922,17.9564"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="8.2600228398861297"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="8.6238900617957164"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#00ff00"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O13">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,17.9064"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.05732,10.5823;16.7499,17.9741"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="16.6822,17.9064"/>
- <dia:point val="3.125,10.65"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O12" connection="5"/>
- <dia:connection handle="1" to="O9" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O14">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3.06681,6.74181;16.7404,9.3407"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="16.6822,9.28251"/>
- <dia:point val="3.125,6.8"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O12" connection="0"/>
- <dia:connection handle="1" to="O9" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O15">
- <dia:attribute name="obj_pos">
- <dia:point val="24.9422,17.9064"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.75945,10.5845;25.0077,17.9719"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="24.9422,17.9064"/>
- <dia:point val="7.825,10.65"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O12" connection="7"/>
- <dia:connection handle="1" to="O9" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O16">
- <dia:attribute name="obj_pos">
- <dia:point val="24.9422,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.76834,6.74334;24.9989,9.33917"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="24.9422,9.28251"/>
- <dia:point val="7.825,6.8"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O12" connection="2"/>
- <dia:connection handle="1" to="O9" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O17">
- <dia:attribute name="obj_pos">
- <dia:point val="16.7352,7.47209"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.7352,6.87709;22.5602,8.42459"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink compose
-selection (scaling)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="16.7352,7.47209"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#00ff00"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O18">
- <dia:attribute name="obj_pos">
- <dia:point val="20.4661,9.72825"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="20.4161,9.67825;25.5254,13.3509"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="20.4661,9.72825"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O19">
- <dia:attribute name="obj_pos">
- <dia:point val="34.475,5.2564"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.475,4.6614;38.7975,6.2089"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#source media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="34.475,5.2564"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O20">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4244,8.6917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.3744,8.6417;39.4837,12.3143"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="34.4244,8.6917"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O21">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4244,12.2643"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="20.4125,12.2107;34.478,13.3545"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.4244,12.2643"/>
- <dia:point val="20.4661,13.3009"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O20" connection="5"/>
- <dia:connection handle="1" to="O18" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O22">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4244,8.6917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="20.4125,8.63813;34.478,9.78182"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.4244,8.6917"/>
- <dia:point val="20.4661,9.72825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O20" connection="0"/>
- <dia:connection handle="1" to="O18" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O23">
- <dia:attribute name="obj_pos">
- <dia:point val="39.4337,12.2643"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.4218,12.2107;39.4873,13.3545"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.4337,12.2643"/>
- <dia:point val="25.4754,13.3009"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O20" connection="7"/>
- <dia:connection handle="1" to="O18" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O24">
- <dia:attribute name="obj_pos">
- <dia:point val="39.4337,8.6917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.4218,8.63813;39.4873,9.78182"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.4337,8.6917"/>
- <dia:point val="25.4754,9.72825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O20" connection="2"/>
- <dia:connection handle="1" to="O18" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O25">
- <dia:attribute name="obj_pos">
- <dia:point val="16.25,5.15"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.25,4.555;21.68,6.1025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink compose
-bounds selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="16.25,5.15"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#ff765a"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O26">
- <dia:attribute name="obj_pos">
- <dia:point val="-1.02991,16.6506"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-1.07991,16.6006;-0.12991,17.5506"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-1.02991,16.6506"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O27">
- <dia:attribute name="obj_pos">
- <dia:point val="-9.20491,17.09"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-9.255,16.7149;-0.918107,17.4385"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="-9.20491,17.09"/>
- <dia:point val="-1.02991,17.0756"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O26" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O28">
- <dia:attribute name="obj_pos">
- <dia:point val="-6.95,16.45"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-6.95,15.855;-3.145,16.6025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 1 (sink)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="-6.95,16.45"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O29">
- <dia:attribute name="obj_pos">
- <dia:point val="0.390412,14.64"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.340412,14.59;6.045,18.8"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="0.390412,14.64"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.604587512785236"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="4.1099999999999994"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O30">
- <dia:attribute name="obj_pos">
- <dia:point val="2.645,15.74"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.595,15.69;5.6,18.3"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="2.645,15.74"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="2.904999999254942"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="2.5100000000000016"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O31">
- <dia:attribute name="obj_pos">
- <dia:point val="1.595,12.99"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="1.595,12.395;1.595,13.1425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="1.595,12.99"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O32">
- <dia:attribute name="obj_pos">
- <dia:point val="17.945,12.595"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.58596,12.536;18.004,15.799"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="17.945,12.595"/>
- <dia:point val="2.645,15.74"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O36" connection="0"/>
- <dia:connection handle="1" to="O30" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O33">
- <dia:attribute name="obj_pos">
- <dia:point val="17.945,15.8"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.58772,15.7427;18.0023,18.3073"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="17.945,15.8"/>
- <dia:point val="2.645,18.25"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O36" connection="5"/>
- <dia:connection handle="1" to="O30" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O34">
- <dia:attribute name="obj_pos">
- <dia:point val="21.7,15.8"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="5.49307,15.7431;21.7569,18.3069"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="21.7,15.8"/>
- <dia:point val="5.55,18.25"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O36" connection="7"/>
- <dia:connection handle="1" to="O30" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O35">
- <dia:attribute name="obj_pos">
- <dia:point val="21.7,12.595"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="5.49136,12.5364;21.7586,15.7986"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="21.7,12.595"/>
- <dia:point val="5.55,15.74"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O36" connection="2"/>
- <dia:connection handle="1" to="O30" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O36">
- <dia:attribute name="obj_pos">
- <dia:point val="17.945,12.595"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="17.895,12.545;21.75,15.85"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="17.945,12.595"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="3.7549999992549452"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.2049999992549427"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#00ff00"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O37">
- <dia:attribute name="obj_pos">
- <dia:point val="22.1631,14.2233"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="22.1131,14.1733;25.45,16.7"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="22.1631,14.2233"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="3.2369000000000021"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="2.4267000000000003"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O38">
- <dia:attribute name="obj_pos">
- <dia:point val="34.6714,16.2367"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.6214,16.1867;37.9,18.75"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="34.6714,16.2367"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="3.178600000000003"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="2.4632999999999967"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O39">
- <dia:attribute name="obj_pos">
- <dia:point val="34.6714,18.7"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="22.1057,16.5926;34.7288,18.7574"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.6714,18.7"/>
- <dia:point val="22.1631,16.65"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O38" connection="5"/>
- <dia:connection handle="1" to="O37" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O40">
- <dia:attribute name="obj_pos">
- <dia:point val="34.6714,16.2367"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="22.1058,14.166;34.7287,16.294"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.6714,16.2367"/>
- <dia:point val="22.1631,14.2233"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O38" connection="0"/>
- <dia:connection handle="1" to="O37" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O41">
- <dia:attribute name="obj_pos">
- <dia:point val="37.85,18.7"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.3425,16.5925;37.9075,18.7575"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="37.85,18.7"/>
- <dia:point val="25.4,16.65"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O38" connection="7"/>
- <dia:connection handle="1" to="O37" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O42">
- <dia:attribute name="obj_pos">
- <dia:point val="37.85,16.2367"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.3427,14.166;37.9073,16.294"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="37.85,16.2367"/>
- <dia:point val="25.4,14.2233"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O38" connection="2"/>
- <dia:connection handle="1" to="O37" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O43">
- <dia:attribute name="obj_pos">
- <dia:point val="40.347,16.7742"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="40.297,16.7242;41.247,17.6742"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="40.347,16.7742"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O44">
- <dia:attribute name="obj_pos">
- <dia:point val="41.197,17.1992"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="41.147,16.8388;49.6123,17.5624"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="41.197,17.1992"/>
- <dia:point val="49.5005,17.2007"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O43" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O45">
- <dia:attribute name="obj_pos">
- <dia:point val="42.4624,16.69"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="42.4624,16.095;47.1074,16.8425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 3 (source)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="42.4624,16.69"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O46">
- <dia:attribute name="obj_pos">
- <dia:point val="9.85,4.55"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="9.85,3.955;12.7275,6.3025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink
-crop
-selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="9.85,4.55"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O47">
- <dia:attribute name="obj_pos">
- <dia:point val="27.65,4.75"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="27.65,4.155;30.5275,6.5025"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#source
-crop
-selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="27.65,4.75"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O48">
- <dia:attribute name="obj_pos">
- <dia:point val="10.55,6.6"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.7135,6.39438;10.6035,7.11605"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="10.55,6.6"/>
- <dia:point val="7.825,6.8"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O9" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O49">
- <dia:attribute name="obj_pos">
- <dia:point val="10.45,6.55"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="5.48029,6.48236;10.5176,15.8387"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="10.45,6.55"/>
- <dia:point val="5.55,15.74"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O30" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O50">
- <dia:attribute name="obj_pos">
- <dia:point val="27.5246,6.66071"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.406,6.59136;27.594,9.82122"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="27.5246,6.66071"/>
- <dia:point val="25.4754,9.72825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O18" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O51">
- <dia:attribute name="obj_pos">
- <dia:point val="27.5036,6.68935"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="25.2161,6.62775;27.5652,14.331"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="27.5036,6.68935"/>
- <dia:point val="25.4,14.2233"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O37" connection="2"/>
- </dia:connections>
- </dia:object>
- </dia:layer>
-</dia:diagram>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg
deleted file mode 100644
index 3322cf4c0093..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-full.svg
+++ /dev/null
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="18cm" viewBox="-186 71 1178 346" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <g>
- <rect style="fill: #ffffff" x="318.9" y="129" width="208.1" height="249"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff765a" x="318.9" y="129" width="208.1" height="249"/>
- </g>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-2" y="73" width="806" height="343"/>
- <g>
- <ellipse style="fill: #ffffff" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <ellipse style="fill: #ffffff" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.5" y1="167" x2="-30.7361" y2="166.729"/>
- <polygon style="fill: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.732" y1="205.184" x2="980.066" y2="205.212"/>
- <polygon style="fill: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139.96" y="155">
- <tspan x="-139.96" y="155">pad 0 (sink)</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.04" y="195">
- <tspan x="849.04" y="195">pad 2 (source)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="5.5" y="120" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="5.5" y="120" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="62.5" y="136" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="62.5" y="136" width="94" height="77"/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="30.5" y="89">
- <tspan x="30.5" y="89"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="9.53836" y="88.9138">
- <tspan x="9.53836" y="88.9138">sink media</tspan>
- <tspan x="9.53836" y="104.914">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="62.5" y2="213"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="62.5" y2="136"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="156.5" y2="213"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="156.5" y2="136"/>
- <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
- <tspan x="334.704" y="149.442">sink compose</tspan>
- <tspan x="334.704" y="165.442">selection (scaling)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="409.322" y="194.565" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="409.322" y="194.565" width="100.186" height="71.4523"/>
- </g>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="689.5" y="105.128">
- <tspan x="689.5" y="105.128">source media</tspan>
- <tspan x="689.5" y="121.128">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="688.488" y="173.834" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="688.488" y="173.834" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="245.286" x2="409.322" y2="266.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="173.834" x2="409.322" y2="194.565"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="245.286" x2="509.508" y2="266.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="173.834" x2="509.508" y2="194.565"/>
- <text style="fill: #ff765a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="325" y="103">
- <tspan x="325" y="103">sink compose</tspan>
- <tspan x="325" y="119">bounds selection</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.098" y1="341.8" x2="-30.3343" y2="341.529"/>
- <polygon style="fill: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139" y="329">
- <tspan x="-139" y="329">pad 1 (sink)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="7.80824" y="292.8" width="112.092" height="82.2"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="7.80824" y="292.8" width="112.092" height="82.2"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="52.9" y="314.8" width="58.1" height="50.2"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="52.9" y="314.8" width="58.1" height="50.2"/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="31.9" y="259.8">
- <tspan x="31.9" y="259.8"></tspan>
- </text>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="251.9" x2="52.9" y2="314.8"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="316" x2="52.9" y2="365"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="316" x2="111" y2="365"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="251.9" x2="111" y2="314.8"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="358.9" y="251.9" width="75.1" height="64.1"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="443.262" y="284.466" width="64.738" height="48.534"/>
- <g>
- <rect style="fill: #ffffff" x="693.428" y="324.734" width="63.572" height="49.266"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="693.428" y="324.734" width="63.572" height="49.266"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="374" x2="443.262" y2="333"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="324.734" x2="443.262" y2="284.466"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="374" x2="508" y2="333"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="324.734" x2="508" y2="284.466"/>
- <g>
- <ellipse style="fill: #ffffff" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.94" y1="343.984" x2="980.274" y2="344.012"/>
- <polygon style="fill: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.248" y="333.8">
- <tspan x="849.248" y="333.8">pad 3 (source)</tspan>
- </text>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="197" y="91">
- <tspan x="197" y="91">sink</tspan>
- <tspan x="197" y="107">crop</tspan>
- <tspan x="197" y="123">selection</tspan>
- </text>
- <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="553" y="95">
- <tspan x="553" y="95">source</tspan>
- <tspan x="553" y="111">crop</tspan>
- <tspan x="553" y="127">selection</tspan>
- </text>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="211" y1="132" x2="166.21" y2="135.287"/>
- <polygon style="fill: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="209" y1="131" x2="115.581" y2="306.209"/>
- <polygon style="fill: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.492" y1="133.214" x2="514.916" y2="186.469"/>
- <polygon style="fill: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.072" y1="133.787" x2="510.618" y2="275.089"/>
- <polygon style="fill: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
- </g>
-</svg>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia
deleted file mode 100644
index 0cd50a7bda80..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.dia
+++ /dev/null
@@ -1,1152 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
- <dia:diagramdata>
- <dia:attribute name="background">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="pagebreak">
- <dia:color val="#000099"/>
- </dia:attribute>
- <dia:attribute name="paper">
- <dia:composite type="paper">
- <dia:attribute name="name">
- <dia:string>#A4#</dia:string>
- </dia:attribute>
- <dia:attribute name="tmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="bmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="lmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="rmargin">
- <dia:real val="2.8222000598907471"/>
- </dia:attribute>
- <dia:attribute name="is_portrait">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="scaling">
- <dia:real val="0.49000000953674316"/>
- </dia:attribute>
- <dia:attribute name="fitto">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="grid">
- <dia:composite type="grid">
- <dia:attribute name="width_x">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="width_y">
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_x">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="visible_y">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:composite type="color"/>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#d8e5e5"/>
- </dia:attribute>
- <dia:attribute name="guides">
- <dia:composite type="guides">
- <dia:attribute name="hguides"/>
- <dia:attribute name="vguides"/>
- </dia:composite>
- </dia:attribute>
- </dia:diagramdata>
- <dia:layer name="Background" visible="true" active="true">
- <dia:object type="Standard - Box" version="0" id="O0">
- <dia:attribute name="obj_pos">
- <dia:point val="-0.4,6.5"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-0.45,6.45;39.95,22.9"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-0.4,6.5"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="40.299999999999997"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="16.349999999999998"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O1">
- <dia:attribute name="obj_pos">
- <dia:point val="0.225,9.45"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.175,9.4;8.225,14.7"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="0.225,9.45"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="7.9499999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="5.1999999999999975"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O2">
- <dia:attribute name="obj_pos">
- <dia:point val="2.475,10.2"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.425,10.15;7.225,14.1"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="2.475,10.2"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="4.6999999999999975"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.8499999999999979"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O3">
- <dia:attribute name="obj_pos">
- <dia:point val="3,11.2"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="3,10.605;5.8775,12.9525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink
-crop
-selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="3,11.2"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#0000ff"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O4">
- <dia:attribute name="obj_pos">
- <dia:point val="1.475,7.9"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="1.475,7.305;1.475,8.0525"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>##</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="1.475,7.9"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O5">
- <dia:attribute name="obj_pos">
- <dia:point val="0.426918,7.89569"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="0.426918,7.30069;3.90942,8.84819"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="0.426918,7.89569"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#a52a2a"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O6">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.6322,9.23251;24.9922,17.9564"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="8.2600228398861297"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="8.6238900617957164"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#00ff00"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O7">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,17.9064"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.41365,13.9886;16.7436,17.9678"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="16.6822,17.9064"/>
- <dia:point val="2.475,14.05"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O6" connection="5"/>
- <dia:connection handle="1" to="O2" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O8">
- <dia:attribute name="obj_pos">
- <dia:point val="16.6822,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="2.42188,9.22939;16.7353,10.2531"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="16.6822,9.28251"/>
- <dia:point val="2.475,10.2"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O6" connection="0"/>
- <dia:connection handle="1" to="O2" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O9">
- <dia:attribute name="obj_pos">
- <dia:point val="24.9422,17.9064"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.11553,13.9905;25.0017,17.9659"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="24.9422,17.9064"/>
- <dia:point val="7.175,14.05"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O6" connection="7"/>
- <dia:connection handle="1" to="O2" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O10">
- <dia:attribute name="obj_pos">
- <dia:point val="24.9422,9.28251"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="7.12249,9.23;24.9947,10.2525"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="24.9422,9.28251"/>
- <dia:point val="7.175,10.2"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O6" connection="2"/>
- <dia:connection handle="1" to="O2" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O11">
- <dia:attribute name="obj_pos">
- <dia:point val="16.7352,7.47209"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="16.7352,6.87709;22.5602,8.42459"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#sink compose
-selection (scaling)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="16.7352,7.47209"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#00ff00"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O12">
- <dia:attribute name="obj_pos">
- <dia:point val="19.1161,9.97825"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.0661,9.92825;24.1754,13.6009"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="19.1161,9.97825"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O13">
- <dia:attribute name="obj_pos">
- <dia:point val="27.1661,7.47209"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="27.1661,6.87709;30.0436,9.22459"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#source
-crop
-selection#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="27.1661,7.47209"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O14">
- <dia:attribute name="obj_pos">
- <dia:point val="34.575,7.8564"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.575,7.2614;38.8975,8.8089"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#source media
-bus format#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="34.575,7.8564"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O15">
- <dia:attribute name="obj_pos">
- <dia:point val="34.5244,11.2917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.4744,11.2417;39.5837,14.9143"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="34.5244,11.2917"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O16">
- <dia:attribute name="obj_pos">
- <dia:point val="34.5244,14.8643"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.062,13.4968;34.5785,14.9184"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.5244,14.8643"/>
- <dia:point val="19.1161,13.5509"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O15" connection="5"/>
- <dia:connection handle="1" to="O12" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O17">
- <dia:attribute name="obj_pos">
- <dia:point val="34.5244,11.2917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.062,9.92418;34.5785,11.3458"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.5244,11.2917"/>
- <dia:point val="19.1161,9.97825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O15" connection="0"/>
- <dia:connection handle="1" to="O12" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O18">
- <dia:attribute name="obj_pos">
- <dia:point val="39.5337,14.8643"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.0713,13.4968;39.5878,14.9184"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.5337,14.8643"/>
- <dia:point val="24.1254,13.5509"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O15" connection="7"/>
- <dia:connection handle="1" to="O12" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O19">
- <dia:attribute name="obj_pos">
- <dia:point val="39.5337,11.2917"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.0713,9.92418;39.5878,11.3458"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.5337,11.2917"/>
- <dia:point val="24.1254,9.97825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O15" connection="2"/>
- <dia:connection handle="1" to="O12" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O20">
- <dia:attribute name="obj_pos">
- <dia:point val="39.98,12.0742"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="39.93,12.0242;40.88,12.9742"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="39.98,12.0742"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O21">
- <dia:attribute name="obj_pos">
- <dia:point val="40.83,12.4992"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="40.78,12.1388;49.2453,12.8624"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="40.83,12.4992"/>
- <dia:point val="49.1335,12.5007"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O20" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O22">
- <dia:attribute name="obj_pos">
- <dia:point val="42.0954,11.99"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="42.0954,11.395;46.7404,12.1425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 1 (source)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="42.0954,11.99"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O23">
- <dia:attribute name="obj_pos">
- <dia:point val="-1.44491,11.6506"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-1.49491,11.6006;-0.54491,12.5506"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="-1.44491,11.6506"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O24">
- <dia:attribute name="obj_pos">
- <dia:point val="-9.61991,12.09"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-9.67,11.7149;-1.33311,12.4385"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="-9.61991,12.09"/>
- <dia:point val="-1.44491,12.0756"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O23" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O25">
- <dia:attribute name="obj_pos">
- <dia:point val="-7.39291,11.49"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="-7.39291,10.895;-3.58791,11.6425"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 0 (sink)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="-7.39291,11.49"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O26">
- <dia:attribute name="obj_pos">
- <dia:point val="19.4911,13.8333"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.4411,13.7833;24.5504,17.4559"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="19.4911,13.8333"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="false"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Box" version="0" id="O27">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4994,17.2967"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="34.4494,17.2467;39.5587,20.9193"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="34.4994,17.2967"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="5.009308462554376"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="3.5726155970598077"/>
- </dia:attribute>
- <dia:attribute name="border_width">
- <dia:real val="0.10000000149011612"/>
- </dia:attribute>
- <dia:attribute name="border_color">
- <dia:color val="#8b6914"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O28">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4994,20.8693"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.4311,17.3459;34.5594,20.9293"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.4994,20.8693"/>
- <dia:point val="19.4911,17.4059"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O27" connection="5"/>
- <dia:connection handle="1" to="O26" connection="5"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O29">
- <dia:attribute name="obj_pos">
- <dia:point val="34.4994,17.2967"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="19.4311,13.7733;34.5594,17.3567"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="34.4994,17.2967"/>
- <dia:point val="19.4911,13.8333"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O27" connection="0"/>
- <dia:connection handle="1" to="O26" connection="0"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O30">
- <dia:attribute name="obj_pos">
- <dia:point val="39.5087,20.8693"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.4404,17.3459;39.5687,20.9293"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.5087,20.8693"/>
- <dia:point val="24.5004,17.4059"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O27" connection="7"/>
- <dia:connection handle="1" to="O26" connection="7"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O31">
- <dia:attribute name="obj_pos">
- <dia:point val="39.5087,17.2967"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.4404,13.7733;39.5687,17.3567"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="39.5087,17.2967"/>
- <dia:point val="24.5004,13.8333"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#e60505"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="4"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O27" connection="2"/>
- <dia:connection handle="1" to="O26" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Geometric - Perfect Circle" version="1" id="O32">
- <dia:attribute name="obj_pos">
- <dia:point val="39.855,18.7792"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="39.805,18.7292;40.755,19.6792"/>
- </dia:attribute>
- <dia:attribute name="meta">
- <dia:composite type="dict"/>
- </dia:attribute>
- <dia:attribute name="elem_corner">
- <dia:point val="39.855,18.7792"/>
- </dia:attribute>
- <dia:attribute name="elem_width">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="elem_height">
- <dia:real val="0.84999999999999787"/>
- </dia:attribute>
- <dia:attribute name="line_width">
- <dia:real val="0.10000000000000001"/>
- </dia:attribute>
- <dia:attribute name="line_colour">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="fill_colour">
- <dia:color val="#ffffff"/>
- </dia:attribute>
- <dia:attribute name="show_background">
- <dia:boolean val="true"/>
- </dia:attribute>
- <dia:attribute name="line_style">
- <dia:enum val="0"/>
- <dia:real val="1"/>
- </dia:attribute>
- <dia:attribute name="flip_horizontal">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="flip_vertical">
- <dia:boolean val="false"/>
- </dia:attribute>
- <dia:attribute name="subscale">
- <dia:real val="1"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O33">
- <dia:attribute name="obj_pos">
- <dia:point val="40.705,19.2042"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="40.655,18.8438;49.1203,19.5674"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="40.705,19.2042"/>
- <dia:point val="49.0085,19.2057"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="0" to="O32" connection="3"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Text" version="1" id="O34">
- <dia:attribute name="obj_pos">
- <dia:point val="41.9704,18.695"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="41.9704,18.1;46.6154,18.8475"/>
- </dia:attribute>
- <dia:attribute name="text">
- <dia:composite type="text">
- <dia:attribute name="string">
- <dia:string>#pad 2 (source)#</dia:string>
- </dia:attribute>
- <dia:attribute name="font">
- <dia:font family="sans" style="0" name="Helvetica"/>
- </dia:attribute>
- <dia:attribute name="height">
- <dia:real val="0.80000000000000004"/>
- </dia:attribute>
- <dia:attribute name="pos">
- <dia:point val="41.9704,18.695"/>
- </dia:attribute>
- <dia:attribute name="color">
- <dia:color val="#000000"/>
- </dia:attribute>
- <dia:attribute name="alignment">
- <dia:enum val="0"/>
- </dia:attribute>
- </dia:composite>
- </dia:attribute>
- <dia:attribute name="valign">
- <dia:enum val="3"/>
- </dia:attribute>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O35">
- <dia:attribute name="obj_pos">
- <dia:point val="27.3,9.55"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.0146,9.49376;27.3562,10.255"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="27.3,9.55"/>
- <dia:point val="24.1254,9.97825"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O12" connection="2"/>
- </dia:connections>
- </dia:object>
- <dia:object type="Standard - Line" version="0" id="O36">
- <dia:attribute name="obj_pos">
- <dia:point val="27.3454,9.53624"/>
- </dia:attribute>
- <dia:attribute name="obj_bb">
- <dia:rectangle val="24.4311,9.46695;27.4147,13.9265"/>
- </dia:attribute>
- <dia:attribute name="conn_endpoints">
- <dia:point val="27.3454,9.53624"/>
- <dia:point val="24.5004,13.8333"/>
- </dia:attribute>
- <dia:attribute name="numcp">
- <dia:int val="1"/>
- </dia:attribute>
- <dia:attribute name="line_color">
- <dia:color val="#a020f0"/>
- </dia:attribute>
- <dia:attribute name="end_arrow">
- <dia:enum val="22"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_length">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:attribute name="end_arrow_width">
- <dia:real val="0.5"/>
- </dia:attribute>
- <dia:connections>
- <dia:connection handle="1" to="O26" connection="2"/>
- </dia:connections>
- </dia:object>
- </dia:layer>
-</dia:diagram>
diff --git a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg b/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg
deleted file mode 100644
index 2340c0f8bc92..000000000000
--- a/Documentation/DocBook/media/v4l/subdev-image-processing-scaling-multi-source.svg
+++ /dev/null
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="17cm" viewBox="-194 128 1179 330" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="806" height="327"/>
- <g>
- <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
- </g>
- <g>
- <rect style="fill: #ffffff" x="49.5" y="204" width="94" height="77"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="49.5" y="204" width="94" height="77"/>
- </g>
- <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="60" y="224">
- <tspan x="60" y="224">sink</tspan>
- <tspan x="60" y="240">crop</tspan>
- <tspan x="60" y="256">selection</tspan>
- </text>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
- <tspan x="29.5" y="158"></tspan>
- </text>
- <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
- <tspan x="8.53836" y="157.914">sink media</tspan>
- <tspan x="8.53836" y="173.914">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="49.5" y2="281"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="49.5" y2="204"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="143.5" y2="281"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="143.5" y2="204"/>
- <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
- <tspan x="334.704" y="149.442">sink compose</tspan>
- <tspan x="334.704" y="165.442">selection (scaling)</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="382.322" y="199.565" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="382.322" y="199.565" width="100.186" height="71.4523"/>
- </g>
- <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="543.322" y="149.442">
- <tspan x="543.322" y="149.442">source</tspan>
- <tspan x="543.322" y="165.442">crop</tspan>
- <tspan x="543.322" y="181.442">selection</tspan>
- </text>
- <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="691.5" y="157.128">
- <tspan x="691.5" y="157.128">source media</tspan>
- <tspan x="691.5" y="173.128">bus format</tspan>
- </text>
- <g>
- <rect style="fill: #ffffff" x="690.488" y="225.834" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="690.488" y="225.834" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="297.286" x2="382.322" y2="271.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="225.834" x2="382.322" y2="199.565"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="297.286" x2="482.508" y2="271.018"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="225.834" x2="482.508" y2="199.565"/>
- <g>
- <ellipse style="fill: #ffffff" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="816.6" y1="249.984" x2="972.934" y2="250.012"/>
- <polygon style="fill: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="841.908" y="239.8">
- <tspan x="841.908" y="239.8">pad 1 (source)</tspan>
- </text>
- <g>
- <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
- <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
- <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
- </text>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="389.822" y="276.666" width="100.186" height="71.4523"/>
- <g>
- <rect style="fill: #ffffff" x="689.988" y="345.934" width="100.186" height="71.4523"/>
- <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="689.988" y="345.934" width="100.186" height="71.4523"/>
- </g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="417.386" x2="389.822" y2="348.118"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="345.934" x2="389.822" y2="276.666"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="417.386" x2="490.008" y2="348.118"/>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="345.934" x2="490.008" y2="276.666"/>
- <g>
- <ellipse style="fill: #ffffff" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="814.1" y1="384.084" x2="970.434" y2="384.112"/>
- <polygon style="fill: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
- </g>
- <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="839.408" y="373.9">
- <tspan x="839.408" y="373.9">pad 2 (source)</tspan>
- </text>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546" y1="191" x2="492.157" y2="198.263"/>
- <polygon style="fill: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
- </g>
- <g>
- <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546.908" y1="190.725" x2="495.383" y2="268.548"/>
- <polygon style="fill: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
- <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
- </g>
-</svg>
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
deleted file mode 100644
index 42e626d6c936..000000000000
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ /dev/null
@@ -1,728 +0,0 @@
- <partinfo>
- <authorgroup>
- <author>
- <firstname>Michael</firstname>
- <surname>Schimek</surname>
- <othername role="mi">H</othername>
- <affiliation>
- <address>
- <email>mschimek@gmx.at</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Bill</firstname>
- <surname>Dirks</surname>
- <!-- Commented until Bill opts in to be spammed.
- <affiliation>
- <address>
- <email>bill@thedirks.org</email>
- </address>
- </affiliation> -->
- <contrib>Original author of the V4L2 API and
-documentation.</contrib>
- </author>
-
- <author>
- <firstname>Hans</firstname>
- <surname>Verkuil</surname>
- <contrib>Designed and documented the VIDIOC_LOG_STATUS ioctl,
-the extended control ioctls, major parts of the sliced VBI API, the
-MPEG encoder and decoder APIs and the DV Timings API.</contrib>
- <affiliation>
- <address>
- <email>hverkuil@xs4all.nl</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Martin</firstname>
- <surname>Rubli</surname>
- <!--
- <affiliation>
- <address>
- <email>martin_rubli@logitech.com</email>
- </address>
- </affiliation> -->
- <contrib>Designed and documented the VIDIOC_ENUM_FRAMESIZES
-and VIDIOC_ENUM_FRAMEINTERVALS ioctls.</contrib>
- </author>
-
- <author>
- <firstname>Andy</firstname>
- <surname>Walls</surname>
- <contrib>Documented the fielded V4L2_MPEG_STREAM_VBI_FMT_IVTV
-MPEG stream embedded, sliced VBI data format in this specification.
-</contrib>
- <affiliation>
- <address>
- <email>awalls@md.metrocast.net</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Mauro</firstname>
- <surname>Carvalho Chehab</surname>
- <contrib>Documented libv4l, designed and added v4l2grab example,
-Remote Controller chapter.</contrib>
- <affiliation>
- <address>
- <email>m.chehab@samsung.com</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Muralidharan</firstname>
- <surname>Karicheri</surname>
- <contrib>Documented the Digital Video timings API.</contrib>
- <affiliation>
- <address>
- <email>m-karicheri2@ti.com</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Pawel</firstname>
- <surname>Osciak</surname>
- <contrib>Designed and documented the multi-planar API.</contrib>
- <affiliation>
- <address>
- <email>pawel AT osciak.com</email>
- </address>
- </affiliation>
- </author>
-
- <author>
- <firstname>Sakari</firstname>
- <surname>Ailus</surname>
- <contrib>Subdev selections API.</contrib>
- <affiliation>
- <address>
- <email>sakari.ailus@iki.fi</email>
- </address>
- </affiliation>
- </author>
- <author>
- <firstname>Antti</firstname>
- <surname>Palosaari</surname>
- <contrib>SDR API.</contrib>
- <affiliation>
- <address>
- <email>crope@iki.fi</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
-
- <copyright>
- <year>1999</year>
- <year>2000</year>
- <year>2001</year>
- <year>2002</year>
- <year>2003</year>
- <year>2004</year>
- <year>2005</year>
- <year>2006</year>
- <year>2007</year>
- <year>2008</year>
- <year>2009</year>
- <year>2010</year>
- <year>2011</year>
- <year>2012</year>
- <year>2013</year>
- <year>2014</year>
- <year>2015</year>
- <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
-Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
- Pawel Osciak</holder>
- </copyright>
- <legalnotice>
- <para>Except when explicitly stated as GPL, programming examples within
- this part can be used and distributed without restrictions.</para>
- </legalnotice>
- <revhistory>
- <!-- Put document revisions here, newest first. -->
- <!-- API revisions (changes and additions of defines, enums,
-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>4.5</revnumber>
- <date>2015-10-29</date>
- <authorinitials>rr</authorinitials>
- <revremark>Extend vidioc-g-ext-ctrls;. Replace ctrl_class with a new
-union with ctrl_class and which. Which is used to select the current value of
-the control or the default value.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>4.4</revnumber>
- <date>2015-05-26</date>
- <authorinitials>ap</authorinitials>
- <revremark>Renamed V4L2_TUNER_ADC to V4L2_TUNER_SDR.
-Added V4L2_CID_RF_TUNER_RF_GAIN control.
-Added transmitter support for Software Defined Radio (SDR) Interface.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>4.1</revnumber>
- <date>2015-02-13</date>
- <authorinitials>mcc</authorinitials>
- <revremark>Fix documentation for media controller device nodes and add support for DVB device nodes.
-Add support for Tuner sub-device.
- </revremark>
- </revision>
- <revision>
- <revnumber>3.19</revnumber>
- <date>2014-12-05</date>
- <authorinitials>hv</authorinitials>
- <revremark>Rewrote Colorspace chapter, added new &v4l2-ycbcr-encoding; and &v4l2-quantization; fields
-to &v4l2-pix-format;, &v4l2-pix-format-mplane; and &v4l2-mbus-framefmt;.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.17</revnumber>
- <date>2014-08-04</date>
- <authorinitials>lp, hv</authorinitials>
- <revremark>Extended &v4l2-pix-format;. Added format flags. Added compound control types
-and VIDIOC_QUERY_EXT_CTRL.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.15</revnumber>
- <date>2014-02-03</date>
- <authorinitials>hv, ap</authorinitials>
- <revremark>Update several sections of "Common API Elements": "Opening and Closing Devices"
-"Querying Capabilities", "Application Priority", "Video Inputs and Outputs", "Audio Inputs and Outputs"
-"Tuners and Modulators", "Video Standards" and "Digital Video (DV) Timings". Added SDR API.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.14</revnumber>
- <date>2013-11-25</date>
- <authorinitials>rr</authorinitials>
- <revremark>Set width and height as unsigned on v4l2_rect.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.11</revnumber>
- <date>2013-05-26</date>
- <authorinitials>hv</authorinitials>
- <revremark>Remove obsolete VIDIOC_DBG_G_CHIP_IDENT ioctl.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.10</revnumber>
- <date>2013-03-25</date>
- <authorinitials>hv</authorinitials>
- <revremark>Remove obsolete and unused DV_PRESET ioctls:
- VIDIOC_G_DV_PRESET, VIDIOC_S_DV_PRESET, VIDIOC_QUERY_DV_PRESET and
- VIDIOC_ENUM_DV_PRESET. Remove the related v4l2_input/output capability
- flags V4L2_IN_CAP_PRESETS and V4L2_OUT_CAP_PRESETS. Added VIDIOC_DBG_G_CHIP_INFO.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.9</revnumber>
- <date>2012-12-03</date>
- <authorinitials>sa, sn</authorinitials>
- <revremark>Added timestamp types to v4l2_buffer.
- Added V4L2_EVENT_CTRL_CH_RANGE control event changes flag.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.6</revnumber>
- <date>2012-07-02</date>
- <authorinitials>hv</authorinitials>
- <revremark>Added VIDIOC_ENUM_FREQ_BANDS.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.5</revnumber>
- <date>2012-05-07</date>
- <authorinitials>sa, sn, hv</authorinitials>
- <revremark>Added V4L2_CTRL_TYPE_INTEGER_MENU and V4L2 subdev
- selections API. Improved the description of V4L2_CID_COLORFX
- control, added V4L2_CID_COLORFX_CBCR control.
- Added camera controls V4L2_CID_AUTO_EXPOSURE_BIAS,
- V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, V4L2_CID_IMAGE_STABILIZATION,
- V4L2_CID_ISO_SENSITIVITY, V4L2_CID_ISO_SENSITIVITY_AUTO,
- V4L2_CID_EXPOSURE_METERING, V4L2_CID_SCENE_MODE,
- V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START,
- V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS
- and V4L2_CID_AUTO_FOCUS_RANGE.
- Added VIDIOC_ENUM_DV_TIMINGS, VIDIOC_QUERY_DV_TIMINGS and
- VIDIOC_DV_TIMINGS_CAP.
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.4</revnumber>
- <date>2012-01-25</date>
- <authorinitials>sn</authorinitials>
- <revremark>Added <link linkend="jpeg-controls">JPEG compression
- control class.</link>
- </revremark>
- </revision>
-
- <revision>
- <revnumber>3.3</revnumber>
- <date>2012-01-11</date>
- <authorinitials>hv</authorinitials>
- <revremark>Added device_caps field to struct v4l2_capabilities.</revremark>
- </revision>
-
- <revision>
- <revnumber>3.2</revnumber>
- <date>2011-08-26</date>
- <authorinitials>hv</authorinitials>
- <revremark>Added V4L2_CTRL_FLAG_VOLATILE.</revremark>
- </revision>
-
- <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>
- <authorinitials>mcc, po</authorinitials>
- <revremark>Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. Added the <link linkend="planar-apis">multi-planar API</link>.</revremark>
- </revision>
-
- <revision>
- <revnumber>2.6.37</revnumber>
- <date>2010-08-06</date>
- <authorinitials>hv</authorinitials>
- <revremark>Removed obsolete vtx (videotext) API.</revremark>
- </revision>
-
- <revision>
- <revnumber>2.6.33</revnumber>
- <date>2009-12-03</date>
- <authorinitials>mk</authorinitials>
- <revremark>Added documentation for the Digital Video timings API.</revremark>
- </revision>
-
- <revision>
- <revnumber>2.6.32</revnumber>
- <date>2009-08-31</date>
- <authorinitials>mcc</authorinitials>
- <revremark>Now, revisions will match the kernel version where
-the V4L2 API changes will be used by the Linux Kernel.
-Also added Remote Controller chapter.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.29</revnumber>
- <date>2009-08-26</date>
- <authorinitials>ev</authorinitials>
- <revremark>Added documentation for string controls and for FM Transmitter controls.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.28</revnumber>
- <date>2009-08-26</date>
- <authorinitials>gl</authorinitials>
- <revremark>Added V4L2_CID_BAND_STOP_FILTER documentation.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.27</revnumber>
- <date>2009-08-15</date>
- <authorinitials>mcc</authorinitials>
- <revremark>Added libv4l and Remote Controller documentation;
-added v4l2grab and keytable application examples.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.26</revnumber>
- <date>2009-07-23</date>
- <authorinitials>hv</authorinitials>
- <revremark>Finalized the RDS capture API. Added modulator and RDS encoder
-capabilities. Added support for string controls.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.25</revnumber>
- <date>2009-01-18</date>
- <authorinitials>hv</authorinitials>
- <revremark>Added pixel formats VYUY, NV16 and NV61, and changed
-the debug ioctls VIDIOC_DBG_G/S_REGISTER and VIDIOC_DBG_G_CHIP_IDENT.
-Added camera controls V4L2_CID_ZOOM_ABSOLUTE, V4L2_CID_ZOOM_RELATIVE,
-V4L2_CID_ZOOM_CONTINUOUS and V4L2_CID_PRIVACY.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.24</revnumber>
- <date>2008-03-04</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Added pixel formats Y16 and SBGGR16, new controls
-and a camera controls class. Removed VIDIOC_G/S_MPEGCOMP.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.23</revnumber>
- <date>2007-08-30</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Fixed a typo in VIDIOC_DBG_G/S_REGISTER.
-Clarified the byte order of packed pixel formats.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.22</revnumber>
- <date>2007-08-29</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Added the Video Output Overlay interface, new MPEG
-controls, V4L2_FIELD_INTERLACED_TB and V4L2_FIELD_INTERLACED_BT,
-VIDIOC_DBG_G/S_REGISTER, VIDIOC_(TRY_)ENCODER_CMD,
-VIDIOC_G_CHIP_IDENT, VIDIOC_G_ENC_INDEX, new pixel formats.
-Clarifications in the cropping chapter, about RGB pixel formats, the
-mmap(), poll(), select(), read() and write() functions. Typographical
-fixes.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.21</revnumber>
- <date>2006-12-19</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Fixed a link in the VIDIOC_G_EXT_CTRLS section.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.20</revnumber>
- <date>2006-11-24</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Clarified the purpose of the audioset field in
-struct v4l2_input and v4l2_output.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.19</revnumber>
- <date>2006-10-19</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Documented V4L2_PIX_FMT_RGB444.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.18</revnumber>
- <date>2006-10-18</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Added the description of extended controls by Hans
-Verkuil. Linked V4L2_PIX_FMT_MPEG to V4L2_CID_MPEG_STREAM_TYPE.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.17</revnumber>
- <date>2006-10-12</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Corrected V4L2_PIX_FMT_HM12 description.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.16</revnumber>
- <date>2006-10-08</date>
- <authorinitials>mhs</authorinitials>
- <revremark>VIDIOC_ENUM_FRAMESIZES and
-VIDIOC_ENUM_FRAMEINTERVALS are now part of the API.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.15</revnumber>
- <date>2006-09-23</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Cleaned up the bibliography, added BT.653 and
-BT.1119. capture.c/start_capturing() for user pointer I/O did not
-initialize the buffer index. Documented the V4L MPEG and MJPEG
-VID_TYPEs and V4L2_PIX_FMT_SBGGR8. Updated the list of reserved pixel
-formats. See the history chapter for API changes.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.14</revnumber>
- <date>2006-09-14</date>
- <authorinitials>mr</authorinitials>
- <revremark>Added VIDIOC_ENUM_FRAMESIZES and
-VIDIOC_ENUM_FRAMEINTERVALS proposal for frame format enumeration of
-digital devices.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.13</revnumber>
- <date>2006-04-07</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Corrected the description of struct v4l2_window
-clips. New V4L2_STD_ and V4L2_TUNER_MODE_LANG1_LANG2
-defines.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.12</revnumber>
- <date>2006-02-03</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Corrected the description of struct
-v4l2_captureparm and v4l2_outputparm.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.11</revnumber>
- <date>2006-01-27</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Improved the description of struct
-v4l2_tuner.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.10</revnumber>
- <date>2006-01-10</date>
- <authorinitials>mhs</authorinitials>
- <revremark>VIDIOC_G_INPUT and VIDIOC_S_PARM
-clarifications.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.9</revnumber>
- <date>2005-11-27</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Improved the 525 line numbering diagram. Hans
-Verkuil and I rewrote the sliced VBI section. He also contributed a
-VIDIOC_LOG_STATUS page. Fixed VIDIOC_S_STD call in the video standard
-selection example. Various updates.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.8</revnumber>
- <date>2004-10-04</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Somehow a piece of junk slipped into the capture
-example, removed.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.7</revnumber>
- <date>2004-09-19</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Fixed video standard selection, control
-enumeration, downscaling and aspect example. Added read and user
-pointer i/o to video capture example.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.6</revnumber>
- <date>2004-08-01</date>
- <authorinitials>mhs</authorinitials>
- <revremark>v4l2_buffer changes, added video capture example,
-various corrections.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.5</revnumber>
- <date>2003-11-05</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Pixel format erratum.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.4</revnumber>
- <date>2003-09-17</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Corrected source and Makefile to generate a PDF.
-SGML fixes. Added latest API changes. Closed gaps in the history
-chapter.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.3</revnumber>
- <date>2003-02-05</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Another draft, more corrections.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.2</revnumber>
- <date>2003-01-15</date>
- <authorinitials>mhs</authorinitials>
- <revremark>Second draft, with corrections pointed out by Gerd
-Knorr.</revremark>
- </revision>
-
- <revision>
- <revnumber>0.1</revnumber>
- <date>2002-12-01</date>
- <authorinitials>mhs</authorinitials>
- <revremark>First draft, based on documentation by Bill Dirks
-and discussions on the V4L mailing list.</revremark>
- </revision>
- </revhistory>
-</partinfo>
-
-<title>Video for Linux Two API Specification</title>
- <subtitle>Revision 4.4</subtitle>
-
- <chapter id="common">
- &sub-common;
- </chapter>
-
- <chapter id="pixfmt">
- &sub-pixfmt;
- </chapter>
-
- <chapter id="io">
- &sub-io;
- </chapter>
-
- <chapter id="devices">
- <title>Interfaces</title>
-
- <section id="capture"> &sub-dev-capture; </section>
- <section id="overlay"> &sub-dev-overlay; </section>
- <section id="output"> &sub-dev-output; </section>
- <section id="osd"> &sub-dev-osd; </section>
- <section id="codec"> &sub-dev-codec; </section>
- <section id="effect"> &sub-dev-effect; </section>
- <section id="raw-vbi"> &sub-dev-raw-vbi; </section>
- <section id="sliced"> &sub-dev-sliced-vbi; </section>
- <section id="ttx"> &sub-dev-teletext; </section>
- <section id="radio"> &sub-dev-radio; </section>
- <section id="rds"> &sub-dev-rds; </section>
- <section id="sdr"> &sub-dev-sdr; </section>
- <section id="event"> &sub-dev-event; </section>
- <section id="subdev"> &sub-dev-subdev; </section>
- </chapter>
-
- <chapter id="driver">
- &sub-driver;
- </chapter>
-
- <chapter id="libv4l">
- &sub-libv4l;
- </chapter>
-
- <chapter id="compat">
- &sub-compat;
- </chapter>
-
- <appendix id="user-func">
- <title>Function Reference</title>
-
- <!-- Keep this alphabetically sorted. -->
-
- &sub-close;
- &sub-ioctl;
- <!-- All ioctls go here. -->
- &sub-create-bufs;
- &sub-cropcap;
- &sub-dbg-g-chip-info;
- &sub-dbg-g-register;
- &sub-decoder-cmd;
- &sub-dqevent;
- &sub-dv-timings-cap;
- &sub-encoder-cmd;
- &sub-enumaudio;
- &sub-enumaudioout;
- &sub-enum-dv-timings;
- &sub-enum-fmt;
- &sub-enum-framesizes;
- &sub-enum-frameintervals;
- &sub-enum-freq-bands;
- &sub-enuminput;
- &sub-enumoutput;
- &sub-enumstd;
- &sub-expbuf;
- &sub-g-audio;
- &sub-g-audioout;
- &sub-g-crop;
- &sub-g-ctrl;
- &sub-g-dv-timings;
- &sub-g-edid;
- &sub-g-enc-index;
- &sub-g-ext-ctrls;
- &sub-g-fbuf;
- &sub-g-fmt;
- &sub-g-frequency;
- &sub-g-input;
- &sub-g-jpegcomp;
- &sub-g-modulator;
- &sub-g-output;
- &sub-g-parm;
- &sub-g-priority;
- &sub-g-selection;
- &sub-g-sliced-vbi-cap;
- &sub-g-std;
- &sub-g-tuner;
- &sub-log-status;
- &sub-overlay;
- &sub-prepare-buf;
- &sub-qbuf;
- &sub-querybuf;
- &sub-querycap;
- &sub-queryctrl;
- &sub-query-dv-timings;
- &sub-querystd;
- &sub-reqbufs;
- &sub-s-hw-freq-seek;
- &sub-streamon;
- &sub-subdev-enum-frame-interval;
- &sub-subdev-enum-frame-size;
- &sub-subdev-enum-mbus-code;
- &sub-subdev-g-crop;
- &sub-subdev-g-fmt;
- &sub-subdev-g-frame-interval;
- &sub-subdev-g-selection;
- &sub-subscribe-event;
- <!-- End of ioctls. -->
- &sub-mmap;
- &sub-munmap;
- &sub-open;
- &sub-poll;
- &sub-read;
- &sub-select;
- &sub-write;
- </appendix>
-
- <appendix>
- <title>Common definitions for V4L2 and V4L2 subdev interfaces</title>
- &sub-selections-common;
- </appendix>
-
- <appendix id="videodev">
- <title>Video For Linux Two Header File</title>
- &sub-videodev2-h;
- </appendix>
-
- <appendix id="capture-example">
- <title>Video Capture Example</title>
- &sub-capture-c;
- </appendix>
-
- <appendix id="v4l2grab-example">
- <title>Video Grabber example using libv4l</title>
- <para>This program demonstrates how to grab V4L2 images in ppm format by
-using libv4l handlers. The advantage is that this grabber can potentially work
-with any V4L2 driver.</para>
- &sub-v4l2grab-c;
- </appendix>
-
- &sub-media-indices;
-
- &sub-biblio;
-
diff --git a/Documentation/DocBook/media/v4l/v4l2grab.c.xml b/Documentation/DocBook/media/v4l/v4l2grab.c.xml
deleted file mode 100644
index bed12e40be27..000000000000
--- a/Documentation/DocBook/media/v4l/v4l2grab.c.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-<programlisting>
-/* V4L2 video picture grabber
- Copyright (C) 2009 Mauro Carvalho Chehab &lt;mchehab@infradead.org&gt;
-
- 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 &lt;stdio.h&gt;
-#include &lt;stdlib.h&gt;
-#include &lt;string.h&gt;
-#include &lt;fcntl.h&gt;
-#include &lt;errno.h&gt;
-#include &lt;sys/ioctl.h&gt;
-#include &lt;sys/types.h&gt;
-#include &lt;sys/time.h&gt;
-#include &lt;sys/mman.h&gt;
-#include &lt;linux/videodev2.h&gt;
-#include "../libv4l/include/libv4l2.h"
-
-#define CLEAR(x) memset(&amp;(x), 0, sizeof(x))
-
-struct buffer {
- void *start;
- size_t length;
-};
-
-static void xioctl(int fh, int request, void *arg)
-{
- int r;
-
- do {
- r = v4l2_ioctl(fh, request, arg);
- } while (r == -1 &amp;&amp; ((errno == EINTR) || (errno == EAGAIN)));
-
- if (r == -1) {
- fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
- exit(EXIT_FAILURE);
- }
-}
-
-int main(int argc, char **argv)
-{
- struct <link linkend="v4l2-format">v4l2_format</link> fmt;
- struct <link linkend="v4l2-buffer">v4l2_buffer</link> buf;
- struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> req;
- enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
- fd_set fds;
- struct timeval tv;
- int r, fd = -1;
- unsigned int i, n_buffers;
- char *dev_name = "/dev/video0";
- char out_name[256];
- FILE *fout;
- struct buffer *buffers;
-
- fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
- if (fd &lt; 0) {
- perror("Cannot open device");
- exit(EXIT_FAILURE);
- }
-
- CLEAR(fmt);
- fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt.fmt.pix.width = 640;
- fmt.fmt.pix.height = 480;
- fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
- xioctl(fd, VIDIOC_S_FMT, &amp;fmt);
- if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
- printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
- exit(EXIT_FAILURE);
- }
- if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
- printf("Warning: driver is sending image at %dx%d\n",
- fmt.fmt.pix.width, fmt.fmt.pix.height);
-
- CLEAR(req);
- req.count = 2;
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- xioctl(fd, VIDIOC_REQBUFS, &amp;req);
-
- buffers = calloc(req.count, sizeof(*buffers));
- for (n_buffers = 0; n_buffers &lt; req.count; ++n_buffers) {
- CLEAR(buf);
-
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = n_buffers;
-
- xioctl(fd, VIDIOC_QUERYBUF, &amp;buf);
-
- buffers[n_buffers].length = buf.length;
- buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
- PROT_READ | PROT_WRITE, MAP_SHARED,
- fd, buf.m.offset);
-
- if (MAP_FAILED == buffers[n_buffers].start) {
- perror("mmap");
- exit(EXIT_FAILURE);
- }
- }
-
- for (i = 0; i &lt; n_buffers; ++i) {
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- buf.index = i;
- xioctl(fd, VIDIOC_QBUF, &amp;buf);
- }
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- xioctl(fd, VIDIOC_STREAMON, &amp;type);
- for (i = 0; i &lt; 20; i++) {
- do {
- FD_ZERO(&amp;fds);
- FD_SET(fd, &amp;fds);
-
- /* Timeout. */
- tv.tv_sec = 2;
- tv.tv_usec = 0;
-
- r = select(fd + 1, &amp;fds, NULL, NULL, &amp;tv);
- } while ((r == -1 &amp;&amp; (errno = EINTR)));
- if (r == -1) {
- perror("select");
- return errno;
- }
-
- CLEAR(buf);
- buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf.memory = V4L2_MEMORY_MMAP;
- xioctl(fd, VIDIOC_DQBUF, &amp;buf);
-
- sprintf(out_name, "out%03d.ppm", i);
- fout = fopen(out_name, "w");
- if (!fout) {
- perror("Cannot open image");
- exit(EXIT_FAILURE);
- }
- fprintf(fout, "P6\n%d %d 255\n",
- fmt.fmt.pix.width, fmt.fmt.pix.height);
- fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
- fclose(fout);
-
- xioctl(fd, VIDIOC_QBUF, &amp;buf);
- }
-
- type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- xioctl(fd, VIDIOC_STREAMOFF, &amp;type);
- for (i = 0; i &lt; n_buffers; ++i)
- v4l2_munmap(buffers[i].start, buffers[i].length);
- v4l2_close(fd);
-
- return 0;
-}
-</programlisting>
diff --git a/Documentation/DocBook/media/v4l/vbi_525.pdf b/Documentation/DocBook/media/v4l/vbi_525.pdf
deleted file mode 100644
index 9e72c25b208d..000000000000
--- a/Documentation/DocBook/media/v4l/vbi_525.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/vbi_625.pdf b/Documentation/DocBook/media/v4l/vbi_625.pdf
deleted file mode 100644
index 765235e33a4d..000000000000
--- a/Documentation/DocBook/media/v4l/vbi_625.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/vbi_hsync.pdf b/Documentation/DocBook/media/v4l/vbi_hsync.pdf
deleted file mode 100644
index 200b668189bf..000000000000
--- a/Documentation/DocBook/media/v4l/vbi_hsync.pdf
+++ /dev/null
Binary files differ
diff --git a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml b/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
deleted file mode 100644
index 6528e97b8990..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-create-bufs.xml
+++ /dev/null
@@ -1,158 +0,0 @@
-<refentry id="vidioc-create-bufs">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_CREATE_BUFS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_CREATE_BUFS</refname>
- <refpurpose>Create buffers for Memory Mapped or User Pointer or DMA Buffer
- I/O</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_create_buffers *<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_CREATE_BUFS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl is used to create buffers for <link linkend="mmap">memory
-mapped</link> or <link linkend="userp">user pointer</link> or <link
-linkend="dmabuf">DMA buffer</link> I/O. It can be used as an alternative or in
-addition to the &VIDIOC-REQBUFS; ioctl, when a tighter
-control over buffers is required. This ioctl can be called multiple times to
-create buffers of different sizes.</para>
-
- <para>To allocate the device buffers applications must initialize the
-relevant fields of the <structname>v4l2_create_buffers</structname> structure.
-The <structfield>count</structfield> field must be set to the number of
-requested buffers, the <structfield>memory</structfield> field specifies the
-requested I/O method and the <structfield>reserved</structfield> array must be
-zeroed.</para>
-
- <para>The <structfield>format</structfield> field specifies the image format
-that the buffers must be able to handle. The application has to fill in this
-&v4l2-format;. Usually this will be done using the &VIDIOC-TRY-FMT; or &VIDIOC-G-FMT; ioctls
-to ensure that the requested format is supported by the driver.
-Based on the format's <structfield>type</structfield> field the requested buffer
-size (for single-planar) or plane sizes (for multi-planar formats) will be
-used for the allocated buffers. The driver may return an error if the size(s)
-are not supported by the hardware (usually because they are too small).</para>
-
- <para>The buffers created by this ioctl will have as minimum size the size
-defined by the <structfield>format.pix.sizeimage</structfield> field (or the
-corresponding fields for other format types). Usually if the
-<structfield>format.pix.sizeimage</structfield> field is less than the minimum
-required for the given format, then an error will be returned since drivers will
-typically not allow this. If it is larger, then the value will be used as-is.
-In other words, the driver may reject the requested size, but if it is accepted
-the driver will use it unchanged.</para>
-
- <para>When the ioctl is called with a pointer to this structure the driver
-will attempt to allocate up to the requested number of buffers and store the
-actual number allocated and the starting index in the
-<structfield>count</structfield> and the <structfield>index</structfield> fields
-respectively. On return <structfield>count</structfield> can be smaller than
-the number requested.</para>
-
- <table pgwide="1" frame="none" id="v4l2-create-buffers">
- <title>struct <structname>v4l2_create_buffers</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>The starting buffer index, returned by the driver.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>count</structfield></entry>
- <entry>The number of buffers requested or granted. If count == 0, then
- <constant>VIDIOC_CREATE_BUFS</constant> will set <structfield>index</structfield>
- to the current number of created buffers, and it will check the validity of
- <structfield>memory</structfield> and <structfield>format.type</structfield>.
- If those are invalid -1 is returned and errno is set to &EINVAL;,
- otherwise <constant>VIDIOC_CREATE_BUFS</constant> returns 0. It will
- never set errno to &EBUSY; in this particular case.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>memory</structfield></entry>
- <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant>,
-<constant>V4L2_MEMORY_DMABUF</constant> or
-<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
-/></entry>
- </row>
- <row>
- <entry>&v4l2-format;</entry>
- <entry><structfield>format</structfield></entry>
- <entry>Filled in by the application, preserved by the driver.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>A place holder for future extensions. Drivers and applications
-must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>ENOMEM</errorcode></term>
- <listitem>
- <para>No memory to allocate buffers for <link linkend="mmap">memory
-mapped</link> I/O.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The buffer type (<structfield>format.type</structfield> field),
-requested I/O method (<structfield>memory</structfield>) or format
-(<structfield>format</structfield> field) is not valid.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-cropcap.xml b/Documentation/DocBook/media/v4l/vidioc-cropcap.xml
deleted file mode 100644
index 50cb940cbe5c..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-cropcap.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<refentry id="vidioc-cropcap">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_CROPCAP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_CROPCAP</refname>
- <refpurpose>Information about the video cropping and scaling abilities</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_cropcap
-*<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_CROPCAP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Applications use this function to query the cropping
-limits, the pixel aspect of images and to calculate scale factors.
-They set the <structfield>type</structfield> field of a v4l2_cropcap
-structure to the respective buffer (stream) type and call the
-<constant>VIDIOC_CROPCAP</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure. The results are
-constant except when switching the video standard. Remember this
-switch can occur implicit when switching the video input or
-output.</para>
-
-<para>Do not use the multiplanar buffer types. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
-and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
-
- <para>This ioctl must be implemented for video capture or output devices that
-support cropping and/or scaling and/or have non-square pixels, and for overlay devices.</para>
-
- <table pgwide="1" frame="none" id="v4l2-cropcap">
- <title>struct <structname>v4l2_cropcap</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the data stream, set by the application.
-Only these types are valid here:
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
- </row>
- <row>
- <entry>struct <link linkend="v4l2-rect-crop">v4l2_rect</link></entry>
- <entry><structfield>bounds</structfield></entry>
- <entry>Defines the window within capturing or output is
-possible, this may exclude for example the horizontal and vertical
-blanking areas. The cropping rectangle cannot exceed these limits.
-Width and height are defined in pixels, the driver writer is free to
-choose origin and units of the coordinate system in the analog
-domain.</entry>
- </row>
- <row>
- <entry>struct <link linkend="v4l2-rect-crop">v4l2_rect</link></entry>
- <entry><structfield>defrect</structfield></entry>
- <entry>Default cropping rectangle, it shall cover the
-"whole picture". Assuming pixel aspect 1/1 this could be for example a
-640&nbsp;&times;&nbsp;480 rectangle for NTSC, a
-768&nbsp;&times;&nbsp;576 rectangle for PAL and SECAM centered over
-the active picture area. The same co-ordinate system as for
- <structfield>bounds</structfield> is used.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>pixelaspect</structfield></entry>
- <entry><para>This is the pixel aspect (y / x) when no
-scaling is applied, the ratio of the actual sampling
-frequency and the frequency required to get square
-pixels.</para><para>When cropping coordinates refer to square pixels,
-the driver sets <structfield>pixelaspect</structfield> to 1/1. Other
-common values are 54/59 for PAL and SECAM, 11/10 for NTSC sampled
-according to [<xref linkend="itu601" />].</para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- NB this table is duplicated in the overlay chapter. -->
-
- <table pgwide="1" frame="none" id="v4l2-rect-crop">
- <title>struct <structname>v4l2_rect</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__s32</entry>
- <entry><structfield>left</structfield></entry>
- <entry>Horizontal offset of the top, left corner of the
-rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>top</structfield></entry>
- <entry>Vertical offset of the top, left corner of the
-rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Width of the rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Height of the rectangle, in pixels.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-cropcap; <structfield>type</structfield> is
-invalid.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml
deleted file mode 100644
index f14a3bb1afaa..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-chip-info.xml
+++ /dev/null
@@ -1,207 +0,0 @@
-<refentry id="vidioc-dbg-g-chip-info">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_DBG_G_CHIP_INFO</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_DBG_G_CHIP_INFO</refname>
- <refpurpose>Identify the chips on a TV card</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_dbg_chip_info
-*<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_DBG_G_CHIP_INFO</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <note>
- <title>Experimental</title>
-
- <para>This is an <link
-linkend="experimental">experimental</link> interface and may change in
-the future.</para>
- </note>
-
- <para>For driver debugging purposes this ioctl allows test
-applications to query the driver about the chips present on the TV
-card. Regular applications must not use it. When you found a chip
-specific bug, please contact the linux-media mailing list (&v4l-ml;)
-so it can be fixed.</para>
-
- <para>Additionally the Linux kernel must be compiled with the
-<constant>CONFIG_VIDEO_ADV_DEBUG</constant> option to enable this ioctl.</para>
-
- <para>To query the driver applications must initialize the
-<structfield>match.type</structfield> and
-<structfield>match.addr</structfield> or <structfield>match.name</structfield>
-fields of a &v4l2-dbg-chip-info;
-and call <constant>VIDIOC_DBG_G_CHIP_INFO</constant> with a pointer to
-this structure. On success the driver stores information about the
-selected chip in the <structfield>name</structfield> and
-<structfield>flags</structfield> fields.</para>
-
- <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
-<structfield>match.addr</structfield> selects the nth bridge 'chip'
-on the TV card. You can enumerate all chips by starting at zero and
-incrementing <structfield>match.addr</structfield> by one until
-<constant>VIDIOC_DBG_G_CHIP_INFO</constant> fails with an &EINVAL;.
-The number zero always selects the bridge chip itself, &eg; the chip
-connected to the PCI or USB bus. Non-zero numbers identify specific
-parts of the bridge chip such as an AC97 register block.</para>
-
- <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_SUBDEV</constant>,
-<structfield>match.addr</structfield> selects the nth sub-device. This
-allows you to enumerate over all sub-devices.</para>
-
- <para>On success, the <structfield>name</structfield> field will
-contain a chip name and the <structfield>flags</structfield> field will
-contain <constant>V4L2_CHIP_FL_READABLE</constant> if the driver supports
-reading registers from the device or <constant>V4L2_CHIP_FL_WRITABLE</constant>
-if the driver supports writing registers to the device.</para>
-
- <para>We recommended the <application>v4l2-dbg</application>
-utility over calling this ioctl directly. It is available from the
-LinuxTV v4l-dvb repository; see <ulink
-url="https://linuxtv.org/repo/">https://linuxtv.org/repo/</ulink> for
-access instructions.</para>
-
- <!-- Note for convenience vidioc-dbg-g-register.sgml
- contains a duplicate of this table. -->
- <table pgwide="1" frame="none" id="name-v4l2-dbg-match">
- <title>struct <structname>v4l2_dbg_match</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>See <xref linkend="name-chip-match-types" /> for a list of
-possible types.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>addr</structfield></entry>
- <entry>Match a chip by this number, interpreted according
-to the <structfield>type</structfield> field.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>char</entry>
- <entry><structfield>name[32]</structfield></entry>
- <entry>Match a chip by this name, interpreted according
-to the <structfield>type</structfield> field. Currently unused.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-dbg-chip-info">
- <title>struct <structname>v4l2_dbg_chip_info</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>struct v4l2_dbg_match</entry>
- <entry><structfield>match</structfield></entry>
- <entry>How to match the chip, see <xref linkend="name-v4l2-dbg-match" />.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>name[32]</structfield></entry>
- <entry>The name of the chip.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Set by the driver. If <constant>V4L2_CHIP_FL_READABLE</constant>
-is set, then the driver supports reading registers from the device. If
-<constant>V4L2_CHIP_FL_WRITABLE</constant> is set, then it supports writing registers.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[8]</structfield></entry>
- <entry>Reserved fields, both application and driver must set these to 0.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- Note for convenience vidioc-dbg-g-register.sgml
- contains a duplicate of this table. -->
- <table pgwide="1" frame="none" id="name-chip-match-types">
- <title>Chip Match Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
- <entry>0</entry>
- <entry>Match the nth chip on the card, zero for the
- bridge chip. Does not match sub-devices.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
- <entry>4</entry>
- <entry>Match the nth sub-device.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>match_type</structfield> is invalid or
-no device could be matched.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml b/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
deleted file mode 100644
index 5877f68a5820..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-dbg-g-register.xml
+++ /dev/null
@@ -1,227 +0,0 @@
-<refentry id="vidioc-dbg-g-register">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_DBG_G_REGISTER, VIDIOC_DBG_S_REGISTER</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_DBG_G_REGISTER</refname>
- <refname>VIDIOC_DBG_S_REGISTER</refname>
- <refpurpose>Read or write hardware registers</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_dbg_register *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_dbg_register
-*<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_DBG_G_REGISTER, VIDIOC_DBG_S_REGISTER</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <note>
- <title>Experimental</title>
-
- <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
- </note>
-
- <para>For driver debugging purposes these ioctls allow test
-applications to access hardware registers directly. Regular
-applications must not use them.</para>
-
- <para>Since writing or even reading registers can jeopardize the
-system security, its stability and damage the hardware, both ioctls
-require superuser privileges. Additionally the Linux kernel must be
-compiled with the <constant>CONFIG_VIDEO_ADV_DEBUG</constant> option
-to enable these ioctls.</para>
-
- <para>To write a register applications must initialize all fields
-of a &v4l2-dbg-register; except for <structfield>size</structfield> and call
-<constant>VIDIOC_DBG_S_REGISTER</constant> with a pointer to this
-structure. The <structfield>match.type</structfield> and
-<structfield>match.addr</structfield> or <structfield>match.name</structfield>
-fields select a chip on the TV
-card, the <structfield>reg</structfield> field specifies a register
-number and the <structfield>val</structfield> field the value to be
-written into the register.</para>
-
- <para>To read a register applications must initialize the
-<structfield>match.type</structfield>,
-<structfield>match.addr</structfield> or <structfield>match.name</structfield> and
-<structfield>reg</structfield> fields, and call
-<constant>VIDIOC_DBG_G_REGISTER</constant> with a pointer to this
-structure. On success the driver stores the register value in the
-<structfield>val</structfield> field and the size (in bytes) of the
-value in <structfield>size</structfield>.</para>
-
- <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_BRIDGE</constant>,
-<structfield>match.addr</structfield> selects the nth non-sub-device chip
-on the TV card. The number zero always selects the host chip, &eg; the
-chip connected to the PCI or USB bus. You can find out which chips are
-present with the &VIDIOC-DBG-G-CHIP-INFO; ioctl.</para>
-
- <para>When <structfield>match.type</structfield> is
-<constant>V4L2_CHIP_MATCH_SUBDEV</constant>,
-<structfield>match.addr</structfield> selects the nth sub-device.</para>
-
- <para>These ioctls are optional, not all drivers may support them.
-However when a driver supports these ioctls it must also support
-&VIDIOC-DBG-G-CHIP-INFO;. Conversely it may support
-<constant>VIDIOC_DBG_G_CHIP_INFO</constant> but not these ioctls.</para>
-
- <para><constant>VIDIOC_DBG_G_REGISTER</constant> and
-<constant>VIDIOC_DBG_S_REGISTER</constant> were introduced in Linux
-2.6.21, but their API was changed to the one described here in kernel 2.6.29.</para>
-
- <para>We recommended the <application>v4l2-dbg</application>
-utility over calling these ioctls directly. It is available from the
-LinuxTV v4l-dvb repository; see <ulink
-url="https://linuxtv.org/repo/">https://linuxtv.org/repo/</ulink> for
-access instructions.</para>
-
- <!-- Note for convenience vidioc-dbg-g-chip-info.sgml
- contains a duplicate of this table. -->
- <table pgwide="1" frame="none" id="v4l2-dbg-match">
- <title>struct <structname>v4l2_dbg_match</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>See <xref linkend="chip-match-types" /> for a list of
-possible types.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>addr</structfield></entry>
- <entry>Match a chip by this number, interpreted according
-to the <structfield>type</structfield> field.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>char</entry>
- <entry><structfield>name[32]</structfield></entry>
- <entry>Match a chip by this name, interpreted according
-to the <structfield>type</structfield> field. Currently unused.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
-
- <table pgwide="1" frame="none" id="v4l2-dbg-register">
- <title>struct <structname>v4l2_dbg_register</structname></title>
- <tgroup cols="4">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c4" />
- <tbody valign="top">
- <row>
- <entry>struct v4l2_dbg_match</entry>
- <entry><structfield>match</structfield></entry>
- <entry>How to match the chip, see <xref linkend="v4l2-dbg-match" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>size</structfield></entry>
- <entry>The register size in bytes.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>reg</structfield></entry>
- <entry>A register number.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>val</structfield></entry>
- <entry>The value read from, or to be written into the
-register.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- Note for convenience vidioc-dbg-g-chip-info.sgml
- contains a duplicate of this table. -->
- <table pgwide="1" frame="none" id="chip-match-types">
- <title>Chip Match Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CHIP_MATCH_BRIDGE</constant></entry>
- <entry>0</entry>
- <entry>Match the nth chip on the card, zero for the
- bridge chip. Does not match sub-devices.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CHIP_MATCH_SUBDEV</constant></entry>
- <entry>4</entry>
- <entry>Match the nth sub-device.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EPERM</errorcode></term>
- <listitem>
- <para>Insufficient permissions. Root privileges are required
-to execute these ioctls.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml b/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml
deleted file mode 100644
index 73eb5cfe698a..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml
+++ /dev/null
@@ -1,259 +0,0 @@
-<refentry id="vidioc-decoder-cmd">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_DECODER_CMD, VIDIOC_TRY_DECODER_CMD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_DECODER_CMD</refname>
- <refname>VIDIOC_TRY_DECODER_CMD</refname>
- <refpurpose>Execute an decoder command</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_decoder_cmd *<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_DECODER_CMD, VIDIOC_TRY_DECODER_CMD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls control an audio/video (usually MPEG-) decoder.
-<constant>VIDIOC_DECODER_CMD</constant> sends a command to the
-decoder, <constant>VIDIOC_TRY_DECODER_CMD</constant> can be used to
-try a command without actually executing it. To send a command applications
-must initialize all fields of a &v4l2-decoder-cmd; and call
-<constant>VIDIOC_DECODER_CMD</constant> or <constant>VIDIOC_TRY_DECODER_CMD</constant>
-with a pointer to this structure.</para>
-
- <para>The <structfield>cmd</structfield> field must contain the
-command code. Some commands use the <structfield>flags</structfield> field for
-additional information.
-</para>
-
- <para>A <function>write</function>() or &VIDIOC-STREAMON; call sends an implicit
-START command to the decoder if it has not been started yet.
-</para>
-
- <para>A <function>close</function>() or &VIDIOC-STREAMOFF; call of a streaming
-file descriptor sends an implicit immediate STOP command to the decoder, and all
-buffered data is discarded.</para>
-
- <para>These ioctls are optional, not all drivers may support
-them. They were introduced in Linux 3.3.</para>
-
- <table pgwide="1" frame="none" id="v4l2-decoder-cmd">
- <title>struct <structname>v4l2_decoder_cmd</structname></title>
- <tgroup cols="5">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>cmd</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>The decoder command, see <xref linkend="decoder-cmds" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry></entry>
- <entry>Flags to go with the command. If no flags are defined for
-this command, drivers and applications must set this field to zero.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct</entry>
- <entry><structfield>start</structfield></entry>
- <entry></entry>
- <entry>Structure containing additional data for the
-<constant>V4L2_DEC_CMD_START</constant> command.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__s32</entry>
- <entry><structfield>speed</structfield></entry>
- <entry>Playback speed and direction. The playback speed is defined as
-<structfield>speed</structfield>/1000 of the normal speed. So 1000 is normal playback.
-Negative numbers denote reverse playback, so -1000 does reverse playback at normal
-speed. Speeds -1, 0 and 1 have special meanings: speed 0 is shorthand for 1000
-(normal playback). A speed of 1 steps just one frame forward, a speed of -1 steps
-just one frame back.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>format</structfield></entry>
- <entry>Format restrictions. This field is set by the driver, not the
-application. Possible values are <constant>V4L2_DEC_START_FMT_NONE</constant> if
-there are no format restrictions or <constant>V4L2_DEC_START_FMT_GOP</constant>
-if the decoder operates on full GOPs (<wordasword>Group Of Pictures</wordasword>).
-This is usually the case for reverse playback: the decoder needs full GOPs, which
-it can then play in reverse order. So to implement reverse playback the application
-must feed the decoder the last GOP in the video file, then the GOP before that, etc. etc.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct</entry>
- <entry><structfield>stop</structfield></entry>
- <entry></entry>
- <entry>Structure containing additional data for the
-<constant>V4L2_DEC_CMD_STOP</constant> command.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__u64</entry>
- <entry><structfield>pts</structfield></entry>
- <entry>Stop playback at this <structfield>pts</structfield> or immediately
-if the playback is already past that timestamp. Leave to 0 if you want to stop after the
-last frame was decoded.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>struct</entry>
- <entry><structfield>raw</structfield></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>data</structfield>[16]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="decoder-cmds">
- <title>Decoder Commands</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_DEC_CMD_START</constant></entry>
- <entry>0</entry>
- <entry>Start the decoder. When the decoder is already
-running or paused, this command will just change the playback speed.
-That means that calling <constant>V4L2_DEC_CMD_START</constant> when
-the decoder was paused will <emphasis>not</emphasis> resume the decoder.
-You have to explicitly call <constant>V4L2_DEC_CMD_RESUME</constant> for that.
-This command has one flag:
-<constant>V4L2_DEC_CMD_START_MUTE_AUDIO</constant>. If set, then audio will
-be muted when playing back at a non-standard speed.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_DEC_CMD_STOP</constant></entry>
- <entry>1</entry>
- <entry>Stop the decoder. When the decoder is already stopped,
-this command does nothing. This command has two flags:
-if <constant>V4L2_DEC_CMD_STOP_TO_BLACK</constant> is set, then the decoder will
-set the picture to black after it stopped decoding. Otherwise the last image will
-repeat. mem2mem decoders will stop producing new frames altogether. They will send
-a <constant>V4L2_EVENT_EOS</constant> event when the last frame has been decoded
-and all frames are ready to be dequeued and will set the
-<constant>V4L2_BUF_FLAG_LAST</constant> buffer flag on the last buffer of the
-capture queue to indicate there will be no new buffers produced to dequeue. This
-buffer may be empty, indicated by the driver setting the
-<structfield>bytesused</structfield> field to 0. Once the
-<constant>V4L2_BUF_FLAG_LAST</constant> flag was set, the
-<link linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl will not block anymore,
-but return an &EPIPE;.
-If <constant>V4L2_DEC_CMD_STOP_IMMEDIATELY</constant> is set, then the decoder
-stops immediately (ignoring the <structfield>pts</structfield> value), otherwise it
-will keep decoding until timestamp >= pts or until the last of the pending data from
-its internal buffers was decoded.
-</entry>
- </row>
- <row>
- <entry><constant>V4L2_DEC_CMD_PAUSE</constant></entry>
- <entry>2</entry>
- <entry>Pause the decoder. When the decoder has not been
-started yet, the driver will return an &EPERM;. When the decoder is
-already paused, this command does nothing. This command has one flag:
-if <constant>V4L2_DEC_CMD_PAUSE_TO_BLACK</constant> is set, then set the
-decoder output to black when paused.
-</entry>
- </row>
- <row>
- <entry><constant>V4L2_DEC_CMD_RESUME</constant></entry>
- <entry>3</entry>
- <entry>Resume decoding after a PAUSE command. When the
-decoder has not been started yet, the driver will return an &EPERM;.
-When the decoder is already running, this command does nothing. No
-flags are defined for this command.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>cmd</structfield> field is invalid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EPERM</errorcode></term>
- <listitem>
- <para>The application sent a PAUSE or RESUME command when
-the decoder was not running.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
deleted file mode 100644
index c9c3c7713832..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
+++ /dev/null
@@ -1,471 +0,0 @@
-<refentry id="vidioc-dqevent">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_DQEVENT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_DQEVENT</refname>
- <refpurpose>Dequeue 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
-*<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_DQEVENT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Dequeue an event from a video device. No input is required
- for this ioctl. All the fields of the &v4l2-event; structure are
- filled by the driver. The file handle will also receive exceptions
- which the application may get by e.g. using the select system
- call.</para>
-
- <table frame="none" pgwide="1" id="v4l2-event">
- <title>struct <structname>v4l2_event</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>Type of the event, see <xref linkend="event-type" />.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield>u</structfield></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-event-vsync;</entry>
- <entry><structfield>vsync</structfield></entry>
- <entry>Event data for event <constant>V4L2_EVENT_VSYNC</constant>.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-event-ctrl;</entry>
- <entry><structfield>ctrl</structfield></entry>
- <entry>Event data for event <constant>V4L2_EVENT_CTRL</constant>.
- </entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-event-frame-sync;</entry>
- <entry><structfield>frame_sync</structfield></entry>
- <entry>Event data for event
- <constant>V4L2_EVENT_FRAME_SYNC</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-event-motion-det;</entry>
- <entry><structfield>motion_det</structfield></entry>
- <entry>Event data for event V4L2_EVENT_MOTION_DET.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-event-src-change;</entry>
- <entry><structfield>src_change</structfield></entry>
- <entry>Event data for event V4L2_EVENT_SOURCE_CHANGE.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8</entry>
- <entry><structfield>data</structfield>[64]</entry>
- <entry>Event data. Defined by the event type. The union
- should be used to define easily accessible type for
- events.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pending</structfield></entry>
- <entry></entry>
- <entry>Number of pending events excluding this one.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>sequence</structfield></entry>
- <entry></entry>
- <entry>Event sequence number. The sequence number is
- incremented for every subscribed event that takes place.
- If sequence numbers are not contiguous it means that
- events have been lost.
- </entry>
- </row>
- <row>
- <entry>struct timespec</entry>
- <entry><structfield>timestamp</structfield></entry>
- <entry></entry>
- <entry>Event timestamp. The timestamp has been taken from the
- <constant>CLOCK_MONOTONIC</constant> clock. To access the
- same clock outside V4L2, use <function>clock_gettime(2)</function>.
- </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>[8]</entry>
- <entry></entry>
- <entry>Reserved for future extensions. Drivers 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_FRAME_SYNC</constant></entry>
- <entry>4</entry>
- <entry>
- <para>Triggered immediately when the reception of a
- frame has begun. This event has a
- &v4l2-event-frame-sync; associated with it.</para>
-
- <para>If the hardware needs to be stopped in the case of a
- buffer underrun it might not be able to generate this event.
- In such cases the <structfield>frame_sequence</structfield>
- field in &v4l2-event-frame-sync; will not be incremented. This
- causes two consecutive frame sequence numbers to have n times
- frame interval in between them.</para>
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
- <entry>5</entry>
- <entry>
- <para>This event is triggered when a source parameter change is
- detected during runtime by the video device. It can be a
- runtime resolution change triggered by a video decoder or the
- format change happening on an input connector.
- This event requires that the <structfield>id</structfield>
- matches the input index (when used with a video device node)
- or the pad index (when used with a subdevice node) from which
- you want to receive events.</para>
-
- <para>This event has a &v4l2-event-src-change; associated
- with it. The <structfield>changes</structfield> bitfield denotes
- what has changed for the subscribed pad. If multiple events
- occurred before application could dequeue them, then the changes
- will have the ORed value of all the events generated.</para>
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
- <entry>6</entry>
- <entry>
- <para>Triggered whenever the motion detection state for one or more of the regions
- changes. This event has a &v4l2-event-motion-det; associated with it.</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 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="ctrl-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 frame="none" pgwide="1" id="v4l2-event-frame-sync">
- <title>struct <structname>v4l2_event_frame_sync</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>frame_sequence</structfield></entry>
- <entry>
- The sequence number of the frame being received.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-event-src-change">
- <title>struct <structname>v4l2_event_src_change</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>changes</structfield></entry>
- <entry>
- A bitmask that tells what has changed. See <xref linkend="src-changes-flags" />.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="v4l2-event-motion-det">
- <title>struct <structname>v4l2_event_motion_det</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>
- Currently only one flag is available: if <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant>
- is set, then the <structfield>frame_sequence</structfield> field is valid,
- otherwise that field should be ignored.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>frame_sequence</structfield></entry>
- <entry>
- The sequence number of the frame being received. Only valid if the
- <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant> flag was set.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>region_mask</structfield></entry>
- <entry>
- The bitmask of the regions that reported motion. There is at least one
- region. If this field is 0, then no motion was detected at all.
- If there is no <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> control
- (see <xref linkend="detect-controls" />) to assign a different region
- to each cell in the motion detection grid, then that all cells
- are automatically assigned to the default region 0.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="ctrl-changes-flags">
- <title>Control 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 cases: Volatile controls do no generate this event;
- If a control has the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant>
- flag set, then this event is sent as well, regardless its value.</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>
- <row>
- <entry><constant>V4L2_EVENT_CTRL_CH_RANGE</constant></entry>
- <entry>0x0004</entry>
- <entry>This control event was triggered because the minimum,
- maximum, step or the default value of the control changed.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="src-changes-flags">
- <title>Source Changes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_EVENT_SRC_CH_RESOLUTION</constant></entry>
- <entry>0x0001</entry>
- <entry>This event gets triggered when a resolution change is
- detected at an input. This can come from an input connector or
- from a video decoder.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml b/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
deleted file mode 100644
index ca9ffce9b4c1..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-dv-timings-cap.xml
+++ /dev/null
@@ -1,210 +0,0 @@
-<refentry id="vidioc-dv-timings-cap">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_DV_TIMINGS_CAP</refname>
- <refname>VIDIOC_SUBDEV_DV_TIMINGS_CAP</refname>
- <refpurpose>The capabilities of the Digital Video receiver/transmitter</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_dv_timings_cap *<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_DV_TIMINGS_CAP, VIDIOC_SUBDEV_DV_TIMINGS_CAP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the capabilities of the DV receiver/transmitter applications initialize the
-<structfield>pad</structfield> field to 0, zero the reserved array of &v4l2-dv-timings-cap;
-and call the <constant>VIDIOC_DV_TIMINGS_CAP</constant> ioctl on a video node
-and the driver will fill in the structure. Note that drivers may return
-different values after switching the video input or output.</para>
-
- <para>When implemented by the driver DV capabilities of subdevices can be
-queried by calling the <constant>VIDIOC_SUBDEV_DV_TIMINGS_CAP</constant> ioctl
-directly on a subdevice node. The capabilities are specific to inputs (for DV
-receivers) or outputs (for DV transmitters), applications must specify the
-desired pad number in the &v4l2-dv-timings-cap; <structfield>pad</structfield>
-field and zero the <structfield>reserved</structfield> array. Attempts to query
-capabilities on a pad that doesn't support them will return an &EINVAL;.</para>
-
- <table pgwide="1" frame="none" id="v4l2-bt-timings-cap">
- <title>struct <structname>v4l2_bt_timings_cap</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_width</structfield></entry>
- <entry>Minimum width of the active video in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_width</structfield></entry>
- <entry>Maximum width of the active video in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_height</structfield></entry>
- <entry>Minimum height of the active video in lines.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_height</structfield></entry>
- <entry>Maximum height of the active video in lines.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>min_pixelclock</structfield></entry>
- <entry>Minimum pixelclock frequency in Hz.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>max_pixelclock</structfield></entry>
- <entry>Maximum pixelclock frequency in Hz.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>standards</structfield></entry>
- <entry>The video standard(s) supported by the hardware.
- See <xref linkend="dv-bt-standards"/> for a list of standards.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capabilities</structfield></entry>
- <entry>Several flags giving more information about the capabilities.
- See <xref linkend="dv-bt-cap-capabilities"/> for a description of the flags.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[16]</entry>
- <entry>Reserved for future extensions. Drivers must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-dv-timings-cap">
- <title>struct <structname>v4l2_dv_timings_cap</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of DV timings as listed in <xref linkend="dv-timing-types"/>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API. This field
- is only used when operating on a subdevice node. When operating on a
- video node applications must set this field to zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set the array to zero.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield></structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-bt-timings-cap;</entry>
- <entry><structfield>bt</structfield></entry>
- <entry>BT.656/1120 timings capabilities of the hardware.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>raw_data</structfield>[32]</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="dv-bt-cap-capabilities">
- <title>DV BT Timing capabilities</title>
- <tgroup cols="2">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>Flag</entry>
- <entry>Description</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_CAP_INTERLACED</entry>
- <entry>Interlaced formats are supported.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_CAP_PROGRESSIVE</entry>
- <entry>Progressive formats are supported.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_CAP_REDUCED_BLANKING</entry>
- <entry>CVT/GTF specific: the timings can make use of reduced blanking (CVT)
-or the 'Secondary GTF' curve (GTF).
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_CAP_CUSTOM</entry>
- <entry>Can support non-standard timings, i.e. timings not belonging to the
-standards set in the <structfield>standards</structfield> field.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml b/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
deleted file mode 100644
index 70a4a08e9404..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
+++ /dev/null
@@ -1,197 +0,0 @@
-<refentry id="vidioc-encoder-cmd">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENCODER_CMD, VIDIOC_TRY_ENCODER_CMD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENCODER_CMD</refname>
- <refname>VIDIOC_TRY_ENCODER_CMD</refname>
- <refpurpose>Execute an encoder command</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_encoder_cmd *<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_ENCODER_CMD, VIDIOC_TRY_ENCODER_CMD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls control an audio/video (usually MPEG-) encoder.
-<constant>VIDIOC_ENCODER_CMD</constant> sends a command to the
-encoder, <constant>VIDIOC_TRY_ENCODER_CMD</constant> can be used to
-try a command without actually executing it.</para>
-
- <para>To send a command applications must initialize all fields of a
- &v4l2-encoder-cmd; and call
- <constant>VIDIOC_ENCODER_CMD</constant> or
- <constant>VIDIOC_TRY_ENCODER_CMD</constant> with a pointer to this
- structure.</para>
-
- <para>The <structfield>cmd</structfield> field must contain the
-command code. The <structfield>flags</structfield> field is currently
-only used by the STOP command and contains one bit: If the
-<constant>V4L2_ENC_CMD_STOP_AT_GOP_END</constant> flag is set,
-encoding will continue until the end of the current <wordasword>Group
-Of Pictures</wordasword>, otherwise it will stop immediately.</para>
-
- <para>A <function>read</function>() or &VIDIOC-STREAMON; call sends an implicit
-START command to the encoder if it has not been started yet. After a STOP command,
-<function>read</function>() calls will read the remaining data
-buffered by the driver. When the buffer is empty,
-<function>read</function>() will return zero and the next
-<function>read</function>() call will restart the encoder.</para>
-
- <para>A <function>close</function>() or &VIDIOC-STREAMOFF; call of a streaming
-file descriptor sends an implicit immediate STOP to the encoder, and all buffered
-data is discarded.</para>
-
- <para>These ioctls are optional, not all drivers may support
-them. They were introduced in Linux 2.6.21.</para>
-
- <table pgwide="1" frame="none" id="v4l2-encoder-cmd">
- <title>struct <structname>v4l2_encoder_cmd</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>cmd</structfield></entry>
- <entry>The encoder command, see <xref linkend="encoder-cmds" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags to go with the command, see <xref
- linkend="encoder-flags" />. If no flags are defined for
-this command, drivers and applications must set this field to
-zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>data</structfield>[8]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="encoder-cmds">
- <title>Encoder Commands</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_ENC_CMD_START</constant></entry>
- <entry>0</entry>
- <entry>Start the encoder. When the encoder is already
-running or paused, this command does nothing. No flags are defined for
-this command.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_CMD_STOP</constant></entry>
- <entry>1</entry>
- <entry>Stop the encoder. When the
-<constant>V4L2_ENC_CMD_STOP_AT_GOP_END</constant> flag is set,
-encoding will continue until the end of the current <wordasword>Group
-Of Pictures</wordasword>, otherwise encoding will stop immediately.
-When the encoder is already stopped, this command does
-nothing. mem2mem encoders will send a <constant>V4L2_EVENT_EOS</constant> event
-when the last frame has been encoded and all frames are ready to be dequeued and
-will set the <constant>V4L2_BUF_FLAG_LAST</constant> buffer flag on the last
-buffer of the capture queue to indicate there will be no new buffers produced to
-dequeue. This buffer may be empty, indicated by the driver setting the
-<structfield>bytesused</structfield> field to 0. Once the
-<constant>V4L2_BUF_FLAG_LAST</constant> flag was set, the
-<link linkend="vidioc-qbuf">VIDIOC_DQBUF</link> ioctl will not block anymore,
-but return an &EPIPE;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_CMD_PAUSE</constant></entry>
- <entry>2</entry>
- <entry>Pause the encoder. When the encoder has not been
-started yet, the driver will return an &EPERM;. When the encoder is
-already paused, this command does nothing. No flags are defined for
-this command.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_CMD_RESUME</constant></entry>
- <entry>3</entry>
- <entry>Resume encoding after a PAUSE command. When the
-encoder has not been started yet, the driver will return an &EPERM;.
-When the encoder is already running, this command does nothing. No
-flags are defined for this command.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="encoder-flags">
- <title>Encoder Command Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_ENC_CMD_STOP_AT_GOP_END</constant></entry>
- <entry>0x0001</entry>
- <entry>Stop encoding at the end of the current <wordasword>Group Of
-Pictures</wordasword>, rather than immediately.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>cmd</structfield> field is invalid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EPERM</errorcode></term>
- <listitem>
- <para>The application sent a PAUSE or RESUME command when
-the encoder was not running.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
deleted file mode 100644
index 9b3d42018b69..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<refentry id="vidioc-enum-dv-timings">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUM_DV_TIMINGS</refname>
- <refname>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</refname>
- <refpurpose>Enumerate supported Digital Video timings</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_enum_dv_timings *<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_ENUM_DV_TIMINGS, VIDIOC_SUBDEV_ENUM_DV_TIMINGS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>While some DV receivers or transmitters support a wide range of timings, others
-support only a limited number of timings. With this ioctl applications can enumerate a list
-of known supported timings. Call &VIDIOC-DV-TIMINGS-CAP; to check if it also supports other
-standards or even custom timings that are not in this list.</para>
-
- <para>To query the available timings, applications initialize the
-<structfield>index</structfield> field, set the <structfield>pad</structfield> field to 0,
-zero the reserved array of &v4l2-enum-dv-timings; and call the
-<constant>VIDIOC_ENUM_DV_TIMINGS</constant> ioctl on a video node with a
-pointer to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all supported DV timings,
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>. Note that drivers may enumerate a
-different set of DV timings after switching the video input or
-output.</para>
-
- <para>When implemented by the driver DV timings of subdevices can be queried
-by calling the <constant>VIDIOC_SUBDEV_ENUM_DV_TIMINGS</constant> ioctl directly
-on a subdevice node. The DV timings are specific to inputs (for DV receivers) or
-outputs (for DV transmitters), applications must specify the desired pad number
-in the &v4l2-enum-dv-timings; <structfield>pad</structfield> field. Attempts to
-enumerate timings on a pad that doesn't support them will return an &EINVAL;.</para>
-
- <table pgwide="1" frame="none" id="v4l2-enum-dv-timings">
- <title>struct <structname>v4l2_enum_dv_timings</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the DV timings, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API. This field
- is only used when operating on a subdevice node. When operating on a
- video node applications must set this field to zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers and applications must
- set the array to zero.</entry>
- </row>
- <row>
- <entry>&v4l2-dv-timings;</entry>
- <entry><structfield>timings</structfield></entry>
- <entry>The timings.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-enum-dv-timings; <structfield>index</structfield>
-is out of bounds or the <structfield>pad</structfield> number is invalid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Digital video presets are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml
deleted file mode 100644
index f8dfeed34fca..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<refentry id="vidioc-enum-fmt">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUM_FMT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUM_FMT</refname>
- <refpurpose>Enumerate image formats</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_fmtdesc
-*<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_ENUM_FMT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To enumerate image formats applications initialize the
-<structfield>type</structfield> and <structfield>index</structfield>
-field of &v4l2-fmtdesc; and call the
-<constant>VIDIOC_ENUM_FMT</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
-&EINVAL;. All formats are enumerable by beginning at index zero and
-incrementing by one until <errorcode>EINVAL</errorcode> is
-returned.</para>
-
- <para>Note that after switching input or output the list of enumerated image
-formats may be different.</para>
-
- <table pgwide="1" frame="none" id="v4l2-fmtdesc">
- <title>struct <structname>v4l2_fmtdesc</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the format in the enumeration, set by
-the application. This is in no way related to the <structfield>
-pixelformat</structfield> field.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the data stream, set by the application.
-Only these types are valid here:
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>See <xref linkend="fmtdesc-flags" /></entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>description</structfield>[32]</entry>
- <entry>Description of the format, a NUL-terminated ASCII
-string. This information is intended for the user, for example: "YUV
-4:2:2".</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixelformat</structfield></entry>
- <entry>The image format identifier. This is a
-four character code as computed by the v4l2_fourcc()
-macro:</entry>
- </row>
- <row>
- <entry spanname="hspan"><para><programlisting id="v4l2-fourcc">
-#define v4l2_fourcc(a,b,c,d) (((__u32)(a)&lt;&lt;0)|((__u32)(b)&lt;&lt;8)|((__u32)(c)&lt;&lt;16)|((__u32)(d)&lt;&lt;24))
-</programlisting></para><para>Several image formats are already
-defined by this specification in <xref linkend="pixfmt" />. Note these
-codes are not the same as those used in the Windows world.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="fmtdesc-flags">
- <title>Image Format Description Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FMT_FLAG_COMPRESSED</constant></entry>
- <entry>0x0001</entry>
- <entry>This is a compressed format.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FMT_FLAG_EMULATED</constant></entry>
- <entry>0x0002</entry>
- <entry>This format is not native to the device but emulated
-through software (usually libv4l2), where possible try to use a native format
-instead for better performance.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-fmtdesc; <structfield>type</structfield>
-is not supported or the <structfield>index</structfield> is out of
-bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-frameintervals.xml b/Documentation/DocBook/media/v4l/vidioc-enum-frameintervals.xml
deleted file mode 100644
index 7c839ab0afbb..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-frameintervals.xml
+++ /dev/null
@@ -1,260 +0,0 @@
-<refentry id="vidioc-enum-frameintervals">
-
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUM_FRAMEINTERVALS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUM_FRAMEINTERVALS</refname>
- <refpurpose>Enumerate frame intervals</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_frmivalenum *<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_ENUM_FRAMEINTERVALS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>Pointer to a &v4l2-frmivalenum; structure that
-contains a pixel format and size and receives a frame interval.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl allows applications to enumerate all frame
-intervals that the device supports for the given pixel format and
-frame size.</para>
- <para>The supported pixel formats and frame sizes can be obtained
-by using the &VIDIOC-ENUM-FMT; and &VIDIOC-ENUM-FRAMESIZES;
-functions.</para>
- <para>The return value and the content of the
-<structfield>v4l2_frmivalenum.type</structfield> field depend on the
-type of frame intervals the device supports. Here are the semantics of
-the function for the different cases:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Discrete:</emphasis> The function
-returns success if the given index value (zero-based) is valid. The
-application should increase the index by one for each call until
-<constant>EINVAL</constant> is returned. The `v4l2_frmivalenum.type`
-field is set to `V4L2_FRMIVAL_TYPE_DISCRETE` by the driver. Of the
-union only the `discrete` member is valid.</para>
- </listitem>
- <listitem>
- <para><emphasis role="bold">Step-wise:</emphasis> The function
-returns success if the given index value is zero and
-<constant>EINVAL</constant> for any other index value. The
-<structfield>v4l2_frmivalenum.type</structfield> field is set to
-<constant>V4L2_FRMIVAL_TYPE_STEPWISE</constant> by the driver. Of the
-union only the <structfield>stepwise</structfield> member is
-valid.</para>
- </listitem>
- <listitem>
- <para><emphasis role="bold">Continuous:</emphasis> This is a
-special case of the step-wise type above. The function returns success
-if the given index value is zero and <constant>EINVAL</constant> for
-any other index value. The
-<structfield>v4l2_frmivalenum.type</structfield> field is set to
-<constant>V4L2_FRMIVAL_TYPE_CONTINUOUS</constant> by the driver. Of
-the union only the <structfield>stepwise</structfield> member is valid
-and the <structfield>step</structfield> value is set to 1.</para>
- </listitem>
- </itemizedlist>
-
- <para>When the application calls the function with index zero, it
-must check the <structfield>type</structfield> field to determine the
-type of frame interval enumeration the device supports. Only for the
-<constant>V4L2_FRMIVAL_TYPE_DISCRETE</constant> type does it make
-sense to increase the index value to receive more frame
-intervals.</para>
- <para>Note that the order in which the frame intervals are
-returned has no special meaning. In particular does it not say
-anything about potential default frame intervals.</para>
- <para>Applications can assume that the enumeration data does not
-change without any interaction from the application itself. This means
-that the enumeration data is consistent if the application does not
-perform any other ioctl calls while it runs the frame interval
-enumeration.</para>
- </refsect1>
-
- <refsect1>
- <title>Notes</title>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Frame intervals and frame
-rates:</emphasis> The V4L2 API uses frame intervals instead of frame
-rates. Given the frame interval the frame rate can be computed as
-follows:<screen>frame_rate = 1 / frame_interval</screen></para>
- </listitem>
- </itemizedlist>
-
- </refsect1>
-
- <refsect1>
- <title>Structs</title>
-
- <para>In the structs below, <emphasis>IN</emphasis> denotes a
-value that has to be filled in by the application,
-<emphasis>OUT</emphasis> denotes values that the driver fills in. The
-application should zero out all members except for the
-<emphasis>IN</emphasis> fields.</para>
-
- <table pgwide="1" frame="none" id="v4l2-frmival-stepwise">
- <title>struct <structname>v4l2_frmival_stepwise</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>min</structfield></entry>
- <entry>Minimum frame interval [s].</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>max</structfield></entry>
- <entry>Maximum frame interval [s].</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>step</structfield></entry>
- <entry>Frame interval step size [s].</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-frmivalenum">
- <title>struct <structname>v4l2_frmivalenum</structname></title>
- <tgroup cols="4">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry></entry>
- <entry>IN: Index of the given frame interval in the
-enumeration.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixel_format</structfield></entry>
- <entry></entry>
- <entry>IN: Pixel format for which the frame intervals are
-enumerated.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry></entry>
- <entry>IN: Frame width for which the frame intervals are
-enumerated.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry></entry>
- <entry>IN: Frame height for which the frame intervals are
-enumerated.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>OUT: Frame interval type the device supports.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry></entry>
- <entry></entry>
- <entry>OUT: Frame interval with the given index.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>discrete</structfield></entry>
- <entry>Frame interval [s].</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-frmival-stepwise;</entry>
- <entry><structfield>stepwise</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[2]</structfield></entry>
- <entry></entry>
- <entry>Reserved space for future use. Must be zeroed by drivers and
- applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- <title>Enums</title>
-
- <table pgwide="1" frame="none" id="v4l2-frmivaltypes">
- <title>enum <structname>v4l2_frmivaltypes</structname></title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FRMIVAL_TYPE_DISCRETE</constant></entry>
- <entry>1</entry>
- <entry>Discrete frame interval.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FRMIVAL_TYPE_CONTINUOUS</constant></entry>
- <entry>2</entry>
- <entry>Continuous frame interval.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FRMIVAL_TYPE_STEPWISE</constant></entry>
- <entry>3</entry>
- <entry>Step-wise defined frame interval.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml b/Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml
deleted file mode 100644
index 9ed68ac8f474..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml
+++ /dev/null
@@ -1,265 +0,0 @@
-<refentry id="vidioc-enum-framesizes">
-
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUM_FRAMESIZES</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUM_FRAMESIZES</refname>
- <refpurpose>Enumerate frame sizes</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_frmsizeenum *<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_ENUM_FRAMESIZES</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>Pointer to a &v4l2-frmsizeenum; that contains an index
-and pixel format and receives a frame width and height.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl allows applications to enumerate all frame sizes
-(&ie; width and height in pixels) that the device supports for the
-given pixel format.</para>
- <para>The supported pixel formats can be obtained by using the
-&VIDIOC-ENUM-FMT; function.</para>
- <para>The return value and the content of the
-<structfield>v4l2_frmsizeenum.type</structfield> field depend on the
-type of frame sizes the device supports. Here are the semantics of the
-function for the different cases:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Discrete:</emphasis> The function
-returns success if the given index value (zero-based) is valid. The
-application should increase the index by one for each call until
-<constant>EINVAL</constant> is returned. The
-<structfield>v4l2_frmsizeenum.type</structfield> field is set to
-<constant>V4L2_FRMSIZE_TYPE_DISCRETE</constant> by the driver. Of the
-union only the <structfield>discrete</structfield> member is
-valid.</para>
- </listitem>
- <listitem>
- <para><emphasis role="bold">Step-wise:</emphasis> The function
-returns success if the given index value is zero and
-<constant>EINVAL</constant> for any other index value. The
-<structfield>v4l2_frmsizeenum.type</structfield> field is set to
-<constant>V4L2_FRMSIZE_TYPE_STEPWISE</constant> by the driver. Of the
-union only the <structfield>stepwise</structfield> member is
-valid.</para>
- </listitem>
- <listitem>
- <para><emphasis role="bold">Continuous:</emphasis> This is a
-special case of the step-wise type above. The function returns success
-if the given index value is zero and <constant>EINVAL</constant> for
-any other index value. The
-<structfield>v4l2_frmsizeenum.type</structfield> field is set to
-<constant>V4L2_FRMSIZE_TYPE_CONTINUOUS</constant> by the driver. Of
-the union only the <structfield>stepwise</structfield> member is valid
-and the <structfield>step_width</structfield> and
-<structfield>step_height</structfield> values are set to 1.</para>
- </listitem>
- </itemizedlist>
-
- <para>When the application calls the function with index zero, it
-must check the <structfield>type</structfield> field to determine the
-type of frame size enumeration the device supports. Only for the
-<constant>V4L2_FRMSIZE_TYPE_DISCRETE</constant> type does it make
-sense to increase the index value to receive more frame sizes.</para>
- <para>Note that the order in which the frame sizes are returned
-has no special meaning. In particular does it not say anything about
-potential default format sizes.</para>
- <para>Applications can assume that the enumeration data does not
-change without any interaction from the application itself. This means
-that the enumeration data is consistent if the application does not
-perform any other ioctl calls while it runs the frame size
-enumeration.</para>
- </refsect1>
-
- <refsect1>
- <title>Structs</title>
-
- <para>In the structs below, <emphasis>IN</emphasis> denotes a
-value that has to be filled in by the application,
-<emphasis>OUT</emphasis> denotes values that the driver fills in. The
-application should zero out all members except for the
-<emphasis>IN</emphasis> fields.</para>
-
- <table pgwide="1" frame="none" id="v4l2-frmsize-discrete">
- <title>struct <structname>v4l2_frmsize_discrete</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Width of the frame [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Height of the frame [pixel].</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-frmsize-stepwise">
- <title>struct <structname>v4l2_frmsize_stepwise</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_width</structfield></entry>
- <entry>Minimum frame width [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_width</structfield></entry>
- <entry>Maximum frame width [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>step_width</structfield></entry>
- <entry>Frame width step size [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_height</structfield></entry>
- <entry>Minimum frame height [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_height</structfield></entry>
- <entry>Maximum frame height [pixel].</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>step_height</structfield></entry>
- <entry>Frame height step size [pixel].</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-frmsizeenum">
- <title>struct <structname>v4l2_frmsizeenum</structname></title>
- <tgroup cols="4">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry></entry>
- <entry>IN: Index of the given frame size in the enumeration.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pixel_format</structfield></entry>
- <entry></entry>
- <entry>IN: Pixel format for which the frame sizes are enumerated.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>OUT: Frame size type the device supports.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry></entry>
- <entry></entry>
- <entry>OUT: Frame size with the given index.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-frmsize-discrete;</entry>
- <entry><structfield>discrete</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-frmsize-stepwise;</entry>
- <entry><structfield>stepwise</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[2]</structfield></entry>
- <entry></entry>
- <entry>Reserved space for future use. Must be zeroed by drivers and
- applications.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- <title>Enums</title>
-
- <table pgwide="1" frame="none" id="v4l2-frmsizetypes">
- <title>enum <structname>v4l2_frmsizetypes</structname></title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FRMSIZE_TYPE_DISCRETE</constant></entry>
- <entry>1</entry>
- <entry>Discrete frame size.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FRMSIZE_TYPE_CONTINUOUS</constant></entry>
- <entry>2</entry>
- <entry>Continuous frame size.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FRMSIZE_TYPE_STEPWISE</constant></entry>
- <entry>3</entry>
- <entry>Step-wise defined frame size.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml b/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
deleted file mode 100644
index a0608abc1ab8..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enum-freq-bands.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-<refentry id="vidioc-enum-freq-bands">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUM_FREQ_BANDS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUM_FREQ_BANDS</refname>
- <refpurpose>Enumerate supported frequency bands</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_frequency_band
-*<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_ENUM_FREQ_BANDS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Enumerates the frequency bands that a tuner or modulator supports.
-To do this applications initialize the <structfield>tuner</structfield>,
-<structfield>type</structfield> and <structfield>index</structfield> fields,
-and zero out the <structfield>reserved</structfield> array of a &v4l2-frequency-band; and
-call the <constant>VIDIOC_ENUM_FREQ_BANDS</constant> ioctl with a pointer
-to this structure.</para>
-
- <para>This ioctl is supported if the <constant>V4L2_TUNER_CAP_FREQ_BANDS</constant> capability
- of the corresponding tuner/modulator is set.</para>
-
- <table pgwide="1" frame="none" id="v4l2-frequency-band">
- <title>struct <structname>v4l2_frequency_band</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>tuner</structfield></entry>
- <entry>The tuner or modulator index number. This is the
-same value as in the &v4l2-input; <structfield>tuner</structfield>
-field and the &v4l2-tuner; <structfield>index</structfield> field, or
-the &v4l2-output; <structfield>modulator</structfield> field and the
-&v4l2-modulator; <structfield>index</structfield> field.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>The tuner type. This is the same value as in the
-&v4l2-tuner; <structfield>type</structfield> field. The type must be set
-to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename>
-device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant>
-for all others. Set this field to <constant>V4L2_TUNER_RADIO</constant> for
-modulators (currently only radio modulators are supported).
-See <xref linkend="v4l2-tuner-type" /></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the frequency band, set by the application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry spanname="hspan">The tuner/modulator capability flags for
-this frequency band, see <xref linkend="tuner-capability" />. The <constant>V4L2_TUNER_CAP_LOW</constant>
-or <constant>V4L2_TUNER_CAP_1HZ</constant> capability must be the same for all frequency bands of the selected tuner/modulator.
-So either all bands have that capability set, or none of them have that capability.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangelow</structfield></entry>
- <entry spanname="hspan">The lowest tunable frequency in
-units of 62.5 kHz, or if the <structfield>capability</structfield>
-flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, for this frequency band. A 1 Hz unit is used when the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangehigh</structfield></entry>
- <entry spanname="hspan">The highest tunable frequency in
-units of 62.5 kHz, or if the <structfield>capability</structfield>
-flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, for this frequency band. A 1 Hz unit is used when the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>modulation</structfield></entry>
- <entry spanname="hspan">The supported modulation systems of this frequency band.
- See <xref linkend="band-modulation" />. Note that currently only one
- modulation system per frequency band is supported. More work will need to
- be done if multiple modulation systems are possible. Contact the
- linux-media mailing list (&v4l-ml;) if you need that functionality.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[9]</entry>
- <entry>Reserved for future extensions. Applications and drivers
- must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="band-modulation">
- <title>Band Modulation Systems</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_BAND_MODULATION_VSB</constant></entry>
- <entry>0x02</entry>
- <entry>Vestigial Sideband modulation, used for analog TV.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BAND_MODULATION_FM</constant></entry>
- <entry>0x04</entry>
- <entry>Frequency Modulation, commonly used for analog radio.</entry>
- </row>
- <row>
- <entry><constant>V4L2_BAND_MODULATION_AM</constant></entry>
- <entry>0x08</entry>
- <entry>Amplitude Modulation, commonly used for analog radio.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>tuner</structfield> or <structfield>index</structfield>
-is out of bounds or the <structfield>type</structfield> field is wrong.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enumaudio.xml b/Documentation/DocBook/media/v4l/vidioc-enumaudio.xml
deleted file mode 100644
index ea816ab2e49e..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enumaudio.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<refentry id="vidioc-enumaudio">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUMAUDIO</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUMAUDIO</refname>
- <refpurpose>Enumerate audio inputs</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_audio *<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_ENUMAUDIO</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of an audio input applications
-initialize the <structfield>index</structfield> field and zero out the
-<structfield>reserved</structfield> array of a &v4l2-audio;
-and call the <constant>VIDIOC_ENUMAUDIO</constant> ioctl with a pointer
-to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all audio
-inputs applications shall begin at index zero, incrementing by one
-until the driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <para>See <xref linkend="vidioc-g-audio" /> for a description of
-&v4l2-audio;.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The number of the audio input is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enumaudioout.xml b/Documentation/DocBook/media/v4l/vidioc-enumaudioout.xml
deleted file mode 100644
index 2e87cedb0d32..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enumaudioout.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<refentry id="vidioc-enumaudioout">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUMAUDOUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUMAUDOUT</refname>
- <refpurpose>Enumerate audio outputs</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_audioout *<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_ENUMAUDOUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of an audio output applications
-initialize the <structfield>index</structfield> field and zero out the
-<structfield>reserved</structfield> array of a &v4l2-audioout; and
-call the <constant>VIDIOC_G_AUDOUT</constant> ioctl with a pointer
-to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all audio
-outputs applications shall begin at index zero, incrementing by one
-until the driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <para>Note connectors on a TV card to loop back the received audio
-signal to a sound card are not audio outputs in this sense.</para>
-
- <para>See <xref linkend="vidioc-g-audioout" /> for a description of
-&v4l2-audioout;.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The number of the audio output is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enuminput.xml b/Documentation/DocBook/media/v4l/vidioc-enuminput.xml
deleted file mode 100644
index 603fecef9083..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enuminput.xml
+++ /dev/null
@@ -1,316 +0,0 @@
-<refentry id="vidioc-enuminput">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUMINPUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUMINPUT</refname>
- <refpurpose>Enumerate video inputs</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_input
-*<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_ENUMINPUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a video input applications
-initialize the <structfield>index</structfield> field of &v4l2-input;
-and call the <constant>VIDIOC_ENUMINPUT</constant> ioctl with a
-pointer to this structure. Drivers fill the rest of the structure or
-return an &EINVAL; when the index is out of bounds. To enumerate all
-inputs applications shall begin at index zero, incrementing by one
-until the driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <table frame="none" pgwide="1" id="v4l2-input">
- <title>struct <structname>v4l2_input</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the input, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the video input, a NUL-terminated ASCII
-string, for example: "Vin (Composite 2)". This information is intended
-for the user, preferably the connector label on the device itself.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the input, see <xref
- linkend="input-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>audioset</structfield></entry>
- <entry><para>Drivers can enumerate up to 32 video and
-audio inputs. This field shows which audio inputs were selectable as
-audio source if this was the currently selected video input. It is a
-bit mask. The LSB corresponds to audio input 0, the MSB to input 31.
-Any number of bits can be set, or none.</para><para>When the driver
-does not enumerate audio inputs no bits must be set. Applications
-shall not interpret this as lack of audio support. Some drivers
-automatically select audio sources and do not enumerate them since
-there is no choice anyway.</para><para>For details on audio inputs and
-how to select the current input see <xref
- linkend="audio" />.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>tuner</structfield></entry>
- <entry>Capture devices can have zero or more tuners (RF
-demodulators). When the <structfield>type</structfield> is set to
-<constant>V4L2_INPUT_TYPE_TUNER</constant> this is an RF connector and
-this field identifies the tuner. It corresponds to
-&v4l2-tuner; field <structfield>index</structfield>. For details on
-tuners see <xref linkend="tuner" />.</entry>
- </row>
- <row>
- <entry>&v4l2-std-id;</entry>
- <entry><structfield>std</structfield></entry>
- <entry>Every video input supports one or more different
-video standards. This field is a set of all supported standards. For
-details on video standards and how to switch see <xref
-linkend="standard" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>status</structfield></entry>
- <entry>This field provides status information about the
-input. See <xref linkend="input-status" /> for flags.
-With the exception of the sensor orientation bits <structfield>status</structfield> is only valid when this is the
-current input.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capabilities</structfield></entry>
- <entry>This field provides capabilities for the
-input. See <xref linkend="input-capabilities" /> for flags.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[3]</entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="input-type">
- <title>Input Types</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_INPUT_TYPE_TUNER</constant></entry>
- <entry>1</entry>
- <entry>This input uses a tuner (RF demodulator).</entry>
- </row>
- <row>
- <entry><constant>V4L2_INPUT_TYPE_CAMERA</constant></entry>
- <entry>2</entry>
- <entry>Analog baseband input, for example CVBS /
-Composite Video, S-Video, RGB.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- Status flags based on proposal by Mark McClelland,
-video4linux-list@redhat.com on 18 Oct 2002, subject "Re: [V4L] Re:
-v4l2 api". "Why are some of them inverted? So that the driver doesn't
-have to lie about the status in cases where it can't tell one way or
-the other. Plus, a status of zero would generally mean that everything
-is OK." -->
-
- <table frame="none" pgwide="1" id="input-status">
- <title>Input Status Flags</title>
- <tgroup cols="3">
- <colspec colname="c1" />
- <colspec colname="c2" align="center" />
- <colspec colname="c3" />
- <spanspec namest="c1" nameend="c3" spanname="hspan"
- align="left" />
- <tbody valign="top">
- <row>
- <entry spanname="hspan">General</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_POWER</constant></entry>
- <entry>0x00000001</entry>
- <entry>Attached device is off.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_SIGNAL</constant></entry>
- <entry>0x00000002</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_COLOR</constant></entry>
- <entry>0x00000004</entry>
- <entry>The hardware supports color decoding, but does not
-detect color modulation in the signal.</entry>
- </row>
- <row>
- <entry spanname="hspan">Sensor Orientation</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_HFLIP</constant></entry>
- <entry>0x00000010</entry>
- <entry>The input is connected to a device that produces a signal
-that is flipped horizontally and does not correct this before passing the
-signal to userspace.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_VFLIP</constant></entry>
- <entry>0x00000020</entry>
- <entry>The input is connected to a device that produces a signal
-that is flipped vertically and does not correct this before passing the
-signal to userspace. Note that a 180 degree rotation is the same as HFLIP | VFLIP</entry>
- </row>
- <row>
- <entry spanname="hspan">Analog Video</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_H_LOCK</constant></entry>
- <entry>0x00000100</entry>
- <entry>No horizontal sync lock.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_COLOR_KILL</constant></entry>
- <entry>0x00000200</entry>
- <entry>A color killer circuit automatically disables color
-decoding when it detects no color modulation. When this flag is set
-the color killer is enabled <emphasis>and</emphasis> has shut off
-color decoding.</entry>
- </row>
- <row>
- <entry spanname="hspan">Digital Video</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_SYNC</constant></entry>
- <entry>0x00010000</entry>
- <entry>No synchronization lock.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_EQU</constant></entry>
- <entry>0x00020000</entry>
- <entry>No equalizer lock.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_CARRIER</constant></entry>
- <entry>0x00040000</entry>
- <entry>Carrier recovery failed.</entry>
- </row>
- <row>
- <entry spanname="hspan">VCR and Set-Top Box</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_MACROVISION</constant></entry>
- <entry>0x01000000</entry>
- <entry>Macrovision is an analog copy prevention system
-mangling the video signal to confuse video recorders. When this
-flag is set Macrovision has been detected.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_NO_ACCESS</constant></entry>
- <entry>0x02000000</entry>
- <entry>Conditional access denied.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_ST_VTR</constant></entry>
- <entry>0x04000000</entry>
- <entry>VTR time constant. [?]</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- Capability flags based on video timings RFC by Muralidharan
-Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
-input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
- -->
- <table frame="none" pgwide="1" id="input-capabilities">
- <title>Input capabilities</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_IN_CAP_DV_TIMINGS</constant></entry>
- <entry>0x00000002</entry>
- <entry>This input supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_CAP_STD</constant></entry>
- <entry>0x00000004</entry>
- <entry>This input supports setting the TV standard by using VIDIOC_S_STD.</entry>
- </row>
- <row>
- <entry><constant>V4L2_IN_CAP_NATIVE_SIZE</constant></entry>
- <entry>0x00000008</entry>
- <entry>This input supports setting the native size using
- the <constant>V4L2_SEL_TGT_NATIVE_SIZE</constant>
- selection target, see <xref
- linkend="v4l2-selections-common"/>.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-input; <structfield>index</structfield> is
-out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml b/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
deleted file mode 100644
index 773fb1258c24..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
+++ /dev/null
@@ -1,201 +0,0 @@
-<refentry id="vidioc-enumoutput">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUMOUTPUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUMOUTPUT</refname>
- <refpurpose>Enumerate video outputs</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_output *<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_ENUMOUTPUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a video outputs applications
-initialize the <structfield>index</structfield> field of &v4l2-output;
-and call the <constant>VIDIOC_ENUMOUTPUT</constant> ioctl with a
-pointer to this structure. Drivers fill the rest of the structure or
-return an &EINVAL; when the index is out of bounds. To enumerate all
-outputs applications shall begin at index zero, incrementing by one
-until the driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <table frame="none" pgwide="1" id="v4l2-output">
- <title>struct <structname>v4l2_output</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the output, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the video output, a NUL-terminated ASCII
-string, for example: "Vout". This information is intended for the
-user, preferably the connector label on the device itself.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the output, see <xref
- linkend="output-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>audioset</structfield></entry>
- <entry><para>Drivers can enumerate up to 32 video and
-audio outputs. This field shows which audio outputs were
-selectable as the current output if this was the currently selected
-video output. It is a bit mask. The LSB corresponds to audio output 0,
-the MSB to output 31. Any number of bits can be set, or
-none.</para><para>When the driver does not enumerate audio outputs no
-bits must be set. Applications shall not interpret this as lack of
-audio support. Drivers may automatically select audio outputs without
-enumerating them.</para><para>For details on audio outputs and how to
-select the current output see <xref linkend="audio" />.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>modulator</structfield></entry>
- <entry>Output devices can have zero or more RF modulators.
-When the <structfield>type</structfield> is
-<constant>V4L2_OUTPUT_TYPE_MODULATOR</constant> this is an RF
-connector and this field identifies the modulator. It corresponds to
-&v4l2-modulator; field <structfield>index</structfield>. For details
-on modulators see <xref linkend="tuner" />.</entry>
- </row>
- <row>
- <entry>&v4l2-std-id;</entry>
- <entry><structfield>std</structfield></entry>
- <entry>Every video output supports one or more different
-video standards. This field is a set of all supported standards. For
-details on video standards and how to switch see <xref
- linkend="standard" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capabilities</structfield></entry>
- <entry>This field provides capabilities for the
-output. See <xref linkend="output-capabilities" /> for flags.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[3]</entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table frame="none" pgwide="1" id="output-type">
- <title>Output Type</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_OUTPUT_TYPE_MODULATOR</constant></entry>
- <entry>1</entry>
- <entry>This output is an analog TV modulator.</entry>
- </row>
- <row>
- <entry><constant>V4L2_OUTPUT_TYPE_ANALOG</constant></entry>
- <entry>2</entry>
- <entry>Analog baseband output, for example Composite /
-CVBS, S-Video, RGB.</entry>
- </row>
- <row>
- <entry><constant>V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY</constant></entry>
- <entry>3</entry>
- <entry>[?]</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- Capabilities flags based on video timings RFC by Muralidharan
-Karicheri, titled RFC (v1.2): V4L - Support for video timings at the
-input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
- -->
- <table frame="none" pgwide="1" id="output-capabilities">
- <title>Output capabilities</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_OUT_CAP_DV_TIMINGS</constant></entry>
- <entry>0x00000002</entry>
- <entry>This output supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
- </row>
- <row>
- <entry><constant>V4L2_OUT_CAP_STD</constant></entry>
- <entry>0x00000004</entry>
- <entry>This output supports setting the TV standard by using VIDIOC_S_STD.</entry>
- </row>
- <row>
- <entry><constant>V4L2_OUT_CAP_NATIVE_SIZE</constant></entry>
- <entry>0x00000008</entry>
- <entry>This output supports setting the native size using
- the <constant>V4L2_SEL_TGT_NATIVE_SIZE</constant>
- selection target, see <xref
- linkend="v4l2-selections-common"/>.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-output; <structfield>index</structfield>
-is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-enumstd.xml b/Documentation/DocBook/media/v4l/vidioc-enumstd.xml
deleted file mode 100644
index f18454e91752..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-enumstd.xml
+++ /dev/null
@@ -1,389 +0,0 @@
-<refentry id="vidioc-enumstd">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_ENUMSTD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_ENUMSTD</refname>
- <refpurpose>Enumerate supported video standards</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_standard *<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_ENUMSTD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a video standard,
-especially a custom (driver defined) one, applications initialize the
-<structfield>index</structfield> field of &v4l2-standard; and call the
-<constant>VIDIOC_ENUMSTD</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all standards
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>. Drivers may enumerate a
-different set of standards after switching the video input or
-output.<footnote>
- <para>The supported standards may overlap and we need an
-unambiguous set to find the current standard returned by
-<constant>VIDIOC_G_STD</constant>.</para>
- </footnote></para>
-
- <table pgwide="1" frame="none" id="v4l2-standard">
- <title>struct <structname>v4l2_standard</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the video standard, set by the
-application.</entry>
- </row>
- <row>
- <entry>&v4l2-std-id;</entry>
- <entry><structfield>id</structfield></entry>
- <entry>The bits in this field identify the standard as
-one of the common standards listed in <xref linkend="v4l2-std-id" />,
-or if bits 32 to 63 are set as custom standards. Multiple bits can be
-set if the hardware does not distinguish between these standards,
-however separate indices do not indicate the opposite. The
-<structfield>id</structfield> must be unique. No other enumerated
-<structname>v4l2_standard</structname> structure, for this input or
-output anyway, can contain the same set of bits.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[24]</entry>
- <entry>Name of the standard, a NUL-terminated ASCII
-string, for example: "PAL-B/G", "NTSC Japan". This information is
-intended for the user.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>frameperiod</structfield></entry>
- <entry>The frame period (not field period) is numerator
-/ denominator. For example M/NTSC has a frame period of 1001 /
-30000 seconds.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>framelines</structfield></entry>
- <entry>Total lines per frame including blanking,
-e.&nbsp;g. 625 for B/PAL.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-fract">
- <title>struct <structname>v4l2_fract</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>numerator</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>denominator</structfield></entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-std-id">
- <title>typedef <structname>v4l2_std_id</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u64</entry>
- <entry><structfield>v4l2_std_id</structfield></entry>
- <entry>This type is a set, each bit representing another
-video standard as listed below and in <xref
-linkend="video-standards" />. The 32 most significant bits are reserved
-for custom (driver defined) video standards.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para><programlisting>
-#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)
-</programlisting></para><para><constant>V4L2_STD_PAL_60</constant> is
-a hybrid standard with 525 lines, 60 Hz refresh rate, and PAL color
-modulation with a 4.43 MHz color subcarrier. Some PAL video recorders
-can play back NTSC tapes in this mode for display on a 50/60 Hz agnostic
-PAL TV.</para><para><programlisting>
-#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)
-</programlisting></para><para><constant>V4L2_STD_NTSC_443</constant>
-is a hybrid standard with 525 lines, 60 Hz refresh rate, and NTSC
-color modulation with a 4.43 MHz color
-subcarrier.</para><para><programlisting>
-#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)
-</programlisting></para><para><!-- ATSC proposal by Mark McClelland,
-video4linux-list@redhat.com on 17 Oct 2002
---><constant>V4L2_STD_ATSC_8_VSB</constant> and
-<constant>V4L2_STD_ATSC_16_VSB</constant> are U.S. terrestrial digital
-TV standards. Presently the V4L2 API does not support digital TV. See
-also the Linux DVB API at <ulink
-url="https://linuxtv.org">https://linuxtv.org</ulink>.</para>
-<para><programlisting>
-#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\
- V4L2_STD_PAL_B1 |\
- V4L2_STD_PAL_G)
-#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_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_MN (V4L2_STD_PAL_M |\
- V4L2_STD_PAL_N |\
- V4L2_STD_PAL_Nc |\
- V4L2_STD_NTSC)
-#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\
- V4L2_STD_SECAM_K |\
- V4L2_STD_SECAM_K1)
-#define V4L2_STD_DK (V4L2_STD_PAL_DK |\
- V4L2_STD_SECAM_DK)
-
-#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_UNKNOWN 0
-#define V4L2_STD_ALL (V4L2_STD_525_60 |\
- V4L2_STD_625_50)
-</programlisting></para>
-
- <table pgwide="1" id="video-standards" orient="land">
- <title>Video Standards (based on [<xref linkend="itu470" />])</title>
- <tgroup cols="12" colsep="1" rowsep="1" align="center">
- <colspec colname="c1" align="left" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <colspec colname="c5" />
- <colspec colnum="7" colname="c7" />
- <colspec colnum="9" colname="c9" />
- <colspec colnum="12" colname="c12" />
- <spanspec namest="c2" nameend="c3" spanname="m" align="center" />
- <spanspec namest="c4" nameend="c12" spanname="x" align="center" />
- <spanspec namest="c5" nameend="c7" spanname="b" align="center" />
- <spanspec namest="c9" nameend="c12" spanname="s" align="center" />
- <thead>
- <row>
- <entry>Characteristics</entry>
- <entry><para>M/NTSC<footnote><para>Japan uses a standard
-similar to M/NTSC
-(V4L2_STD_NTSC_M_JP).</para></footnote></para></entry>
- <entry>M/PAL</entry>
- <entry><para>N/PAL<footnote><para> The values in
-brackets apply to the combination N/PAL a.k.a.
-N<subscript>C</subscript> used in Argentina
-(V4L2_STD_PAL_Nc).</para></footnote></para></entry>
- <entry align="center">B, B1, G/PAL</entry>
- <entry align="center">D, D1, K/PAL</entry>
- <entry align="center">H/PAL</entry>
- <entry align="center">I/PAL</entry>
- <entry align="center">B, G/SECAM</entry>
- <entry align="center">D, K/SECAM</entry>
- <entry align="center">K1/SECAM</entry>
- <entry align="center">L/SECAM</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry>Frame lines</entry>
- <entry spanname="m">525</entry>
- <entry spanname="x">625</entry>
- </row>
- <row>
- <entry>Frame period (s)</entry>
- <entry spanname="m">1001/30000</entry>
- <entry spanname="x">1/25</entry>
- </row>
- <row>
- <entry>Chrominance sub-carrier frequency (Hz)</entry>
- <entry>3579545 &plusmn;&nbsp;10</entry>
- <entry>3579611.49 &plusmn;&nbsp;10</entry>
- <entry>4433618.75 &plusmn;&nbsp;5 (3582056.25
-&plusmn;&nbsp;5)</entry>
- <entry spanname="b">4433618.75 &plusmn;&nbsp;5</entry>
- <entry>4433618.75 &plusmn;&nbsp;1</entry>
- <entry spanname="s">f<subscript>OR</subscript>&nbsp;=
-4406250 &plusmn;&nbsp;2000, f<subscript>OB</subscript>&nbsp;= 4250000
-&plusmn;&nbsp;2000</entry>
- </row>
- <row>
- <entry>Nominal radio-frequency channel bandwidth
-(MHz)</entry>
- <entry>6</entry>
- <entry>6</entry>
- <entry>6</entry>
- <entry>B: 7; B1, G: 8</entry>
- <entry>8</entry>
- <entry>8</entry>
- <entry>8</entry>
- <entry>8</entry>
- <entry>8</entry>
- <entry>8</entry>
- <entry>8</entry>
- </row>
- <row>
- <entry>Sound carrier relative to vision carrier
-(MHz)</entry>
- <entry>+&nbsp;4.5</entry>
- <entry>+&nbsp;4.5</entry>
- <entry>+&nbsp;4.5</entry>
- <entry><para>+&nbsp;5.5 &plusmn;&nbsp;0.001
-<footnote><para>In the Federal Republic of Germany, Austria, Italy,
-the Netherlands, Slovakia and Switzerland a system of two sound
-carriers is used, the frequency of the second carrier being
-242.1875&nbsp;kHz above the frequency of the first sound carrier. For
-stereophonic sound transmissions a similar system is used in
-Australia.</para></footnote> <footnote><para>New Zealand uses a sound
-carrier displaced 5.4996 &plusmn;&nbsp;0.0005 MHz from the vision
-carrier.</para></footnote> <footnote><para>In Denmark, Finland, New
-Zealand, Sweden and Spain a system of two sound carriers is used. In
-Iceland, Norway and Poland the same system is being introduced. The
-second carrier is 5.85&nbsp;MHz above the vision carrier and is DQPSK
-modulated with 728&nbsp;kbit/s sound and data multiplex. (NICAM
-system)</para></footnote> <footnote><para>In the United Kingdom, a
-system of two sound carriers is used. The second sound carrier is
-6.552&nbsp;MHz above the vision carrier and is DQPSK modulated with a
-728&nbsp;kbit/s sound and data multiplex able to carry two sound
-channels. (NICAM system)</para></footnote></para></entry>
- <entry>+&nbsp;6.5 &plusmn;&nbsp;0.001</entry>
- <entry>+&nbsp;5.5</entry>
- <entry>+&nbsp;5.9996 &plusmn;&nbsp;0.0005</entry>
- <entry>+&nbsp;5.5 &plusmn;&nbsp;0.001</entry>
- <entry>+&nbsp;6.5 &plusmn;&nbsp;0.001</entry>
- <entry>+&nbsp;6.5</entry>
- <entry><para>+&nbsp;6.5 <footnote><para>In France, a
-digital carrier 5.85 MHz away from the vision carrier may be used in
-addition to the main sound carrier. It is modulated in differentially
-encoded QPSK with a 728 kbit/s sound and data multiplexer capable of
-carrying two sound channels. (NICAM
-system)</para></footnote></para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-standard; <structfield>index</structfield>
-is out of bounds.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Standard video timings are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml b/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
deleted file mode 100644
index a6558a676ef3..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-expbuf.xml
+++ /dev/null
@@ -1,205 +0,0 @@
-<refentry id="vidioc-expbuf">
-
- <refmeta>
- <refentrytitle>ioctl VIDIOC_EXPBUF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_EXPBUF</refname>
- <refpurpose>Export a buffer as a DMABUF file descriptor.</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_exportbuffer *<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_EXPBUF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>This ioctl is an extension to the <link linkend="mmap">memory
-mapping</link> I/O method, therefore it is available only for
-<constant>V4L2_MEMORY_MMAP</constant> buffers. It can be used to export a
-buffer as a DMABUF file at any time after buffers have been allocated with the
-&VIDIOC-REQBUFS; ioctl.</para>
-
-<para> To export a buffer, applications fill &v4l2-exportbuffer;. The
-<structfield>type</structfield> field is set to the same buffer type as was
-previously used with &v4l2-requestbuffers; <structfield>type</structfield>.
-Applications must also set the <structfield>index</structfield> field. Valid
-index numbers range from zero to the number of buffers allocated with
-&VIDIOC-REQBUFS; (&v4l2-requestbuffers; <structfield>count</structfield>)
-minus one. For the multi-planar API, applications set the <structfield>plane</structfield>
-field to the index of the plane to be exported. Valid planes
-range from zero to the maximal number of valid planes for the currently active
-format. For the single-planar API, applications must set <structfield>plane</structfield>
-to zero. Additional flags may be posted in the <structfield>flags</structfield>
-field. Refer to a manual for open() for details.
-Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported. All
-other fields must be set to zero.
-In the case of multi-planar API, every plane is exported separately using
-multiple <constant>VIDIOC_EXPBUF</constant> calls.</para>
-
-<para>After calling <constant>VIDIOC_EXPBUF</constant> the <structfield>fd</structfield>
-field will be set by a driver. This is a DMABUF file
-descriptor. The application may pass it to other DMABUF-aware devices. Refer to
-<link linkend="dmabuf">DMABUF importing</link> for details about importing
-DMABUF files into V4L2 nodes. It is recommended to close a DMABUF file when it
-is no longer used to allow the associated memory to be reclaimed.</para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
-
- <example>
- <title>Exporting a buffer.</title>
- <programlisting>
-int buffer_export(int v4lfd, &v4l2-buf-type; bt, int index, int *dmafd)
-{
- &v4l2-exportbuffer; expbuf;
-
- memset(&amp;expbuf, 0, sizeof(expbuf));
- expbuf.type = bt;
- expbuf.index = index;
- if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
- perror("VIDIOC_EXPBUF");
- return -1;
- }
-
- *dmafd = expbuf.fd;
-
- return 0;
-}
- </programlisting>
- </example>
-
- <example>
- <title>Exporting a buffer using the multi-planar API.</title>
- <programlisting>
-int buffer_export_mp(int v4lfd, &v4l2-buf-type; bt, int index,
- int dmafd[], int n_planes)
-{
- int i;
-
- for (i = 0; i &lt; n_planes; ++i) {
- &v4l2-exportbuffer; expbuf;
-
- memset(&amp;expbuf, 0, sizeof(expbuf));
- expbuf.type = bt;
- expbuf.index = index;
- expbuf.plane = i;
- if (ioctl(v4lfd, &VIDIOC-EXPBUF;, &amp;expbuf) == -1) {
- perror("VIDIOC_EXPBUF");
- while (i)
- close(dmafd[--i]);
- return -1;
- }
- dmafd[i] = expbuf.fd;
- }
-
- return 0;
-}
- </programlisting>
- </example>
-
- <table pgwide="1" frame="none" id="v4l2-exportbuffer">
- <title>struct <structname>v4l2_exportbuffer</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the buffer, same as &v4l2-format;
-<structfield>type</structfield> or &v4l2-requestbuffers;
-<structfield>type</structfield>, set by the application. See <xref
-linkend="v4l2-buf-type" /></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the buffer, set by the application. This field is
-only used for <link linkend="mmap">memory mapping</link> I/O and can range from
-zero to the number of buffers allocated with the &VIDIOC-REQBUFS; and/or
-&VIDIOC-CREATE-BUFS; ioctls. </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>plane</structfield></entry>
- <entry>Index of the plane to be exported when using the
-multi-planar API. Otherwise this value must be set to zero. </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags for the newly created file, currently only
-<constant>O_CLOEXEC</constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY</constant>,
-and <constant>O_RDWR</constant> are supported, refer to the manual
-of open() for more details.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>fd</structfield></entry>
- <entry>The DMABUF file descriptor associated with a buffer. Set by
- the driver.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[11]</structfield></entry>
- <entry>Reserved field for future use. Drivers and applications must
-set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>A queue is not in MMAP mode or DMABUF exporting is not
-supported or <structfield>flags</structfield> or <structfield>type</structfield>
-or <structfield>index</structfield> or <structfield>plane</structfield> fields
-are invalid.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-audio.xml b/Documentation/DocBook/media/v4l/vidioc-g-audio.xml
deleted file mode 100644
index d7bb9b3738f6..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-audio.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-<refentry id="vidioc-g-audio">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_AUDIO, VIDIOC_S_AUDIO</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_AUDIO</refname>
- <refname>VIDIOC_S_AUDIO</refname>
- <refpurpose>Query or select the current audio input and its
-attributes</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_audio *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_audio *<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_G_AUDIO, VIDIOC_S_AUDIO</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the current audio input applications zero out the
-<structfield>reserved</structfield> array of a &v4l2-audio;
-and call the <constant>VIDIOC_G_AUDIO</constant> ioctl with a pointer
-to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the device has no audio inputs, or none which combine
-with the current video input.</para>
-
- <para>Audio inputs have one writable property, the audio mode. To
-select the current audio input <emphasis>and</emphasis> change the
-audio mode, applications initialize the
-<structfield>index</structfield> and <structfield>mode</structfield>
-fields, and the
-<structfield>reserved</structfield> array of a
-<structname>v4l2_audio</structname> structure and call the
-<constant>VIDIOC_S_AUDIO</constant> ioctl. Drivers may switch to a
-different audio mode if the request cannot be satisfied. However, this
-is a write-only ioctl, it does not return the actual new audio
-mode.</para>
-
- <table pgwide="1" frame="none" id="v4l2-audio">
- <title>struct <structname>v4l2_audio</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the audio input, set by the
-driver or application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the audio input, a NUL-terminated ASCII
-string, for example: "Line In". This information is intended for the
-user, preferably the connector label on the device itself.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry>Audio capability flags, see <xref
- linkend="audio-capability" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>mode</structfield></entry>
- <entry>Audio mode flags set by drivers and applications (on
- <constant>VIDIOC_S_AUDIO</constant> ioctl), see <xref linkend="audio-mode" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="audio-capability">
- <title>Audio Capability Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_AUDCAP_STEREO</constant></entry>
- <entry>0x00001</entry>
- <entry>This is a stereo input. The flag is intended to
-automatically disable stereo recording etc. when the signal is always
-monaural. The API provides no means to detect if stereo is
-<emphasis>received</emphasis>, unless the audio input belongs to a
-tuner.</entry>
- </row>
- <row>
- <entry><constant>V4L2_AUDCAP_AVL</constant></entry>
- <entry>0x00002</entry>
- <entry>Automatic Volume Level mode is supported.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="audio-mode">
- <title>Audio Mode Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_AUDMODE_AVL</constant></entry>
- <entry>0x00001</entry>
- <entry>AVL mode is on.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <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.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-audioout.xml b/Documentation/DocBook/media/v4l/vidioc-g-audioout.xml
deleted file mode 100644
index 200a2704a970..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-audioout.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-<refentry id="vidioc-g-audioout">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_AUDOUT, VIDIOC_S_AUDOUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_AUDOUT</refname>
- <refname>VIDIOC_S_AUDOUT</refname>
- <refpurpose>Query or select the current audio output</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_audioout *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_audioout *<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_G_AUDOUT, VIDIOC_S_AUDOUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the current audio output applications zero out the
-<structfield>reserved</structfield> array of a &v4l2-audioout; and
-call the <constant>VIDIOC_G_AUDOUT</constant> ioctl with a pointer
-to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the device has no audio inputs, or none which combine
-with the current video output.</para>
-
- <para>Audio outputs have no writable properties. Nevertheless, to
-select the current audio output applications can initialize the
-<structfield>index</structfield> field and
-<structfield>reserved</structfield> array (which in the future may
-contain writable properties) of a
-<structname>v4l2_audioout</structname> structure and call the
-<constant>VIDIOC_S_AUDOUT</constant> ioctl. Drivers switch to the
-requested output or return the &EINVAL; when the index is out of
-bounds. This is a write-only ioctl, it does not return the current
-audio output attributes as <constant>VIDIOC_G_AUDOUT</constant>
-does.</para>
-
- <para>Note connectors on a TV card to loop back the received audio
-signal to a sound card are not audio outputs in this sense.</para>
-
- <table pgwide="1" frame="none" id="v4l2-audioout">
- <title>struct <structname>v4l2_audioout</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the audio output, set by the
-driver or application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the audio output, a NUL-terminated ASCII
-string, for example: "Line Out". This information is intended for the
-user, preferably the connector label on the device itself.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry>Audio capability flags, none defined yet. Drivers
-must set this field to zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>mode</structfield></entry>
- <entry>Audio mode, none defined yet. Drivers and
-applications (on <constant>VIDIOC_S_AUDOUT</constant>) must set this
-field to zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <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.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-crop.xml b/Documentation/DocBook/media/v4l/vidioc-g-crop.xml
deleted file mode 100644
index e6c4efb9e8b4..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-crop.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<refentry id="vidioc-g-crop">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_CROP, VIDIOC_S_CROP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_CROP</refname>
- <refname>VIDIOC_S_CROP</refname>
- <refpurpose>Get or set the current cropping rectangle</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_crop *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_crop *<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_G_CROP, VIDIOC_S_CROP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the cropping rectangle size and position
-applications set the <structfield>type</structfield> field of a
-<structname>v4l2_crop</structname> structure to the respective buffer
-(stream) type and call the <constant>VIDIOC_G_CROP</constant> ioctl
-with a pointer to this structure. The driver fills the rest of the
-structure or returns the &EINVAL; if cropping is not supported.</para>
-
- <para>To change the cropping rectangle applications initialize the
-<structfield>type</structfield> and &v4l2-rect; substructure named
-<structfield>c</structfield> of a v4l2_crop structure and call the
-<constant>VIDIOC_S_CROP</constant> ioctl with a pointer to this
-structure.</para>
-
-<para>Do not use the multiplanar buffer types. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
-and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
-
- <para>The driver first adjusts the requested dimensions against
-hardware limits, &ie; the bounds given by the capture/output window,
-and it rounds to the closest possible values of horizontal and
-vertical offset, width and height. In particular the driver must round
-the vertical offset of the cropping rectangle to frame lines modulo
-two, such that the field order cannot be confused.</para>
-
- <para>Second the driver adjusts the image size (the opposite
-rectangle of the scaling process, source or target depending on the
-data direction) to the closest size possible while maintaining the
-current horizontal and vertical scaling factor.</para>
-
- <para>Finally the driver programs the hardware with the actual
-cropping and image parameters. <constant>VIDIOC_S_CROP</constant> is a
-write-only ioctl, it does not return the actual parameters. To query
-them applications must call <constant>VIDIOC_G_CROP</constant> and
-&VIDIOC-G-FMT;. When the parameters are unsuitable the application may
-modify the cropping or image parameters and repeat the cycle until
-satisfactory parameters have been negotiated.</para>
-
- <para>When cropping is not supported then no parameters are
-changed and <constant>VIDIOC_S_CROP</constant> returns the
-&EINVAL;.</para>
-
- <table pgwide="1" frame="none" id="v4l2-crop">
- <title>struct <structname>v4l2_crop</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the data stream, set by the application.
-Only these types are valid here: <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
- </row>
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>c</structfield></entry>
- <entry>Cropping rectangle. The same co-ordinate system as
-for &v4l2-cropcap; <structfield>bounds</structfield> is used.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml b/Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml
deleted file mode 100644
index ee2820d6ca66..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-ctrl.xml
+++ /dev/null
@@ -1,133 +0,0 @@
-<refentry id="vidioc-g-ctrl">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_CTRL, VIDIOC_S_CTRL</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_CTRL</refname>
- <refname>VIDIOC_S_CTRL</refname>
- <refpurpose>Get or set the value of a control</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_control
-*<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_G_CTRL, VIDIOC_S_CTRL</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To get the current value of a control applications
-initialize the <structfield>id</structfield> field of a struct
-<structname>v4l2_control</structname> and call the
-<constant>VIDIOC_G_CTRL</constant> ioctl with a pointer to this
-structure. To change the value of a control applications initialize
-the <structfield>id</structfield> and <structfield>value</structfield>
-fields of a struct <structname>v4l2_control</structname> and call the
-<constant>VIDIOC_S_CTRL</constant> ioctl.</para>
-
- <para>When the <structfield>id</structfield> is invalid drivers
-return an &EINVAL;. When the <structfield>value</structfield> is out
-of bounds drivers can choose to take the closest valid value or return
-an &ERANGE;, whatever seems more appropriate. However,
-<constant>VIDIOC_S_CTRL</constant> is a write-only ioctl, it does not
-return the actual new value. If the <structfield>value</structfield>
-is inappropriate for the control (e.g. if it refers to an unsupported
-menu index of a menu control), then &EINVAL; is returned as well.</para>
-
- <para>These ioctls work only with user controls. For other
-control classes the &VIDIOC-G-EXT-CTRLS;, &VIDIOC-S-EXT-CTRLS; or
-&VIDIOC-TRY-EXT-CTRLS; must be used.</para>
-
- <table pgwide="1" frame="none" id="v4l2-control">
- <title>struct <structname>v4l2_control</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry>Identifies the control, set by the
-application.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>value</structfield></entry>
- <entry>New value or current value.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-control; <structfield>id</structfield> is
-invalid or the <structfield>value</structfield> is inappropriate for
-the given control (i.e. if a menu item is selected that is not supported
-by the driver according to &VIDIOC-QUERYMENU;).</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ERANGE</errorcode></term>
- <listitem>
- <para>The &v4l2-control; <structfield>value</structfield>
-is out of bounds.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The control is temporarily not changeable, possibly
-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>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml
deleted file mode 100644
index 06952d7cc770..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml
+++ /dev/null
@@ -1,343 +0,0 @@
-<refentry id="vidioc-g-dv-timings">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_DV_TIMINGS</refname>
- <refname>VIDIOC_S_DV_TIMINGS</refname>
- <refname>VIDIOC_SUBDEV_G_DV_TIMINGS</refname>
- <refname>VIDIOC_SUBDEV_S_DV_TIMINGS</refname>
- <refpurpose>Get or set DV timings for input or output</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_dv_timings *<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_G_DV_TIMINGS, VIDIOC_S_DV_TIMINGS, VIDIOC_SUBDEV_G_DV_TIMINGS, VIDIOC_SUBDEV_S_DV_TIMINGS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>To set DV timings for the input or output, applications use the
-<constant>VIDIOC_S_DV_TIMINGS</constant> ioctl and to get the current timings,
-applications use the <constant>VIDIOC_G_DV_TIMINGS</constant> ioctl. The detailed timing
-information is filled in using the structure &v4l2-dv-timings;. These ioctls take
-a pointer to the &v4l2-dv-timings; structure as argument. If the ioctl is not supported
-or the timing values are not correct, the driver returns &EINVAL;.</para>
-<para>The <filename>linux/v4l2-dv-timings.h</filename> header can be used to get the
-timings of the formats in the <xref linkend="cea861" /> and <xref linkend="vesadmt" />
-standards. If the current input or output does not support DV timings (e.g. if
-&VIDIOC-ENUMINPUT; does not set the <constant>V4L2_IN_CAP_DV_TIMINGS</constant> flag), then
-&ENODATA; is returned.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>This ioctl is not supported, or the
-<constant>VIDIOC_S_DV_TIMINGS</constant> parameter was unsuitable.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Digital video timings are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The device is busy and therefore can not change the timings.</para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <table pgwide="1" frame="none" id="v4l2-bt-timings">
- <title>struct <structname>v4l2_bt_timings</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Width of the active video in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Height of the active video frame in lines. So for interlaced formats the
- height of the active video in each field is <structfield>height</structfield>/2.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>interlaced</structfield></entry>
- <entry>Progressive (0) or interlaced (1)</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>polarities</structfield></entry>
- <entry>This is a bit mask that defines polarities of sync signals.
-bit 0 (V4L2_DV_VSYNC_POS_POL) is for vertical sync polarity and bit 1 (V4L2_DV_HSYNC_POS_POL) is for horizontal sync polarity. If the bit is set
-(1) it is positive polarity and if is cleared (0), it is negative polarity.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>pixelclock</structfield></entry>
- <entry>Pixel clock in Hz. Ex. 74.25MHz->74250000</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>hfrontporch</structfield></entry>
- <entry>Horizontal front porch in pixels</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>hsync</structfield></entry>
- <entry>Horizontal sync length in pixels</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>hbackporch</structfield></entry>
- <entry>Horizontal back porch in pixels</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>vfrontporch</structfield></entry>
- <entry>Vertical front porch in lines. For interlaced formats this refers to the
- odd field (aka field 1).</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>vsync</structfield></entry>
- <entry>Vertical sync length in lines. For interlaced formats this refers to the
- odd field (aka field 1).</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>vbackporch</structfield></entry>
- <entry>Vertical back porch in lines. For interlaced formats this refers to the
- odd field (aka field 1).</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>il_vfrontporch</structfield></entry>
- <entry>Vertical front porch in lines for the even field (aka field 2) of
- interlaced field formats. Must be 0 for progressive formats.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>il_vsync</structfield></entry>
- <entry>Vertical sync length in lines for the even field (aka field 2) of
- interlaced field formats. Must be 0 for progressive formats.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>il_vbackporch</structfield></entry>
- <entry>Vertical back porch in lines for the even field (aka field 2) of
- interlaced field formats. Must be 0 for progressive formats.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>standards</structfield></entry>
- <entry>The video standard(s) this format belongs to. This will be filled in by
- the driver. Applications must set this to 0. See <xref linkend="dv-bt-standards"/>
- for a list of standards.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Several flags giving more information about the format.
- See <xref linkend="dv-bt-flags"/> for a description of the flags.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-dv-timings">
- <title>struct <structname>v4l2_dv_timings</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>Type of DV timings as listed in <xref linkend="dv-timing-types"/>.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield></structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-bt-timings;</entry>
- <entry><structfield>bt</structfield></entry>
- <entry>Timings defined by BT.656/1120 specifications</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[32]</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="dv-timing-types">
- <title>DV Timing types</title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>Timing type</entry>
- <entry>value</entry>
- <entry>Description</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_656_1120</entry>
- <entry>0</entry>
- <entry>BT.656/1120 timings</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table pgwide="1" frame="none" id="dv-bt-standards">
- <title>DV BT Timing standards</title>
- <tgroup cols="2">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>Timing standard</entry>
- <entry>Description</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_STD_CEA861</entry>
- <entry>The timings follow the CEA-861 Digital TV Profile standard</entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_STD_DMT</entry>
- <entry>The timings follow the VESA Discrete Monitor Timings standard</entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_STD_CVT</entry>
- <entry>The timings follow the VESA Coordinated Video Timings standard</entry>
- </row>
- <row>
- <entry>V4L2_DV_BT_STD_GTF</entry>
- <entry>The timings follow the VESA Generalized Timings Formula standard</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <table pgwide="1" frame="none" id="dv-bt-flags">
- <title>DV BT Timing flags</title>
- <tgroup cols="2">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>Flag</entry>
- <entry>Description</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry>V4L2_DV_FL_REDUCED_BLANKING</entry>
- <entry>CVT/GTF specific: the timings use reduced blanking (CVT) or the 'Secondary
-GTF' curve (GTF). In both cases the horizontal and/or vertical blanking
-intervals are reduced, allowing a higher resolution over the same
-bandwidth. This is a read-only flag, applications must not set this.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_FL_CAN_REDUCE_FPS</entry>
- <entry>CEA-861 specific: set for CEA-861 formats with a framerate that is a multiple
-of six. These formats can be optionally played at 1 / 1.001 speed to
-be compatible with 60 Hz based standards such as NTSC and PAL-M that use a framerate of
-29.97 frames per second. If the transmitter can't generate such frequencies, then the
-flag will also be cleared. This is a read-only flag, applications must not set this.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_FL_REDUCED_FPS</entry>
- <entry>CEA-861 specific: only valid for video transmitters, the flag is cleared
-by receivers. It is also only valid for formats with the V4L2_DV_FL_CAN_REDUCE_FPS flag
-set, for other formats the flag will be cleared by the driver.
-
-If the application sets this flag, then the pixelclock used to set up the transmitter is
-divided by 1.001 to make it compatible with NTSC framerates. If the transmitter
-can't generate such frequencies, then the flag will also be cleared.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_FL_HALF_LINE</entry>
- <entry>Specific to interlaced formats: if set, then the vertical frontporch
-of field 1 (aka the odd field) is really one half-line longer and the vertical backporch
-of field 2 (aka the even field) is really one half-line shorter, so each field has exactly
-the same number of half-lines. Whether half-lines can be detected or used depends on
-the hardware.
- </entry>
- </row>
- <row>
- <entry>V4L2_DV_FL_IS_CE_VIDEO</entry>
- <entry>If set, then this is a Consumer Electronics (CE) video format.
-Such formats differ from other formats (commonly called IT formats) in that if
-R'G'B' encoding is used then by default the R'G'B' values use limited range
-(i.e. 16-235) as opposed to full range (i.e. 0-255). All formats defined in CEA-861
-except for the 640x480p59.94 format are CE formats.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
deleted file mode 100644
index b7602d30f596..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-edid.xml
+++ /dev/null
@@ -1,173 +0,0 @@
-<refentry id="vidioc-g-edid">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_EDID</refname>
- <refname>VIDIOC_S_EDID</refname>
- <refname>VIDIOC_SUBDEV_G_EDID</refname>
- <refname>VIDIOC_SUBDEV_S_EDID</refname>
- <refpurpose>Get or set the EDID of a video receiver/transmitter</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_edid *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>struct v4l2_edid *<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_G_EDID, VIDIOC_S_EDID, VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>These ioctls can be used to get or set an EDID associated with an input
- from a receiver or an output of a transmitter device. They can be
- used with subdevice nodes (/dev/v4l-subdevX) or with video nodes (/dev/videoX).</para>
-
- <para>When used with video nodes the <structfield>pad</structfield> field represents the
- input (for video capture devices) or output (for video output devices) index as
- is returned by &VIDIOC-ENUMINPUT; and &VIDIOC-ENUMOUTPUT; respectively. When used
- with subdevice nodes the <structfield>pad</structfield> field represents the
- input or output pad of the subdevice. If there is no EDID support for the given
- <structfield>pad</structfield> value, then the &EINVAL; will be returned.</para>
-
- <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>,
- <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield>
- fields, zero the <structfield>reserved</structfield> array and call
- <constant>VIDIOC_G_EDID</constant>. The current EDID from block
- <structfield>start_block</structfield> and of size <structfield>blocks</structfield>
- will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield>
- pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes
- large (the size of one block is 128 bytes).</para>
-
- <para>If there are fewer blocks than specified, then the driver will set <structfield>blocks</structfield>
- to the actual number of blocks. If there are no EDID blocks available at all, then the error code
- ENODATA is set.</para>
-
- <para>If blocks have to be retrieved from the sink, then this call will block until they
- have been read.</para>
-
- <para>If <structfield>start_block</structfield> and <structfield>blocks</structfield> are
- both set to 0 when <constant>VIDIOC_G_EDID</constant> is called, then the driver will
- set <structfield>blocks</structfield> to the total number of available EDID blocks
- and it will return 0 without copying any data. This is an easy way to discover how many
- EDID blocks there are. Note that if there are no EDID blocks available at all, then
- the driver will set <structfield>blocks</structfield> to 0 and it returns 0.</para>
-
- <para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>,
- <structfield>blocks</structfield> and <structfield>edid</structfield> fields, set
- <structfield>start_block</structfield> to 0 and zero the <structfield>reserved</structfield> array.
- It is not possible to set part of an EDID,
- it is always all or nothing. Setting the EDID data is only valid for receivers as it makes
- no sense for a transmitter.</para>
-
- <para>The driver assumes that the full EDID is passed in. If there are more EDID blocks than
- the hardware can handle then the EDID is not written, but instead the error code E2BIG is set
- and <structfield>blocks</structfield> is set to the maximum that the hardware supports.
- If <structfield>start_block</structfield> is any
- value other than 0 then the error code EINVAL is set.</para>
-
- <para>To disable an EDID you set <structfield>blocks</structfield> to 0. Depending on the
- hardware this will drive the hotplug pin low and/or block the source from reading the EDID
- data in some way. In any case, the end result is the same: the EDID is no longer available.
- </para>
-
- <table pgwide="1" frame="none" id="v4l2-edid">
- <title>struct <structname>v4l2_edid</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad for which to get/set the EDID blocks. When used with a video device
- node the pad represents the input or output index as returned by
- &VIDIOC-ENUMINPUT; and &VIDIOC-ENUMOUTPUT; respectively.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>start_block</structfield></entry>
- <entry>Read the EDID from starting with this block. Must be 0 when setting
- the EDID.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>blocks</structfield></entry>
- <entry>The number of blocks to get or set. Must be less or equal to 256 (the
- maximum number of blocks as defined by the standard). When you set the EDID and
- <structfield>blocks</structfield> is 0, then the EDID is disabled or erased.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[5]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- <row>
- <entry>__u8&nbsp;*</entry>
- <entry><structfield>edid</structfield></entry>
- <entry>Pointer to memory that contains the EDID. The minimum size is
- <structfield>blocks</structfield>&nbsp;*&nbsp;128.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>The EDID data is not available.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>E2BIG</errorcode></term>
- <listitem>
- <para>The EDID data you provided is more than the hardware can handle.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml b/Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml
deleted file mode 100644
index be25029a16f1..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml
+++ /dev/null
@@ -1,189 +0,0 @@
-<refentry id="vidioc-g-enc-index">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_ENC_INDEX</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_ENC_INDEX</refname>
- <refpurpose>Get meta data about a compressed video stream</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_enc_idx *<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_G_ENC_INDEX</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The <constant>VIDIOC_G_ENC_INDEX</constant> ioctl provides
-meta data about a compressed video stream the same or another
-application currently reads from the driver, which is useful for
-random access into the stream without decoding it.</para>
-
- <para>To read the data applications must call
-<constant>VIDIOC_G_ENC_INDEX</constant> with a pointer to a
-&v4l2-enc-idx;. On success the driver fills the
-<structfield>entry</structfield> array, stores the number of elements
-written in the <structfield>entries</structfield> field, and
-initializes the <structfield>entries_cap</structfield> field.</para>
-
- <para>Each element of the <structfield>entry</structfield> array
-contains meta data about one picture. A
-<constant>VIDIOC_G_ENC_INDEX</constant> call reads up to
-<constant>V4L2_ENC_IDX_ENTRIES</constant> entries from a driver
-buffer, which can hold up to <structfield>entries_cap</structfield>
-entries. This number can be lower or higher than
-<constant>V4L2_ENC_IDX_ENTRIES</constant>, but not zero. When the
-application fails to read the meta data in time the oldest entries
-will be lost. When the buffer is empty or no capturing/encoding is in
-progress, <structfield>entries</structfield> will be zero.</para>
-
- <para>Currently this ioctl is only defined for MPEG-2 program
-streams and video elementary streams.</para>
-
- <table pgwide="1" frame="none" id="v4l2-enc-idx">
- <title>struct <structname>v4l2_enc_idx</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>entries</structfield></entry>
- <entry>The number of entries the driver stored in the
-<structfield>entry</structfield> array.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>entries_cap</structfield></entry>
- <entry>The number of entries the driver can
-buffer. Must be greater than zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry spanname="hspan">Reserved for future extensions.
-Drivers must set the array to zero.</entry>
- </row>
- <row>
- <entry>&v4l2-enc-idx-entry;</entry>
- <entry><structfield>entry</structfield>[<constant>V4L2_ENC_IDX_ENTRIES</constant>]</entry>
- <entry>Meta data about a compressed video stream. Each
-element of the array corresponds to one picture, sorted in ascending
-order by their <structfield>offset</structfield>.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-enc-idx-entry">
- <title>struct <structname>v4l2_enc_idx_entry</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u64</entry>
- <entry><structfield>offset</structfield></entry>
- <entry>The offset in bytes from the beginning of the
-compressed video stream to the beginning of this picture, that is a
-<wordasword>PES packet header</wordasword> as defined in <xref
- linkend="mpeg2part1" /> or a <wordasword>picture
-header</wordasword> as defined in <xref linkend="mpeg2part2" />. When
-the encoder is stopped, the driver resets the offset to zero.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>pts</structfield></entry>
- <entry>The 33 bit <wordasword>Presentation Time
-Stamp</wordasword> of this picture as defined in <xref
- linkend="mpeg2part1" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>length</structfield></entry>
- <entry>The length of this picture in bytes.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags containing the coding type of this picture, see <xref
- linkend="enc-idx-flags" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions.
-Drivers must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="enc-idx-flags">
- <title>Index Entry Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_ENC_IDX_FRAME_I</constant></entry>
- <entry>0x00</entry>
- <entry>This is an Intra-coded picture.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_IDX_FRAME_P</constant></entry>
- <entry>0x01</entry>
- <entry>This is a Predictive-coded picture.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_IDX_FRAME_B</constant></entry>
- <entry>0x02</entry>
- <entry>This is a Bidirectionally predictive-coded
-picture.</entry>
- </row>
- <row>
- <entry><constant>V4L2_ENC_IDX_FRAME_MASK</constant></entry>
- <entry>0x0F</entry>
- <entry><wordasword>AND</wordasword> the flags field with
-this mask to obtain the picture coding type.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
deleted file mode 100644
index eb82f7e7d06b..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ /dev/null
@@ -1,456 +0,0 @@
-<refentry id="vidioc-g-ext-ctrls">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_EXT_CTRLS, VIDIOC_S_EXT_CTRLS,
-VIDIOC_TRY_EXT_CTRLS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_EXT_CTRLS</refname>
- <refname>VIDIOC_S_EXT_CTRLS</refname>
- <refname>VIDIOC_TRY_EXT_CTRLS</refname>
- <refpurpose>Get or set the value of several controls, try control
-values</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_ext_controls
-*<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_G_EXT_CTRLS, VIDIOC_S_EXT_CTRLS,
-VIDIOC_TRY_EXT_CTRLS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls allow the caller to get or set multiple
-controls atomically. Control IDs are grouped into control classes (see
-<xref linkend="ctrl-class" />) and all controls in the control array
-must belong to the same control class.</para>
-
- <para>Applications must always fill in the
-<structfield>count</structfield>,
-<structfield>which</structfield>,
-<structfield>controls</structfield> and
-<structfield>reserved</structfield> fields of &v4l2-ext-controls;, and
-initialize the &v4l2-ext-control; array pointed to by the
-<structfield>controls</structfield> fields.</para>
-
- <para>To get the current value of a set of controls applications
-initialize the <structfield>id</structfield>,
-<structfield>size</structfield> and <structfield>reserved2</structfield> fields
-of each &v4l2-ext-control; and call the
-<constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
-must also set the <structfield>string</structfield> field. Controls
-of compound types (<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set)
-must set the <structfield>ptr</structfield> field.</para>
-
- <para>If the <structfield>size</structfield> is too small to
-receive the control result (only relevant for pointer-type controls
-like strings), then the driver will set <structfield>size</structfield>
-to a valid value and return an &ENOSPC;. You should re-allocate the
-memory to this new size and try again. For the string type it is possible that
-the same issue occurs again if the string has grown in the meantime. It is
-recommended to call &VIDIOC-QUERYCTRL; first and use
-<structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
-value. It is guaranteed that that is sufficient memory.
-</para>
-
- <para>N-dimensional arrays are set and retrieved row-by-row. You cannot set a partial
-array, all elements have to be set or retrieved. The total size is calculated
-as <structfield>elems</structfield> * <structfield>elem_size</structfield>.
-These values can be obtained by calling &VIDIOC-QUERY-EXT-CTRL;.</para>
-
- <para>To change the value of a set of controls applications
-initialize the <structfield>id</structfield>, <structfield>size</structfield>,
-<structfield>reserved2</structfield> and
-<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
-call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
-will only be set if <emphasis>all</emphasis> control values are
-valid.</para>
-
- <para>To check if a set of controls have correct values applications
-initialize the <structfield>id</structfield>, <structfield>size</structfield>,
-<structfield>reserved2</structfield> and
-<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
-call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
-the driver whether wrong values are automatically adjusted to a valid
-value or if an error is returned.</para>
-
- <para>When the <structfield>id</structfield> or
-<structfield>which</structfield> is invalid drivers return an
-&EINVAL;. When the value is out of bounds drivers can choose to take
-the closest valid value or return an &ERANGE;, whatever seems more
-appropriate. In the first case the new value is set in
-&v4l2-ext-control;. If the new control value is inappropriate (e.g. the
-given menu index is not supported by the menu control), then this will
-also result in an &EINVAL; error.</para>
-
- <para>The driver will only set/get these controls if all control
-values are correct. This prevents the situation where only some of the
-controls were set/get. Only low-level errors (&eg; a failed i2c
-command) can still cause this situation.</para>
-
- <table pgwide="1" frame="none" id="v4l2-ext-control">
- <title>struct <structname>v4l2_ext_control</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry></entry>
- <entry>Identifies the control, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>size</structfield></entry>
- <entry></entry>
- <entry>The total size in bytes of the payload of this
-control. This is normally 0, but for pointer controls this should be
-set to the size of the memory containing the payload, or that will
-receive the payload. If <constant>VIDIOC_G_EXT_CTRLS</constant> finds
-that this value is less than is required to store
-the payload result, then it is set to a value large enough to store the
-payload result and ENOSPC is returned. Note that for string controls
-this <structfield>size</structfield> field should not be confused with the length of the string.
-This field refers to the size of the memory that contains the string.
-The actual <emphasis>length</emphasis> of the string may well be much smaller.
-</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved2</structfield>[1]</entry>
- <entry></entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__s32</entry>
- <entry><structfield>value</structfield></entry>
- <entry>New value or current value. Valid if this control is not of
-type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
-<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__s64</entry>
- <entry><structfield>value64</structfield></entry>
- <entry>New value or current value. Valid if this control is of
-type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
-<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>char *</entry>
- <entry><structfield>string</structfield></entry>
- <entry>A pointer to a string. Valid if this control is of
-type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8 *</entry>
- <entry><structfield>p_u8</structfield></entry>
- <entry>A pointer to a matrix control of unsigned 8-bit values.
-Valid if this control is of type <constant>V4L2_CTRL_TYPE_U8</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u16 *</entry>
- <entry><structfield>p_u16</structfield></entry>
- <entry>A pointer to a matrix control of unsigned 16-bit values.
-Valid if this control is of type <constant>V4L2_CTRL_TYPE_U16</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32 *</entry>
- <entry><structfield>p_u32</structfield></entry>
- <entry>A pointer to a matrix control of unsigned 32-bit values.
-Valid if this control is of type <constant>V4L2_CTRL_TYPE_U32</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>void *</entry>
- <entry><structfield>ptr</structfield></entry>
- <entry>A pointer to a compound type which can be an N-dimensional array and/or a
-compound type (the control's type is >= <constant>V4L2_CTRL_COMPOUND_TYPES</constant>).
-Valid if <constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set for this control.
-</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-ext-controls">
- <title>struct <structname>v4l2_ext_controls</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>union</entry>
- <entry>(anonymous)</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>ctrl_class</structfield></entry>
- <entry>The control class to which all controls belong, see
-<xref linkend="ctrl-class" />. Drivers that use a kernel framework for handling
-controls will also accept a value of 0 here, meaning that the controls can
-belong to any control class. Whether drivers support this can be tested by setting
-<structfield>ctrl_class</structfield> to 0 and calling <constant>VIDIOC_TRY_EXT_CTRLS</constant>
-with a <structfield>count</structfield> of 0. If that succeeds, then the driver
-supports this feature.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry><para>Which value of the control to get/set/try. <constant>V4L2_CTRL_WHICH_CUR_VAL</constant>
-will return the current value of the control and <constant>V4L2_CTRL_WHICH_DEF_VAL</constant> will
-return the default value of the control. Please note that you can only get the default value of the
-control, you cannot set or try it.</para>
-<para>For backwards compatibility you can also use a control class here (see
-<xref linkend="ctrl-class" />). In that case all controls have to belong to that
-control class. This usage is deprecated, instead just use <constant>V4L2_CTRL_WHICH_CUR_VAL</constant>.
-There are some very old drivers that do not yet support <constant>V4L2_CTRL_WHICH_CUR_VAL</constant>
-and that require a control class here. You can test for such drivers by setting ctrl_class to
-<constant>V4L2_CTRL_WHICH_CUR_VAL</constant> and calling VIDIOC_TRY_EXT_CTRLS with a count of 0.
-If that fails, then the driver does not support <constant>V4L2_CTRL_WHICH_CUR_VAL</constant>.</para>
-</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>count</structfield></entry>
- <entry>The number of controls in the controls array. May
-also be zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>error_idx</structfield></entry>
- <entry><para>Set by the driver in case of an error. If the error is
-associated with a particular control, then <structfield>error_idx</structfield>
-is set to the index of that control. If the error is not related to a specific
-control, or the validation step failed (see below), then
-<structfield>error_idx</structfield> is set to <structfield>count</structfield>.
-The value is undefined if the ioctl returned 0 (success).</para>
-
-<para>Before controls are read from/written to hardware a validation step
-takes place: this checks if all controls in the list are valid controls,
-if no attempt is made to write to a read-only control or read from a write-only
-control, and any other up-front checks that can be done without accessing the
-hardware. The exact validations done during this step are driver dependent
-since some checks might require hardware access for some devices, thus making
-it impossible to do those checks up-front. However, drivers should make a
-best-effort to do as many up-front checks as possible.</para>
-
-<para>This check is done to avoid leaving the hardware in an inconsistent state due
-to easy-to-avoid problems. But it leads to another problem: the application needs to
-know whether an error came from the validation step (meaning that the hardware
-was not touched) or from an error during the actual reading from/writing to hardware.</para>
-
-<para>The, in hindsight quite poor, solution for that is to set <structfield>error_idx</structfield>
-to <structfield>count</structfield> if the validation failed. This has the
-unfortunate side-effect that it is not possible to see which control failed the
-validation. If the validation was successful and the error happened while
-accessing the hardware, then <structfield>error_idx</structfield> is less than
-<structfield>count</structfield> and only the controls up to
-<structfield>error_idx-1</structfield> were read or written correctly, and the
-state of the remaining controls is undefined.</para>
-
-<para>Since <constant>VIDIOC_TRY_EXT_CTRLS</constant> does not access hardware
-there is also no need to handle the validation step in this special way,
-so <structfield>error_idx</structfield> will just be set to the control that
-failed the validation step instead of to <structfield>count</structfield>.
-This means that if <constant>VIDIOC_S_EXT_CTRLS</constant> fails with
-<structfield>error_idx</structfield> set to <structfield>count</structfield>,
-then you can call <constant>VIDIOC_TRY_EXT_CTRLS</constant> to try to discover
-the actual control that failed the validation step. Unfortunately, there
-is no <constant>TRY</constant> equivalent for <constant>VIDIOC_G_EXT_CTRLS</constant>.
-</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- <row>
- <entry>&v4l2-ext-control; *</entry>
- <entry><structfield>controls</structfield></entry>
- <entry>Pointer to an array of
-<structfield>count</structfield> v4l2_ext_control structures. Ignored
-if <structfield>count</structfield> equals zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="ctrl-class">
- <title>Control classes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CTRL_CLASS_USER</constant></entry>
- <entry>0x980000</entry>
- <entry>The class containing user controls. These controls
-are described in <xref linkend="control" />. All controls that can be set
-using the &VIDIOC-S-CTRL; and &VIDIOC-G-CTRL; ioctl belong to this
-class.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_MPEG</constant></entry>
- <entry>0x990000</entry>
- <entry>The class containing MPEG compression controls.
-These controls are described in <xref
- linkend="mpeg-controls" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_CAMERA</constant></entry>
- <entry>0x9a0000</entry>
- <entry>The class containing camera controls.
-These controls are described in <xref
- linkend="camera-controls" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_FM_TX</constant></entry>
- <entry>0x9b0000</entry>
- <entry>The class containing FM Transmitter (FM TX) controls.
-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>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_JPEG</constant></entry>
- <entry>0x9d0000</entry>
- <entry>The class containing JPEG compression controls.
-These controls are described in <xref
- linkend="jpeg-controls" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_IMAGE_SOURCE</constant></entry>
- <entry>0x9e0000</entry> <entry>The class containing image
- source controls. These controls are described in <xref
- linkend="image-source-controls" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_IMAGE_PROC</constant></entry>
- <entry>0x9f0000</entry> <entry>The class containing image
- processing controls. These controls are described in <xref
- linkend="image-process-controls" />.</entry>
- </row>
-
- <row>
- <entry><constant>V4L2_CTRL_CLASS_FM_RX</constant></entry>
- <entry>0xa10000</entry>
- <entry>The class containing FM Receiver (FM RX) controls.
-These controls are described in <xref
- linkend="fm-rx-controls" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_CLASS_RF_TUNER</constant></entry>
- <entry>0xa20000</entry>
- <entry>The class containing RF tuner controls.
-These controls are described in <xref linkend="rf-tuner-controls" />.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-ext-control; <structfield>id</structfield>
-is invalid, the &v4l2-ext-controls;
-<structfield>which</structfield> is invalid, or the &v4l2-ext-control;
-<structfield>value</structfield> was inappropriate (e.g. the given menu
-index is not supported by the driver). This error code is
-also returned by the <constant>VIDIOC_S_EXT_CTRLS</constant> and
-<constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctls if two or more
-control values are in conflict.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ERANGE</errorcode></term>
- <listitem>
- <para>The &v4l2-ext-control; <structfield>value</structfield>
-is out of bounds.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The control is temporarily not changeable, possibly
-because another applications took over control of the device function
-this control belongs to.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOSPC</errorcode></term>
- <listitem>
- <para>The space reserved for the control's payload is insufficient.
-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>
-
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
deleted file mode 100644
index 77607cc19688..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
+++ /dev/null
@@ -1,459 +0,0 @@
-<refentry id="vidioc-g-fbuf">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_FBUF, VIDIOC_S_FBUF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_FBUF</refname>
- <refname>VIDIOC_S_FBUF</refname>
- <refpurpose>Get or set frame buffer overlay parameters</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_framebuffer *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_framebuffer *<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_G_FBUF, VIDIOC_S_FBUF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Applications can use the <constant>VIDIOC_G_FBUF</constant> and
-<constant>VIDIOC_S_FBUF</constant> ioctl to get and set the
-framebuffer parameters for a <link linkend="overlay">Video
-Overlay</link> or <link linkend="osd">Video Output Overlay</link>
-(OSD). The type of overlay is implied by the device type (capture or
-output device) and can be determined with the &VIDIOC-QUERYCAP; ioctl.
-One <filename>/dev/videoN</filename> device must not support both
-kinds of overlay.</para>
-
- <para>The V4L2 API distinguishes destructive and non-destructive
-overlays. A destructive overlay copies captured video images into the
-video memory of a graphics card. A non-destructive overlay blends
-video images into a VGA signal or graphics into a video signal.
-<wordasword>Video Output Overlays</wordasword> are always
-non-destructive.</para>
-
- <para>To get the current parameters applications call the
-<constant>VIDIOC_G_FBUF</constant> ioctl with a pointer to a
-<structname>v4l2_framebuffer</structname> structure. The driver fills
-all fields of the structure or returns an &EINVAL; when overlays are
-not supported.</para>
-
- <para>To set the parameters for a <wordasword>Video Output
-Overlay</wordasword>, applications must initialize the
-<structfield>flags</structfield> field of a struct
-<structname>v4l2_framebuffer</structname>. Since the framebuffer is
-implemented on the TV card all other parameters are determined by the
-driver. When an application calls <constant>VIDIOC_S_FBUF</constant>
-with a pointer to this structure, the driver prepares for the overlay
-and returns the framebuffer parameters as
-<constant>VIDIOC_G_FBUF</constant> does, or it returns an error
-code.</para>
-
- <para>To set the parameters for a <wordasword>non-destructive
-Video Overlay</wordasword>, applications must initialize the
-<structfield>flags</structfield> field, the
-<structfield>fmt</structfield> substructure, and call
-<constant>VIDIOC_S_FBUF</constant>. Again the driver prepares for the
-overlay and returns the framebuffer parameters as
-<constant>VIDIOC_G_FBUF</constant> does, or it returns an error
-code.</para>
-
- <para>For a <wordasword>destructive Video Overlay</wordasword>
-applications must additionally provide a
-<structfield>base</structfield> address. Setting up a DMA to a
-random memory location can jeopardize the system security, its
-stability or even damage the hardware, therefore only the superuser
-can set the parameters for a destructive video overlay.</para>
-
- <!-- NB v4l2_pix_format is also specified in pixfmt.sgml.-->
-
- <table pgwide="1" frame="none" id="v4l2-framebuffer">
- <title>struct <structname>v4l2_framebuffer</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry></entry>
- <entry>Overlay capability flags set by the driver, see
-<xref linkend="framebuffer-cap" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry></entry>
- <entry>Overlay control flags set by application and
-driver, see <xref linkend="framebuffer-flags" /></entry>
- </row>
- <row>
- <entry>void *</entry>
- <entry><structfield>base</structfield></entry>
- <entry></entry>
- <entry>Physical base address of the framebuffer,
-that is the address of the pixel in the top left corner of the
-framebuffer.<footnote><para>A physical base address may not suit all
-platforms. GK notes in theory we should pass something like PCI device
-+ memory region + offset instead. If you encounter problems please
-discuss on the linux-media mailing list: &v4l-ml;.</para></footnote></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>This field is irrelevant to
-<wordasword>non-destructive Video Overlays</wordasword>. For
-<wordasword>destructive Video Overlays</wordasword> applications must
-provide a base address. The driver may accept only base addresses
-which are a multiple of two, four or eight bytes. For
-<wordasword>Video Output Overlays</wordasword> the driver must return
-a valid base address, so applications can find the corresponding Linux
-framebuffer device (see <xref linkend="osd" />).</entry>
- </row>
- <row>
- <entry>struct</entry>
- <entry><structfield>fmt</structfield></entry>
- <entry></entry>
- <entry>Layout of the frame buffer.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Width of the frame buffer in pixels.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Height of the frame buffer in pixels.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>pixelformat</structfield></entry>
- <entry>The pixel format of the
-framebuffer.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>For <wordasword>non-destructive Video
-Overlays</wordasword> this field only defines a format for the
-&v4l2-window; <structfield>chromakey</structfield> field.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>For <wordasword>destructive Video
-Overlays</wordasword> applications must initialize this field. For
-<wordasword>Video Output Overlays</wordasword> the driver must return
-a valid format.</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- <entry>Usually this is an RGB format (for example
-<link linkend="V4L2-PIX-FMT-RGB565"><constant>V4L2_PIX_FMT_RGB565</constant></link>)
-but YUV formats (only packed YUV formats when chroma keying is used,
-not including <constant>V4L2_PIX_FMT_YUYV</constant> and
-<constant>V4L2_PIX_FMT_UYVY</constant>) and the
-<constant>V4L2_PIX_FMT_PAL8</constant> format are also permitted. The
-behavior of the driver when an application requests a compressed
-format is undefined. See <xref linkend="pixfmt" /> for information on
-pixel formats.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-field;</entry>
- <entry><structfield>field</structfield></entry>
- <entry>Drivers and applications shall ignore this field.
-If applicable, the field order is selected with the &VIDIOC-S-FMT;
-ioctl, using the <structfield>field</structfield> field of
-&v4l2-window;.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>bytesperline</structfield></entry>
- <entry>Distance in bytes between the leftmost pixels in
-two adjacent lines.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>This field is irrelevant to
-<wordasword>non-destructive Video
-Overlays</wordasword>.</para><para>For <wordasword>destructive Video
-Overlays</wordasword> both applications and drivers can set this field
-to request padding bytes at the end of each line. Drivers however may
-ignore the requested value, returning <structfield>width</structfield>
-times bytes-per-pixel or a larger value required by the hardware. That
-implies applications can just set this field to zero to get a
-reasonable default.</para><para>For <wordasword>Video Output
-Overlays</wordasword> the driver must return a valid
-value.</para><para>Video hardware may access padding bytes, therefore
-they must reside in accessible memory. Consider for example the case
-where padding bytes after the last line of an image cross a system
-page boundary. Capture devices may write padding bytes, the value is
-undefined. Output devices ignore the contents of padding
-bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the first
-plane and is divided by the same factor as the
-<structfield>width</structfield> field for the other planes. For
-example the Cb and Cr planes of a YUV 4:2:0 image have half as many
-padding bytes following each line as the Y plane. To avoid ambiguities
-drivers must return a <structfield>bytesperline</structfield> value
-rounded up to a multiple of the scale factor.</para></entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>sizeimage</structfield></entry>
- <entry><para>This field is irrelevant to
-<wordasword>non-destructive Video Overlays</wordasword>. For
-<wordasword>destructive Video Overlays</wordasword> applications must
-initialize this field. For <wordasword>Video Output
-Overlays</wordasword> the driver must return a valid
-format.</para><para>Together with <structfield>base</structfield> it
-defines the framebuffer memory accessible by the
-driver.</para></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-colorspace;</entry>
- <entry><structfield>colorspace</structfield></entry>
- <entry>This information supplements the
-<structfield>pixelformat</structfield> and must be set by the driver,
-see <xref linkend="colorspaces" />.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u32</entry>
- <entry><structfield>priv</structfield></entry>
- <entry>Reserved. Drivers and applications must set this field to
-zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="framebuffer-cap">
- <title>Frame Buffer Capability Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FBUF_CAP_EXTERNOVERLAY</constant></entry>
- <entry>0x0001</entry>
- <entry>The device is capable of non-destructive overlays.
-When the driver clears this flag, only destructive overlays are
-supported. There are no drivers yet which support both destructive and
-non-destructive overlays. Video Output Overlays are in practice always
-non-destructive.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_CHROMAKEY</constant></entry>
- <entry>0x0002</entry>
- <entry>The device supports clipping by chroma-keying the
-images. That is, image pixels replace pixels in the VGA or video
-signal only where the latter assume a certain color. Chroma-keying
-makes no sense for destructive overlays.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_LIST_CLIPPING</constant></entry>
- <entry>0x0004</entry>
- <entry>The device supports clipping using a list of clip
-rectangles.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_BITMAP_CLIPPING</constant></entry>
- <entry>0x0008</entry>
- <entry>The device supports clipping using a bit mask.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_LOCAL_ALPHA</constant></entry>
- <entry>0x0010</entry>
- <entry>The device supports clipping/blending using the
-alpha channel of the framebuffer or VGA signal. Alpha blending makes
-no sense for destructive overlays.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_GLOBAL_ALPHA</constant></entry>
- <entry>0x0020</entry>
- <entry>The device supports alpha blending using a global
-alpha value. Alpha blending makes no sense for destructive overlays.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_LOCAL_INV_ALPHA</constant></entry>
- <entry>0x0040</entry>
- <entry>The device supports clipping/blending using the
-inverted alpha channel of the framebuffer or VGA signal. Alpha
-blending makes no sense for destructive overlays.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_CAP_SRC_CHROMAKEY</constant></entry>
- <entry>0x0080</entry>
- <entry>The device supports Source Chroma-keying. Video pixels
-with the chroma-key colors are replaced by framebuffer pixels, which is exactly opposite of
-<constant>V4L2_FBUF_CAP_CHROMAKEY</constant></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="framebuffer-flags">
- <title>Frame Buffer Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_FBUF_FLAG_PRIMARY</constant></entry>
- <entry>0x0001</entry>
- <entry>The framebuffer is the primary graphics surface.
-In other words, the overlay is destructive. This flag is typically set by any
-driver that doesn't have the <constant>V4L2_FBUF_CAP_EXTERNOVERLAY</constant>
-capability and it is cleared otherwise.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_OVERLAY</constant></entry>
- <entry>0x0002</entry>
- <entry>If this flag is set for a video capture device, then the
-driver will set the initial overlay size to cover the full framebuffer size,
-otherwise the existing overlay size (as set by &VIDIOC-S-FMT;) will be used.
-
-Only one video capture driver (bttv) supports this flag. The use of this flag
-for capture devices is deprecated. There is no way to detect which drivers
-support this flag, so the only reliable method of setting the overlay size is
-through &VIDIOC-S-FMT;.
-
-If this flag is set for a video output device, then the video output overlay
-window is relative to the top-left corner of the framebuffer and restricted
-to the size of the framebuffer. If it is cleared, then the video output
-overlay window is relative to the video output display.
- </entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_CHROMAKEY</constant></entry>
- <entry>0x0004</entry>
- <entry>Use chroma-keying. The chroma-key color is
-determined by the <structfield>chromakey</structfield> field of
-&v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see <xref
- linkend="overlay" />
-and
- <xref linkend="osd" />.</entry>
- </row>
- <row>
- <entry spanname="hspan">There are no flags to enable
-clipping using a list of clip rectangles or a bitmap. These methods
-are negotiated with the &VIDIOC-S-FMT; ioctl, see <xref
- linkend="overlay" /> and <xref linkend="osd" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_LOCAL_ALPHA</constant></entry>
- <entry>0x0008</entry>
- <entry>Use the alpha channel of the framebuffer to clip or
-blend framebuffer pixels with video images. The blend
-function is: output = framebuffer pixel * alpha + video pixel * (1 -
-alpha). The actual alpha depth depends on the framebuffer pixel
-format.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_GLOBAL_ALPHA</constant></entry>
- <entry>0x0010</entry>
- <entry>Use a global alpha value to blend the framebuffer
-with video images. The blend function is: output = (framebuffer pixel
-* alpha + video pixel * (255 - alpha)) / 255. The alpha value is
-determined by the <structfield>global_alpha</structfield> field of
-&v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see <xref
- linkend="overlay" />
-and <xref linkend="osd" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_LOCAL_INV_ALPHA</constant></entry>
- <entry>0x0020</entry>
- <entry>Like
-<constant>V4L2_FBUF_FLAG_LOCAL_ALPHA</constant>, use the alpha channel
-of the framebuffer to clip or blend framebuffer pixels with video
-images, but with an inverted alpha value. The blend function is:
-output = framebuffer pixel * (1 - alpha) + video pixel * alpha. The
-actual alpha depth depends on the framebuffer pixel format.</entry>
- </row>
- <row>
- <entry><constant>V4L2_FBUF_FLAG_SRC_CHROMAKEY</constant></entry>
- <entry>0x0040</entry>
- <entry>Use source chroma-keying. The source chroma-key color is
-determined by the <structfield>chromakey</structfield> field of
-&v4l2-window; and negotiated with the &VIDIOC-S-FMT; ioctl, see <xref
-linkend="overlay" /> and <xref linkend="osd" />.
-Both chroma-keying are mutual exclusive to each other, so same
-<structfield>chromakey</structfield> field of &v4l2-window; is being used.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EPERM</errorcode></term>
- <listitem>
- <para><constant>VIDIOC_S_FBUF</constant> can only be called
-by a privileged user to negotiate the parameters for a destructive
-overlay.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <constant>VIDIOC_S_FBUF</constant> parameters are unsuitable.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
deleted file mode 100644
index ffcb448251f0..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
+++ /dev/null
@@ -1,204 +0,0 @@
-<refentry id="vidioc-g-fmt">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_FMT, VIDIOC_S_FMT,
-VIDIOC_TRY_FMT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_FMT</refname>
- <refname>VIDIOC_S_FMT</refname>
- <refname>VIDIOC_TRY_FMT</refname>
- <refpurpose>Get or set the data format, try a format</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_format
-*<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_G_FMT, VIDIOC_S_FMT, VIDIOC_TRY_FMT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls are used to negotiate the format of data
-(typically image format) exchanged between driver and
-application.</para>
-
- <para>To query the current parameters applications set the
-<structfield>type</structfield> field of a struct
-<structname>v4l2_format</structname> to the respective buffer (stream)
-type. For example video capture devices use
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. When the application
-calls the <constant>VIDIOC_G_FMT</constant> ioctl with a pointer to
-this structure the driver fills the respective member of the
-<structfield>fmt</structfield> union. In case of video capture devices
-that is either the &v4l2-pix-format; <structfield>pix</structfield> or
-the &v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member.
-When the requested buffer type is not supported drivers return an
-&EINVAL;.</para>
-
- <para>To change the current format parameters applications
-initialize the <structfield>type</structfield> field and all
-fields of the respective <structfield>fmt</structfield>
-union member. For details see the documentation of the various devices
-types in <xref linkend="devices" />. Good practice is to query the
-current parameters first, and to
-modify only those parameters not suitable for the application. When
-the application calls the <constant>VIDIOC_S_FMT</constant> ioctl
-with a pointer to a <structname>v4l2_format</structname> structure
-the driver checks
-and adjusts the parameters against hardware abilities. Drivers
-should not return an error code unless the <structfield>type</structfield> field is invalid, this is
-a mechanism to fathom device capabilities and to approach parameters
-acceptable for both the application and driver. On success the driver
-may program the hardware, allocate resources and generally prepare for
-data exchange.
-Finally the <constant>VIDIOC_S_FMT</constant> ioctl returns the
-current format parameters as <constant>VIDIOC_G_FMT</constant> does.
-Very simple, inflexible devices may even ignore all input and always
-return the default parameters. However all V4L2 devices exchanging
-data with the application must implement the
-<constant>VIDIOC_G_FMT</constant> and
-<constant>VIDIOC_S_FMT</constant> ioctl. When the requested buffer
-type is not supported drivers return an &EINVAL; on a
-<constant>VIDIOC_S_FMT</constant> attempt. When I/O is already in
-progress or the resource is not available for other reasons drivers
-return the &EBUSY;.</para>
-
- <para>The <constant>VIDIOC_TRY_FMT</constant> ioctl is equivalent
-to <constant>VIDIOC_S_FMT</constant> with one exception: it does not
-change driver state. It can also be called at any time, never
-returning <errorcode>EBUSY</errorcode>. This function is provided to
-negotiate parameters, to learn about hardware limitations, without
-disabling I/O or possibly time consuming hardware preparations.
-Although strongly recommended drivers are not required to implement
-this ioctl.</para>
-
- <para>The format as returned by <constant>VIDIOC_TRY_FMT</constant>
-must be identical to what <constant>VIDIOC_S_FMT</constant> returns for
-the same input or output.</para>
-
- <table pgwide="1" frame="none" id="v4l2-format">
- <title>struct <structname>v4l2_format</structname></title>
- <tgroup cols="4">
- <colspec colname="c1" />
- <colspec colname="c2" />
- <colspec colname="c3" />
- <colspec colname="c4" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>Type of the data stream, see <xref
- linkend="v4l2-buf-type" />.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield>fmt</structfield></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-pix-format;</entry>
- <entry><structfield>pix</structfield></entry>
- <entry>Definition of an image format, see <xref
- linkend="pixfmt" />, used by video capture and output
-devices.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-pix-format-mplane;</entry>
- <entry><structfield>pix_mp</structfield></entry>
- <entry>Definition of an image format, see <xref
- linkend="pixfmt" />, used by video capture and output
-devices that support the <link linkend="planar-apis">multi-planar
-version of the API</link>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-window;</entry>
- <entry><structfield>win</structfield></entry>
- <entry>Definition of an overlaid image, see <xref
- linkend="overlay" />, used by video overlay devices.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-vbi-format;</entry>
- <entry><structfield>vbi</structfield></entry>
- <entry>Raw VBI capture or output parameters. This is
-discussed in more detail in <xref linkend="raw-vbi" />. Used by raw VBI
-capture and output devices.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-sliced-vbi-format;</entry>
- <entry><structfield>sliced</structfield></entry>
- <entry>Sliced VBI capture or output parameters. See
-<xref linkend="sliced" /> for details. Used by sliced VBI
-capture and output devices.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-sdr-format;</entry>
- <entry><structfield>sdr</structfield></entry>
- <entry>Definition of a data format, see
-<xref linkend="pixfmt" />, used by SDR capture and output devices.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8</entry>
- <entry><structfield>raw_data</structfield>[200]</entry>
- <entry>Place holder for future extensions.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-format; <structfield>type</structfield>
-field is invalid or the requested buffer type not supported.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml b/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
deleted file mode 100644
index d1034fb61d15..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-frequency.xml
+++ /dev/null
@@ -1,148 +0,0 @@
-<refentry id="vidioc-g-frequency">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_FREQUENCY, VIDIOC_S_FREQUENCY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_FREQUENCY</refname>
- <refname>VIDIOC_S_FREQUENCY</refname>
- <refpurpose>Get or set tuner or modulator radio
-frequency</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_frequency
-*<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_frequency
-*<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_G_FREQUENCY, VIDIOC_S_FREQUENCY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To get the current tuner or modulator radio frequency
-applications set the <structfield>tuner</structfield> field of a
-&v4l2-frequency; to the respective tuner or modulator number (only
-input devices have tuners, only output devices have modulators), zero
-out the <structfield>reserved</structfield> array and
-call the <constant>VIDIOC_G_FREQUENCY</constant> ioctl with a pointer
-to this structure. The driver stores the current frequency in the
-<structfield>frequency</structfield> field.</para>
-
- <para>To change the current tuner or modulator radio frequency
-applications initialize the <structfield>tuner</structfield>,
-<structfield>type</structfield> and
-<structfield>frequency</structfield> fields, and the
-<structfield>reserved</structfield> array of a &v4l2-frequency; and
-call the <constant>VIDIOC_S_FREQUENCY</constant> ioctl with a pointer
-to this structure. When the requested frequency is not possible the
-driver assumes the closest possible value. However
-<constant>VIDIOC_S_FREQUENCY</constant> is a write-only ioctl, it does
-not return the actual new frequency.</para>
-
- <table pgwide="1" frame="none" id="v4l2-frequency">
- <title>struct <structname>v4l2_frequency</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>tuner</structfield></entry>
- <entry>The tuner or modulator index number. This is the
-same value as in the &v4l2-input; <structfield>tuner</structfield>
-field and the &v4l2-tuner; <structfield>index</structfield> field, or
-the &v4l2-output; <structfield>modulator</structfield> field and the
-&v4l2-modulator; <structfield>index</structfield> field.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>The tuner type. This is the same value as in the
-&v4l2-tuner; <structfield>type</structfield> field. The type must be set
-to <constant>V4L2_TUNER_RADIO</constant> for <filename>/dev/radioX</filename>
-device nodes, and to <constant>V4L2_TUNER_ANALOG_TV</constant>
-for all others. Set this field to <constant>V4L2_TUNER_RADIO</constant> for
-modulators (currently only radio modulators are supported).
-See <xref linkend="v4l2-tuner-type" /></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>frequency</structfield></entry>
- <entry>Tuning frequency in units of 62.5 kHz, or if the
-&v4l2-tuner; or &v4l2-modulator; <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz. A 1 Hz unit is used when the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Drivers and
- applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>tuner</structfield> index is out of
-bounds or the value in the <structfield>type</structfield> field is
-wrong.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>A hardware seek is in progress.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-input.xml b/Documentation/DocBook/media/v4l/vidioc-g-input.xml
deleted file mode 100644
index 1d43065090dd..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-input.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<refentry id="vidioc-g-input">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_INPUT, VIDIOC_S_INPUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_INPUT</refname>
- <refname>VIDIOC_S_INPUT</refname>
- <refpurpose>Query or select the current video input</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>int *<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_G_INPUT, VIDIOC_S_INPUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the current video input applications call the
-<constant>VIDIOC_G_INPUT</constant> ioctl with a pointer to an integer
-where the driver stores the number of the input, as in the
-&v4l2-input; <structfield>index</structfield> field. This ioctl will
-fail only when there are no video inputs, returning
-<errorcode>EINVAL</errorcode>.</para>
-
- <para>To select a video input applications store the number of the
-desired input in an integer and call the
-<constant>VIDIOC_S_INPUT</constant> ioctl with a pointer to this
-integer. Side effects are possible. For example inputs may support
-different video standards, so the driver may implicitly switch the
-current standard. Because of these possible side effects applications
-must select an input before querying or negotiating any other parameters.</para>
-
- <para>Information about video inputs is available using the
-&VIDIOC-ENUMINPUT; ioctl.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The number of the video input is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml b/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
deleted file mode 100644
index 098ff483802e..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-jpegcomp.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-<refentry id="vidioc-g-jpegcomp">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_JPEGCOMP, VIDIOC_S_JPEGCOMP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_JPEGCOMP</refname>
- <refname>VIDIOC_S_JPEGCOMP</refname>
- <refpurpose></refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>v4l2_jpegcompression *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const v4l2_jpegcompression *<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_G_JPEGCOMP, VIDIOC_S_JPEGCOMP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls are <emphasis role="bold">deprecated</emphasis>.
- New drivers and applications should use <link linkend="jpeg-controls">
- JPEG class controls</link> for image quality and JPEG markers control.
- </para>
-
- <para>[to do]</para>
-
- <para>Ronald Bultje elaborates:</para>
-
- <!-- See video4linux-list@redhat.com on 16 Oct 2002, subject
-"Re: [V4L] Re: v4l2 api / Zoran v4l2_jpegcompression" -->
-
- <para>APP is some application-specific information. The
-application can set it itself, and it'll be stored in the JPEG-encoded
-fields (eg; interlacing information for in an AVI or so). COM is the
-same, but it's comments, like 'encoded by me' or so.</para>
-
- <para>jpeg_markers describes whether the huffman tables,
-quantization tables and the restart interval information (all
-JPEG-specific stuff) should be stored in the JPEG-encoded fields.
-These define how the JPEG field is encoded. If you omit them,
-applications assume you've used standard encoding. You usually do want
-to add them.</para>
-
- <!-- NB VIDIOC_S_JPEGCOMP is w/o. -->
-
- <table pgwide="1" frame="none" id="v4l2-jpegcompression">
- <title>struct <structname>v4l2_jpegcompression</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>int</entry>
- <entry><structfield>quality</structfield></entry>
- <entry>Deprecated. If <link linkend="jpeg-quality-control"><constant>
- V4L2_CID_JPEG_COMPRESSION_QUALITY</constant></link> control is exposed
- by a driver applications should use it instead and ignore this field.
- </entry>
- </row>
- <row>
- <entry>int</entry>
- <entry><structfield>APPn</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>int</entry>
- <entry><structfield>APP_len</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>APP_data</structfield>[60]</entry>
- <entry></entry>
- </row>
- <row>
- <entry>int</entry>
- <entry><structfield>COM_len</structfield></entry>
- <entry></entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>COM_data</structfield>[60]</entry>
- <entry></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>jpeg_markers</structfield></entry>
- <entry>See <xref linkend="jpeg-markers"/>. Deprecated.
- If <link linkend="jpeg-active-marker-control"><constant>
- V4L2_CID_JPEG_ACTIVE_MARKER</constant></link> control
- is exposed by a driver applications should use it instead
- and ignore this field.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="jpeg-markers">
- <title>JPEG Markers Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_JPEG_MARKER_DHT</constant></entry>
- <entry>(1&lt;&lt;3)</entry>
- <entry>Define Huffman Tables</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_MARKER_DQT</constant></entry>
- <entry>(1&lt;&lt;4)</entry>
- <entry>Define Quantization Tables</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_MARKER_DRI</constant></entry>
- <entry>(1&lt;&lt;5)</entry>
- <entry>Define Restart Interval</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_MARKER_COM</constant></entry>
- <entry>(1&lt;&lt;6)</entry>
- <entry>Comment segment</entry>
- </row>
- <row>
- <entry><constant>V4L2_JPEG_MARKER_APP</constant></entry>
- <entry>(1&lt;&lt;7)</entry>
- <entry>App segment, driver will always use APP0</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml b/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
deleted file mode 100644
index 96e17b344c5d..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-modulator.xml
+++ /dev/null
@@ -1,252 +0,0 @@
-<refentry id="vidioc-g-modulator">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_MODULATOR, VIDIOC_S_MODULATOR</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_MODULATOR</refname>
- <refname>VIDIOC_S_MODULATOR</refname>
- <refpurpose>Get or set modulator attributes</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_modulator
-*<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_modulator
-*<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_G_MODULATOR, VIDIOC_S_MODULATOR</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a modulator applications initialize
-the <structfield>index</structfield> field and zero out the
-<structfield>reserved</structfield> array of a &v4l2-modulator; and
-call the <constant>VIDIOC_G_MODULATOR</constant> ioctl with a pointer
-to this structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all modulators
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <para>Modulators have two writable properties, an audio
-modulation set and the radio frequency. To change the modulated audio
-subprograms, applications initialize the <structfield>index
-</structfield> and <structfield>txsubchans</structfield> fields and the
-<structfield>reserved</structfield> array and call the
-<constant>VIDIOC_S_MODULATOR</constant> ioctl. Drivers may choose a
-different audio modulation if the request cannot be satisfied. However
-this is a write-only ioctl, it does not return the actual audio
-modulation selected.</para>
-
- <para><link linkend="sdr">SDR</link> specific modulator types are
-<constant>V4L2_TUNER_SDR</constant> and <constant>V4L2_TUNER_RF</constant>.
-For SDR devices <structfield>txsubchans</structfield> field must be
-initialized to zero.
-The term 'modulator' means SDR transmitter in this context.</para>
-
- <para>To change the radio frequency the &VIDIOC-S-FREQUENCY; ioctl
-is available.</para>
-
- <table pgwide="1" frame="none" id="v4l2-modulator">
- <title>struct <structname>v4l2_modulator</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Identifies the modulator, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the modulator, a NUL-terminated ASCII
-string. This information is intended for the user.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry>Modulator capability flags. No flags are defined
-for this field, the tuner flags in &v4l2-tuner;
-are used accordingly. The audio flags indicate the ability
-to encode audio subprograms. They will <emphasis>not</emphasis>
-change for example with the current video standard.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangelow</structfield></entry>
- <entry>The lowest tunable frequency in units of 62.5
-KHz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangehigh</structfield></entry>
- <entry>The highest tunable frequency in units of 62.5
-KHz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>txsubchans</structfield></entry>
- <entry>With this field applications can determine how
-audio sub-carriers shall be modulated. It contains a set of flags as
-defined in <xref linkend="modulator-txsubchans" />. Note the tuner
-<structfield>rxsubchans</structfield> flags are reused, but the
-semantics are different. Video output devices are assumed to have an
-analog or PCM audio input with 1-3 channels. The
-<structfield>txsubchans</structfield> flags select one or more
-channels for modulation, together with some audio subprogram
-indicator, for example a stereo pilot tone.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry spanname="hspan">Type of the modulator, see <xref
- linkend="v4l2-tuner-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[3]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="modulator-txsubchans">
- <title>Modulator Audio Transmission Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TUNER_SUB_MONO</constant></entry>
- <entry>0x0001</entry>
- <entry>Modulate channel 1 as mono audio, when the input
-has more channels, a down-mix of channel 1 and 2. This flag does not
-combine with <constant>V4L2_TUNER_SUB_STEREO</constant> or
-<constant>V4L2_TUNER_SUB_LANG1</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_STEREO</constant></entry>
- <entry>0x0002</entry>
- <entry>Modulate channel 1 and 2 as left and right
-channel of a stereo audio signal. When the input has only one channel
-or two channels and <constant>V4L2_TUNER_SUB_SAP</constant> is also
-set, channel 1 is encoded as left and right channel. This flag does
-not combine with <constant>V4L2_TUNER_SUB_MONO</constant> or
-<constant>V4L2_TUNER_SUB_LANG1</constant>. When the driver does not
-support stereo audio it shall fall back to mono.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_LANG1</constant></entry>
- <entry>0x0008</entry>
- <entry>Modulate channel 1 and 2 as primary and secondary
-language of a bilingual audio signal. When the input has only one
-channel it is used for both languages. It is not possible to encode
-the primary or secondary language only. This flag does not combine
-with <constant>V4L2_TUNER_SUB_MONO</constant>,
-<constant>V4L2_TUNER_SUB_STEREO</constant> or
-<constant>V4L2_TUNER_SUB_SAP</constant>. If the hardware does not
-support the respective audio matrix, or the current video standard
-does not permit bilingual audio the
-<constant>VIDIOC_S_MODULATOR</constant> ioctl shall return an &EINVAL;
-and the driver shall fall back to mono or stereo mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_LANG2</constant></entry>
- <entry>0x0004</entry>
- <entry>Same effect as
-<constant>V4L2_TUNER_SUB_SAP</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_SAP</constant></entry>
- <entry>0x0004</entry>
- <entry>When combined with <constant>V4L2_TUNER_SUB_MONO
-</constant> the first channel is encoded as mono audio, the last
-channel as Second Audio Program. When the input has only one channel
-it is used for both audio tracks. When the input has three channels
-the mono track is a down-mix of channel 1 and 2. When combined with
-<constant>V4L2_TUNER_SUB_STEREO</constant> channel 1 and 2 are
-encoded as left and right stereo audio, channel 3 as Second Audio
-Program. When the input has only two channels, the first is encoded as
-left and right channel and the second as SAP. When the input has only
-one channel it is used for all audio tracks. It is not possible to
-encode a Second Audio Program only. This flag must combine with
-<constant>V4L2_TUNER_SUB_MONO</constant> or
-<constant>V4L2_TUNER_SUB_STEREO</constant>. If the hardware does not
-support the respective audio matrix, or the current video standard
-does not permit SAP the <constant>VIDIOC_S_MODULATOR</constant> ioctl
-shall return an &EINVAL; and driver shall fall back to mono or stereo
-mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_RDS</constant></entry>
- <entry>0x0010</entry>
- <entry>Enable the RDS encoder for a radio FM transmitter.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-modulator;
-<structfield>index</structfield> is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-output.xml b/Documentation/DocBook/media/v4l/vidioc-g-output.xml
deleted file mode 100644
index 4533068ecb8a..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-output.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<refentry id="vidioc-g-output">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_OUTPUT, VIDIOC_S_OUTPUT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_OUTPUT</refname>
- <refname>VIDIOC_S_OUTPUT</refname>
- <refpurpose>Query or select the current video output</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>int *<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_G_OUTPUT, VIDIOC_S_OUTPUT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the current video output applications call the
-<constant>VIDIOC_G_OUTPUT</constant> ioctl with a pointer to an integer
-where the driver stores the number of the output, as in the
-&v4l2-output; <structfield>index</structfield> field. This ioctl
-will fail only when there are no video outputs, returning the
-&EINVAL;.</para>
-
- <para>To select a video output applications store the number of the
-desired output in an integer and call the
-<constant>VIDIOC_S_OUTPUT</constant> ioctl with a pointer to this integer.
-Side effects are possible. For example outputs may support different
-video standards, so the driver may implicitly switch the current
-standard.
-standard. Because of these possible side effects applications
-must select an output before querying or negotiating any other parameters.</para>
-
- <para>Information about video outputs is available using the
-&VIDIOC-ENUMOUTPUT; ioctl.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <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.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-parm.xml b/Documentation/DocBook/media/v4l/vidioc-g-parm.xml
deleted file mode 100644
index 721728745407..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-parm.xml
+++ /dev/null
@@ -1,314 +0,0 @@
-<refentry id="vidioc-g-parm">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_PARM, VIDIOC_S_PARM</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_PARM</refname>
- <refname>VIDIOC_S_PARM</refname>
- <refpurpose>Get or set streaming parameters</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>v4l2_streamparm *<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_G_PARM, VIDIOC_S_PARM</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The current video standard determines a nominal number of
-frames per second. If less than this number of frames is to be
-captured or output, applications can request frame skipping or
-duplicating on the driver side. This is especially useful when using
-the <function>read()</function> or <function>write()</function>, which
-are not augmented by timestamps or sequence counters, and to avoid
-unnecessary data copying.</para>
-
- <para>Further these ioctls can be used to determine the number of
-buffers used internally by a driver in read/write mode. For
-implications see the section discussing the &func-read;
-function.</para>
-
- <para>To get and set the streaming parameters applications call
-the <constant>VIDIOC_G_PARM</constant> and
-<constant>VIDIOC_S_PARM</constant> ioctl, respectively. They take a
-pointer to a struct <structname>v4l2_streamparm</structname> which
-contains a union holding separate parameters for input and output
-devices.</para>
-
- <table pgwide="1" frame="none" id="v4l2-streamparm">
- <title>struct <structname>v4l2_streamparm</structname></title>
- <tgroup cols="4">
- &cs-ustr;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry></entry>
- <entry>The buffer (stream) type, same as &v4l2-format;
-<structfield>type</structfield>, set by the application. See <xref
- linkend="v4l2-buf-type" /></entry>
- </row>
- <row>
- <entry>union</entry>
- <entry><structfield>parm</structfield></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-captureparm;</entry>
- <entry><structfield>capture</structfield></entry>
- <entry>Parameters for capture devices, used when
-<structfield>type</structfield> is
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>&v4l2-outputparm;</entry>
- <entry><structfield>output</structfield></entry>
- <entry>Parameters for output devices, used when
-<structfield>type</structfield> is
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8</entry>
- <entry><structfield>raw_data</structfield>[200]</entry>
- <entry>A place holder for future extensions.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-captureparm">
- <title>struct <structname>v4l2_captureparm</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry>See <xref linkend="parm-caps" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capturemode</structfield></entry>
- <entry>Set by drivers and applications, see <xref linkend="parm-flags" />.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>timeperframe</structfield></entry>
- <entry><para>This is the desired period between
-successive frames captured by the driver, in seconds. The
-field is intended to skip frames on the driver side, saving I/O
-bandwidth.</para><para>Applications store here the desired frame
-period, drivers return the actual frame period, which must be greater
-or equal to the nominal frame period determined by the current video
-standard (&v4l2-standard; <structfield>frameperiod</structfield>
-field). Changing the video standard (also implicitly by switching the
-video input) may reset this parameter to the nominal frame period. To
-reset manually applications can just set this field to
-zero.</para><para>Drivers support this function only when they set the
-<constant>V4L2_CAP_TIMEPERFRAME</constant> flag in the
-<structfield>capability</structfield> field.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>extendedmode</structfield></entry>
- <entry>Custom (driver specific) streaming parameters. When
-unused, applications and drivers must set this field to zero.
-Applications using this field should check the driver name and
-version, see <xref linkend="querycap" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>readbuffers</structfield></entry>
- <entry>Applications set this field to the desired number
-of buffers used internally by the driver in &func-read; mode. Drivers
-return the actual number of buffers. When an application requests zero
-buffers, drivers should just return the current setting rather than
-the minimum or an error code. For details see <xref
- linkend="rw" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-outputparm">
- <title>struct <structname>v4l2_outputparm</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry>See <xref linkend="parm-caps" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>outputmode</structfield></entry>
- <entry>Set by drivers and applications, see <xref
- linkend="parm-flags" />.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>timeperframe</structfield></entry>
- <entry>This is the desired period between
-successive frames output by the driver, in seconds.</entry>
- </row>
- <row>
- <entry spanname="hspan"><para>The field is intended to
-repeat frames on the driver side in &func-write; mode (in streaming
-mode timestamps can be used to throttle the output), saving I/O
-bandwidth.</para><para>Applications store here the desired frame
-period, drivers return the actual frame period, which must be greater
-or equal to the nominal frame period determined by the current video
-standard (&v4l2-standard; <structfield>frameperiod</structfield>
-field). Changing the video standard (also implicitly by switching the
-video output) may reset this parameter to the nominal frame period. To
-reset manually applications can just set this field to
-zero.</para><para>Drivers support this function only when they set the
-<constant>V4L2_CAP_TIMEPERFRAME</constant> flag in the
-<structfield>capability</structfield> field.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>extendedmode</structfield></entry>
- <entry>Custom (driver specific) streaming parameters. When
-unused, applications and drivers must set this field to zero.
-Applications using this field should check the driver name and
-version, see <xref linkend="querycap" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>writebuffers</structfield></entry>
- <entry>Applications set this field to the desired number
-of buffers used internally by the driver in
-<function>write()</function> mode. Drivers return the actual number of
-buffers. When an application requests zero buffers, drivers should
-just return the current setting rather than the minimum or an error
-code. For details see <xref linkend="rw" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry>Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="parm-caps">
- <title>Streaming Parameters Capabilites</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CAP_TIMEPERFRAME</constant></entry>
- <entry>0x1000</entry>
- <entry>The frame skipping/repeating controlled by the
-<structfield>timeperframe</structfield> field is supported.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="parm-flags">
- <title>Capture Parameters Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_MODE_HIGHQUALITY</constant></entry>
- <entry>0x0001</entry>
- <entry><para>High quality imaging mode. High quality mode
-is intended for still imaging applications. The idea is to get the
-best possible image quality that the hardware can deliver. It is not
-defined how the driver writer may achieve that; it will depend on the
-hardware and the ingenuity of the driver writer. High quality mode is
-a different mode from the regular motion video capture modes. In
-high quality mode:<itemizedlist>
- <listitem>
- <para>The driver may be able to capture higher
-resolutions than for motion capture.</para>
- </listitem>
- <listitem>
- <para>The driver may support fewer pixel formats
-than motion capture (eg; true color).</para>
- </listitem>
- <listitem>
- <para>The driver may capture and arithmetically
-combine multiple successive fields or frames to remove color edge
-artifacts and reduce the noise in the video data.
-</para>
- </listitem>
- <listitem>
- <para>The driver may capture images in slices like
-a scanner in order to handle larger format images than would otherwise
-be possible. </para>
- </listitem>
- <listitem>
- <para>An image capture operation may be
-significantly slower than motion capture. </para>
- </listitem>
- <listitem>
- <para>Moving objects in the image might have
-excessive motion blur. </para>
- </listitem>
- <listitem>
- <para>Capture might only work through the
-<function>read()</function> call.</para>
- </listitem>
- </itemizedlist></para></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-priority.xml b/Documentation/DocBook/media/v4l/vidioc-g-priority.xml
deleted file mode 100644
index 6a81b4fe9538..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-priority.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<refentry id="vidioc-g-priority">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_PRIORITY, VIDIOC_S_PRIORITY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_PRIORITY</refname>
- <refname>VIDIOC_S_PRIORITY</refname>
- <refpurpose>Query or request the access priority associated with a
-file descriptor</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>enum v4l2_priority *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const enum v4l2_priority *<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_G_PRIORITY, VIDIOC_S_PRIORITY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para>Pointer to an enum v4l2_priority type.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the current access priority
-applications call the <constant>VIDIOC_G_PRIORITY</constant> ioctl
-with a pointer to an enum v4l2_priority variable where the driver stores
-the current priority.</para>
-
- <para>To request an access priority applications store the
-desired priority in an enum v4l2_priority variable and call
-<constant>VIDIOC_S_PRIORITY</constant> ioctl with a pointer to this
-variable.</para>
-
- <table frame="none" pgwide="1" id="v4l2-priority">
- <title>enum v4l2_priority</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_PRIORITY_UNSET</constant></entry>
- <entry>0</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_PRIORITY_BACKGROUND</constant></entry>
- <entry>1</entry>
- <entry>Lowest priority, usually applications running in
-background, for example monitoring VBI transmissions. A proxy
-application running in user space will be necessary if multiple
-applications want to read from a device at this priority.</entry>
- </row>
- <row>
- <entry><constant>V4L2_PRIORITY_INTERACTIVE</constant></entry>
- <entry>2</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_PRIORITY_DEFAULT</constant></entry>
- <entry>2</entry>
- <entry>Medium priority, usually applications started and
-interactively controlled by the user. For example TV viewers, Teletext
-browsers, or just "panel" applications to change the channel or video
-controls. This is the default priority unless an application requests
-another.</entry>
- </row>
- <row>
- <entry><constant>V4L2_PRIORITY_RECORD</constant></entry>
- <entry>3</entry>
- <entry>Highest priority. Only one file descriptor can have
-this priority, it blocks any other fd from changing device properties.
-Usually applications which must not be interrupted, like video
-recording.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The requested priority value is invalid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>Another application already requested higher
-priority.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
deleted file mode 100644
index 997f4e96f297..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ /dev/null
@@ -1,233 +0,0 @@
-<refentry id="vidioc-g-selection">
-
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_SELECTION, VIDIOC_S_SELECTION</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_SELECTION</refname>
- <refname>VIDIOC_S_SELECTION</refname>
- <refpurpose>Get or set one of the selection rectangles</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_selection *<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_G_SELECTION, VIDIOC_S_SELECTION</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The ioctls are used to query and configure selection rectangles.</para>
-
-<para>To query the cropping (composing) rectangle set &v4l2-selection;
-<structfield> type </structfield> field to the respective buffer type.
-Do not use the multiplanar buffer types. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and use
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
-setting the value of &v4l2-selection; <structfield>target</structfield> field
-to <constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
-Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
-for additional targets. The <structfield>flags</structfield> and <structfield>reserved
-</structfield> fields of &v4l2-selection; are ignored and they must be filled
-with zeros. The driver fills the rest of the structure or
-returns &EINVAL; if incorrect buffer type or target was used. If cropping
-(composing) is not supported then the active rectangle is not mutable and it is
-always equal to the bounds rectangle. Finally, the &v4l2-rect;
-<structfield>r</structfield> rectangle is filled with the current cropping
-(composing) coordinates. The coordinates are expressed in driver-dependent
-units. The only exception are rectangles for images in raw formats, whose
-coordinates are always expressed in pixels.</para>
-
-<para>To change the cropping (composing) rectangle set the &v4l2-selection;
-<structfield>type</structfield> field to the respective buffer type. Do not
-use multiplanar buffers. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. Use
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
-setting the value of &v4l2-selection; <structfield>target</structfield> to
-<constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
-Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
-for additional targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
-set to the desired active area. Field &v4l2-selection; <structfield> reserved
-</structfield> is ignored and must be filled with zeros. The driver may adjust
-coordinates of the requested rectangle. An application may
-introduce constraints to control rounding behaviour. The &v4l2-selection;
-<structfield>flags</structfield> field must be set to one of the following:
-
-<itemizedlist>
- <listitem>
-<para><constant>0</constant> - The driver can adjust the rectangle size freely
-and shall choose a crop/compose rectangle as close as possible to the requested
-one.</para>
- </listitem>
- <listitem>
-<para><constant>V4L2_SEL_FLAG_GE</constant> - The driver is not allowed to
-shrink the rectangle. The original rectangle must lay inside the adjusted
-one.</para>
- </listitem>
- <listitem>
-<para><constant>V4L2_SEL_FLAG_LE</constant> - The driver is not allowed to
-enlarge the rectangle. The adjusted rectangle must lay inside the original
-one.</para>
- </listitem>
- <listitem>
-<para><constant>V4L2_SEL_FLAG_GE | V4L2_SEL_FLAG_LE</constant> - The driver
-must choose the size exactly the same as in the requested rectangle.</para>
- </listitem>
-</itemizedlist>
-
-Please refer to <xref linkend="sel-const-adjust" />.
-
-</para>
-
-<para> The driver may have to adjusts the requested dimensions against hardware
-limits and other parts as the pipeline, i.e. the bounds given by the
-capture/output window or TV display. The closest possible values of horizontal
-and vertical offset and sizes are chosen according to following priority:
-
-<orderedlist>
- <listitem>
- <para>Satisfy constraints from &v4l2-selection; <structfield>flags</structfield>.</para>
- </listitem>
- <listitem>
- <para>Adjust width, height, left, and top to hardware limits and alignments.</para>
- </listitem>
- <listitem>
- <para>Keep center of adjusted rectangle as close as possible to the original one.</para>
- </listitem>
- <listitem>
- <para>Keep width and height as close as possible to original ones.</para>
- </listitem>
- <listitem>
- <para>Keep horizontal and vertical offset as close as possible to original ones.</para>
- </listitem>
-</orderedlist>
-
-On success the &v4l2-rect; <structfield>r</structfield> field contains
-the adjusted rectangle. When the parameters are unsuitable the application may
-modify the cropping (composing) or image parameters and repeat the cycle until
-satisfactory parameters have been negotiated. If constraints flags have to be
-violated at then ERANGE is returned. The error indicates that <emphasis>there
-exist no rectangle</emphasis> that satisfies the constraints.</para>
-
- <para>Selection targets and flags are documented in <xref
- linkend="v4l2-selections-common"/>.</para>
-
- <para>
- <figure id="sel-const-adjust">
- <title>Size adjustments with constraint flags.</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="constraints.png" format="PNG" />
- </imageobject>
- <textobject>
- <phrase>Behaviour of rectangle adjustment for different constraint
- flags.</phrase>
- </textobject>
- </mediaobject>
- </figure>
- </para>
-
- <para>
- <table pgwide="1" frame="none" id="v4l2-selection">
- <title>struct <structname>v4l2_selection</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the buffer (from &v4l2-buf-type;).</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>target</structfield></entry>
- <entry>Used to select between <link linkend="v4l2-selections-common"> cropping
- and composing rectangles</link>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags controlling the selection rectangle adjustments, refer to
- <link linkend="v4l2-selection-flags">selection flags</link>.</entry>
- </row>
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>r</structfield></entry>
- <entry>The selection rectangle.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved[9]</structfield></entry>
- <entry>Reserved fields for future use. Drivers and applications must zero this array.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </para>
- </refsect1>
-
- <refsect1>
- &return-value;
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>Given buffer type <structfield>type</structfield> or
-the selection target <structfield>target</structfield> is not supported,
-or the <structfield>flags</structfield> argument is not valid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ERANGE</errorcode></term>
- <listitem>
- <para>It is not possible to adjust &v4l2-rect; <structfield>
-r</structfield> rectangle to satisfy all constraints given in the
-<structfield>flags</structfield> argument.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>It is not possible to apply change of the selection rectangle
-at the moment. Usually because streaming is in progress.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-sliced-vbi-cap.xml b/Documentation/DocBook/media/v4l/vidioc-g-sliced-vbi-cap.xml
deleted file mode 100644
index d05623c55403..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-sliced-vbi-cap.xml
+++ /dev/null
@@ -1,255 +0,0 @@
-<refentry id="vidioc-g-sliced-vbi-cap">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_SLICED_VBI_CAP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_SLICED_VBI_CAP</refname>
- <refpurpose>Query sliced VBI capabilities</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_sliced_vbi_cap *<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_G_SLICED_VBI_CAP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To find out which data services are supported by a sliced
-VBI capture or output device, applications initialize the
-<structfield>type</structfield> field of a &v4l2-sliced-vbi-cap;,
-clear the <structfield>reserved</structfield> array and
-call the <constant>VIDIOC_G_SLICED_VBI_CAP</constant> ioctl. The
-driver fills in the remaining fields or returns an &EINVAL; if the
-sliced VBI API is unsupported or <structfield>type</structfield>
-is invalid.</para>
-
- <para>Note the <structfield>type</structfield> field was added,
-and the ioctl changed from read-only to write-read, in Linux 2.6.19.</para>
-
- <table pgwide="1" frame="none" id="v4l2-sliced-vbi-cap">
- <title>struct <structname>v4l2_sliced_vbi_cap</structname></title>
- <tgroup cols="5">
- <colspec colname="c1" colwidth="3*" />
- <colspec colname="c2" colwidth="3*" />
- <colspec colname="c3" colwidth="2*" />
- <colspec colname="c4" colwidth="2*" />
- <colspec colname="c5" colwidth="2*" />
- <spanspec spanname="hspan" namest="c3" nameend="c5" />
- <tbody valign="top">
- <row>
- <entry>__u16</entry>
- <entry><structfield>service_set</structfield></entry>
- <entry spanname="hspan">A set of all data services
-supported by the driver. Equal to the union of all elements of the
-<structfield>service_lines </structfield> array.</entry>
- </row>
- <row>
- <entry>__u16</entry>
- <entry><structfield>service_lines</structfield>[2][24]</entry>
- <entry spanname="hspan">Each element of this array
-contains a set of data services the hardware can look for or insert
-into a particular scan line. Data services are defined in <xref
- linkend="vbi-services" />. Array indices map to ITU-R
-line numbers (see also <xref
- linkend="vbi-525" /> and <xref
-linkend="vbi-625" />) as follows:</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry>Element</entry>
- <entry>525 line systems</entry>
- <entry>625 line systems</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[0][1]</entry>
- <entry align="center">1</entry>
- <entry align="center">1</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[0][23]</entry>
- <entry align="center">23</entry>
- <entry align="center">23</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[1][1]</entry>
- <entry align="center">264</entry>
- <entry align="center">314</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><structfield>service_lines</structfield>[1][23]</entry>
- <entry align="center">286</entry>
- <entry align="center">336</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry spanname="hspan">The number of VBI lines the
-hardware can capture or output per frame, or the number of services it
-can identify on a given line may be limited. For example on PAL line
-16 the hardware may be able to look for a VPS or Teletext signal, but
-not both at the same time. Applications can learn about these limits
-using the &VIDIOC-S-FMT; ioctl as described in <xref
- linkend="sliced" />.</entry>
- </row>
- <row>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry spanname="hspan">Drivers must set
-<structfield>service_lines</structfield>[0][0] and
-<structfield>service_lines</structfield>[1][0] to zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the data stream, see <xref
- linkend="v4l2-buf-type" />. Should be
-<constant>V4L2_BUF_TYPE_SLICED_VBI_CAPTURE</constant> or
-<constant>V4L2_BUF_TYPE_SLICED_VBI_OUTPUT</constant>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[3]</entry>
- <entry spanname="hspan">This array is reserved for future
-extensions. Applications and drivers must set it to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <!-- See also dev-sliced-vbi.sgml -->
- <table pgwide="1" frame="none" id="vbi-services">
- <title>Sliced VBI services</title>
- <tgroup cols="5">
- <colspec colname="c1" colwidth="2*" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colname="c3" colwidth="1*" />
- <colspec colname="c4" colwidth="2*" />
- <colspec colname="c5" colwidth="2*" />
- <spanspec spanname='rlp' namest='c3' nameend='c5' />
- <thead>
- <row>
- <entry>Symbol</entry>
- <entry>Value</entry>
- <entry>Reference</entry>
- <entry>Lines, usually</entry>
- <entry>Payload</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_SLICED_TELETEXT_B</constant> (Teletext
-System B)</entry>
- <entry>0x0001</entry>
- <entry><xref linkend="ets300706" />, <xref linkend="itu653" /></entry>
- <entry>PAL/SECAM line 7-22, 320-335 (second field 7-22)</entry>
- <entry>Last 42 of the 45 byte Teletext packet, that is
-without clock run-in and framing code, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VPS</constant></entry>
- <entry>0x0400</entry>
- <entry><xref linkend="ets300231" /></entry>
- <entry>PAL line 16</entry>
- <entry>Byte number 3 to 15 according to Figure 9 of
-ETS&nbsp;300&nbsp;231, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_CAPTION_525</constant></entry>
- <entry>0x1000</entry>
- <entry><xref linkend="cea608" /></entry>
- <entry>NTSC line 21, 284 (second field 21)</entry>
- <entry>Two bytes in transmission order, including parity
-bit, lsb first transmitted.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_WSS_625</constant></entry>
- <entry>0x4000</entry>
- <entry><xref linkend="en300294" />, <xref linkend="itu1119" /></entry>
- <entry>PAL/SECAM line 23</entry>
- <entry><screen>
-Byte 0 1
- msb lsb msb lsb
-Bit 7 6 5 4 3 2 1 0 x x 13 12 11 10 9
-</screen></entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VBI_525</constant></entry>
- <entry>0x1000</entry>
- <entry spanname="rlp">Set of services applicable to 525
-line systems.</entry>
- </row>
- <row>
- <entry><constant>V4L2_SLICED_VBI_625</constant></entry>
- <entry>0x4401</entry>
- <entry spanname="rlp">Set of services applicable to 625
-line systems.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The value in the <structfield>type</structfield> field is
-wrong.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-std.xml b/Documentation/DocBook/media/v4l/vidioc-g-std.xml
deleted file mode 100644
index 4a898417de28..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-std.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<refentry id="vidioc-g-std">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_STD, VIDIOC_S_STD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_STD</refname>
- <refname>VIDIOC_S_STD</refname>
- <refpurpose>Query or select the video standard of the current input</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>v4l2_std_id
-*<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const v4l2_std_id
-*<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_G_STD, VIDIOC_S_STD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query and select the current video standard applications
-use the <constant>VIDIOC_G_STD</constant> and <constant>VIDIOC_S_STD</constant> ioctls which take a pointer to a
-&v4l2-std-id; type as argument. <constant>VIDIOC_G_STD</constant> can
-return a single flag or a set of flags as in &v4l2-standard; field
-<structfield>id</structfield>. The flags must be unambiguous such
-that they appear in only one enumerated <structname>v4l2_standard</structname> structure.</para>
-
- <para><constant>VIDIOC_S_STD</constant> accepts one or more
-flags, being a write-only ioctl it does not return the actual new standard as
-<constant>VIDIOC_G_STD</constant> does. When no flags are given or
-the current input does not support the requested standard the driver
-returns an &EINVAL;. When the standard set is ambiguous drivers may
-return <errorcode>EINVAL</errorcode> or choose any of the requested
-standards. If the current input or output does not support standard video timings (e.g. if
-&VIDIOC-ENUMINPUT; does not set the <constant>V4L2_IN_CAP_STD</constant> flag), then
-&ENODATA; is returned.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Standard video timings are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
deleted file mode 100644
index 459b7e561f3c..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
+++ /dev/null
@@ -1,594 +0,0 @@
-<refentry id="vidioc-g-tuner">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_G_TUNER, VIDIOC_S_TUNER</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_G_TUNER</refname>
- <refname>VIDIOC_S_TUNER</refname>
- <refpurpose>Get or set tuner attributes</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_tuner
-*<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_tuner
-*<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_G_TUNER, VIDIOC_S_TUNER</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a tuner applications initialize the
-<structfield>index</structfield> field and zero out the
-<structfield>reserved</structfield> array of a &v4l2-tuner; and call the
-<constant>VIDIOC_G_TUNER</constant> ioctl with a pointer to this
-structure. Drivers fill the rest of the structure or return an
-&EINVAL; when the index is out of bounds. To enumerate all tuners
-applications shall begin at index zero, incrementing by one until the
-driver returns <errorcode>EINVAL</errorcode>.</para>
-
- <para>Tuners have two writable properties, the audio mode and
-the radio frequency. To change the audio mode, applications initialize
-the <structfield>index</structfield>,
-<structfield>audmode</structfield> and
-<structfield>reserved</structfield> fields and call the
-<constant>VIDIOC_S_TUNER</constant> ioctl. This will
-<emphasis>not</emphasis> change the current tuner, which is determined
-by the current video input. Drivers may choose a different audio mode
-if the requested mode is invalid or unsupported. Since this is a
-<!-- FIXME -->write-only ioctl, it does not return the actually
-selected audio mode.</para>
-
- <para><link linkend="sdr">SDR</link> specific tuner types are
-<constant>V4L2_TUNER_SDR</constant> and <constant>V4L2_TUNER_RF</constant>.
-For SDR devices <structfield>audmode</structfield> field must be
-initialized to zero.
-The term 'tuner' means SDR receiver in this context.</para>
-
- <para>To change the radio frequency the &VIDIOC-S-FREQUENCY; ioctl
-is available.</para>
-
- <table pgwide="1" frame="none" id="v4l2-tuner">
- <title>struct <structname>v4l2_tuner</structname></title>
- <tgroup cols="3">
- <colspec colname="c1" colwidth="1*" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colname="c3" colwidth="1*" />
- <colspec colname="c4" colwidth="1*" />
- <spanspec spanname="hspan" namest="c3" nameend="c4" />
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry spanname="hspan">Identifies the tuner, set by the
-application.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry spanname="hspan"><para>Name of the tuner, a
-NUL-terminated ASCII string. This information is intended for the
-user.<!-- FIXME Video inputs already have a name, the purpose of this
-field is not quite clear.--></para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry spanname="hspan">Type of the tuner, see <xref
- linkend="v4l2-tuner-type" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capability</structfield></entry>
- <entry spanname="hspan"><para>Tuner capability flags, see
-<xref linkend="tuner-capability" />. Audio flags indicate the ability
-to decode audio subprograms. They will <emphasis>not</emphasis>
-change, for example with the current video standard.</para><para>When
-the structure refers to a radio tuner the
-<constant>V4L2_TUNER_CAP_LANG1</constant>,
-<constant>V4L2_TUNER_CAP_LANG2</constant> and
-<constant>V4L2_TUNER_CAP_NORM</constant> flags can't be used.</para>
-<para>If multiple frequency bands are supported, then
-<structfield>capability</structfield> is the union of all
-<structfield>capability</structfield> fields of each &v4l2-frequency-band;.
-</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangelow</structfield></entry>
- <entry spanname="hspan">The lowest tunable frequency in
-units of 62.5 kHz, or if the <structfield>capability</structfield>
-flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.
-If multiple frequency bands are supported, then
-<structfield>rangelow</structfield> is the lowest frequency
-of all the frequency bands.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangehigh</structfield></entry>
- <entry spanname="hspan">The highest tunable frequency in
-units of 62.5 kHz, or if the <structfield>capability</structfield>
-flag <constant>V4L2_TUNER_CAP_LOW</constant> is set, in units of 62.5
-Hz, or if the <structfield>capability</structfield> flag
-<constant>V4L2_TUNER_CAP_1HZ</constant> is set, in units of 1 Hz.
-If multiple frequency bands are supported, then
-<structfield>rangehigh</structfield> is the highest frequency
-of all the frequency bands.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rxsubchans</structfield></entry>
- <entry spanname="hspan"><para>Some tuners or audio
-decoders can determine the received audio subprograms by analyzing
-audio carriers, pilot tones or other indicators. To pass this
-information drivers set flags defined in <xref
- linkend="tuner-rxsubchans" /> in this field. For
-example:</para></entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><constant>V4L2_TUNER_SUB_MONO</constant></entry>
- <entry>receiving mono audio</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><constant>STEREO | SAP</constant></entry>
- <entry>receiving stereo audio and a secondary audio
-program</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><constant>MONO | STEREO</constant></entry>
- <entry>receiving mono or stereo audio, the hardware cannot
-distinguish</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><constant>LANG1 | LANG2</constant></entry>
- <entry>receiving bilingual audio</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry><constant>MONO | STEREO | LANG1 | LANG2</constant></entry>
- <entry>receiving mono, stereo or bilingual
-audio</entry>
- </row>
- <row>
- <entry></entry>
- <entry></entry>
- <entry spanname="hspan"><para>When the
-<constant>V4L2_TUNER_CAP_STEREO</constant>,
-<constant>_LANG1</constant>, <constant>_LANG2</constant> or
-<constant>_SAP</constant> flag is cleared in the
-<structfield>capability</structfield> field, the corresponding
-<constant>V4L2_TUNER_SUB_</constant> flag must not be set
-here.</para><para>This field is valid only if this is the tuner of the
-current video input, or when the structure refers to a radio
-tuner.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>audmode</structfield></entry>
- <entry spanname="hspan"><para>The selected audio mode, see
-<xref linkend="tuner-audmode" /> for valid values. The audio mode does
-not affect audio subprogram detection, and like a <link
-linkend="control">control</link> it does not automatically change
-unless the requested mode is invalid or unsupported. See <xref
- linkend="tuner-matrix" /> for possible results when
-the selected and received audio programs do not
-match.</para><para>Currently this is the only field of struct
-<structname>v4l2_tuner</structname> applications can
-change.</para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>signal</structfield></entry>
- <entry spanname="hspan">The signal strength if known, ranging
-from 0 to 65535. Higher values indicate a better signal.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>afc</structfield></entry>
- <entry spanname="hspan">Automatic frequency control: When the
-<structfield>afc</structfield> value is negative, the frequency is too
-low, when positive too high.<!-- FIXME need example what to do when it never
-settles at zero, &ie; range is what? --></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[4]</entry>
- <entry spanname="hspan">Reserved for future extensions. Drivers and
-applications must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-tuner-type">
- <title>enum v4l2_tuner_type</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TUNER_RADIO</constant></entry>
- <entry>1</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_ANALOG_TV</constant></entry>
- <entry>2</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SDR</constant></entry>
- <entry>4</entry>
- <entry></entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_RF</constant></entry>
- <entry>5</entry>
- <entry></entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="tuner-capability">
- <title>Tuner and Modulator Capability Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TUNER_CAP_LOW</constant></entry>
- <entry>0x0001</entry>
- <entry>When set, tuning frequencies are expressed in units of
-62.5 Hz instead of 62.5 kHz.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_NORM</constant></entry>
- <entry>0x0002</entry>
- <entry>This is a multi-standard tuner; the video standard
-can or must be switched. (B/G PAL tuners for example are typically not
- considered multi-standard because the video standard is automatically
- determined from the frequency band.) The set of supported video
- standards is available from the &v4l2-input; pointing to this tuner,
- see the description of ioctl &VIDIOC-ENUMINPUT; for details. Only
- <constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_HWSEEK_BOUNDED</constant></entry>
- <entry>0x0004</entry>
- <entry>If set, then this tuner supports the hardware seek functionality
- where the seek stops when it reaches the end of the frequency range.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_HWSEEK_WRAP</constant></entry>
- <entry>0x0008</entry>
- <entry>If set, then this tuner supports the hardware seek functionality
- where the seek wraps around when it reaches the end of the frequency range.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_STEREO</constant></entry>
- <entry>0x0010</entry>
- <entry>Stereo audio reception is supported.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_LANG1</constant></entry>
- <entry>0x0040</entry>
- <entry>Reception of the primary language of a bilingual
-audio program is supported. Bilingual audio is a feature of
-two-channel systems, transmitting the primary language monaural on the
-main audio carrier and a secondary language monaural on a second
-carrier. Only
- <constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_LANG2</constant></entry>
- <entry>0x0020</entry>
- <entry>Reception of the secondary language of a bilingual
-audio program is supported. Only
- <constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_SAP</constant></entry>
- <entry>0x0020</entry>
- <entry><para>Reception of a secondary audio program is
-supported. This is a feature of the BTSC system which accompanies the
-NTSC video standard. Two audio carriers are available for mono or
-stereo transmissions of a primary language, and an independent third
-carrier for a monaural secondary language. Only
- <constant>V4L2_TUNER_ANALOG_TV</constant> tuners can have this capability.</para><para>Note the
-<constant>V4L2_TUNER_CAP_LANG2</constant> and
-<constant>V4L2_TUNER_CAP_SAP</constant> flags are synonyms.
-<constant>V4L2_TUNER_CAP_SAP</constant> applies when the tuner
-supports the <constant>V4L2_STD_NTSC_M</constant> video
-standard.</para><!-- FIXME what if PAL+NTSC and Bi but not SAP? --></entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_RDS</constant></entry>
- <entry>0x0080</entry>
- <entry>RDS capture is supported. This capability is only valid for
-radio tuners.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_RDS_BLOCK_IO</constant></entry>
- <entry>0x0100</entry>
- <entry>The RDS data is passed as unparsed RDS blocks.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_RDS_CONTROLS</constant></entry>
- <entry>0x0200</entry>
- <entry>The RDS data is parsed by the hardware and set via controls.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_FREQ_BANDS</constant></entry>
- <entry>0x0400</entry>
- <entry>The &VIDIOC-ENUM-FREQ-BANDS; ioctl can be used to enumerate
- the available frequency bands.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_HWSEEK_PROG_LIM</constant></entry>
- <entry>0x0800</entry>
- <entry>The range to search when using the hardware seek functionality
- is programmable, see &VIDIOC-S-HW-FREQ-SEEK; for details.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_CAP_1HZ</constant></entry>
- <entry>0x1000</entry>
- <entry>When set, tuning frequencies are expressed in units of 1 Hz instead of 62.5 kHz.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="tuner-rxsubchans">
- <title>Tuner Audio Reception Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TUNER_SUB_MONO</constant></entry>
- <entry>0x0001</entry>
- <entry>The tuner receives a mono audio signal.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_STEREO</constant></entry>
- <entry>0x0002</entry>
- <entry>The tuner receives a stereo audio signal.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_LANG1</constant></entry>
- <entry>0x0008</entry>
- <entry>The tuner receives the primary language of a
-bilingual audio signal. Drivers must clear this flag when the current
-video standard is <constant>V4L2_STD_NTSC_M</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_LANG2</constant></entry>
- <entry>0x0004</entry>
- <entry>The tuner receives the secondary language of a
-bilingual audio signal (or a second audio program).</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_SAP</constant></entry>
- <entry>0x0004</entry>
- <entry>The tuner receives a Second Audio Program. Note the
-<constant>V4L2_TUNER_SUB_LANG2</constant> and
-<constant>V4L2_TUNER_SUB_SAP</constant> flags are synonyms. The
-<constant>V4L2_TUNER_SUB_SAP</constant> flag applies when the
-current video standard is <constant>V4L2_STD_NTSC_M</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_SUB_RDS</constant></entry>
- <entry>0x0010</entry>
- <entry>The tuner receives an RDS channel.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="tuner-audmode">
- <title>Tuner Audio Modes</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_TUNER_MODE_MONO</constant></entry>
- <entry>0</entry>
- <entry>Play mono audio. When the tuner receives a stereo
-signal this a down-mix of the left and right channel. When the tuner
-receives a bilingual or SAP signal this mode selects the primary
-language.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_MODE_STEREO</constant></entry>
- <entry>1</entry>
- <entry><para>Play stereo audio. When the tuner receives
-bilingual audio it may play different languages on the left and right
-channel or the primary language is played on both channels.</para><para>Playing
-different languages in this mode is
-deprecated. New drivers should do this only in
-<constant>MODE_LANG1_LANG2</constant>.</para><para>When the tuner
-receives no stereo signal or does not support stereo reception the
-driver shall fall back to <constant>MODE_MONO</constant>.</para></entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_MODE_LANG1</constant></entry>
- <entry>3</entry>
- <entry>Play the primary language, mono or stereo. Only
-<constant>V4L2_TUNER_ANALOG_TV</constant> tuners support this
-mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_MODE_LANG2</constant></entry>
- <entry>2</entry>
- <entry>Play the secondary language, mono. When the tuner
-receives no bilingual audio or SAP, or their reception is not
-supported the driver shall fall back to mono or stereo mode. Only
-<constant>V4L2_TUNER_ANALOG_TV</constant> tuners support this
-mode.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_MODE_SAP</constant></entry>
- <entry>2</entry>
- <entry>Play the Second Audio Program. When the tuner
-receives no bilingual audio or SAP, or their reception is not
-supported the driver shall fall back to mono or stereo mode. Only
-<constant>V4L2_TUNER_ANALOG_TV</constant> tuners support this mode.
-Note the <constant>V4L2_TUNER_MODE_LANG2</constant> and
-<constant>V4L2_TUNER_MODE_SAP</constant> are synonyms.</entry>
- </row>
- <row>
- <entry><constant>V4L2_TUNER_MODE_LANG1_LANG2</constant></entry>
- <entry>4</entry>
- <entry>Play the primary language on the left channel, the
-secondary language on the right channel. When the tuner receives no
-bilingual audio or SAP, it shall fall back to
-<constant>MODE_LANG1</constant> or <constant>MODE_MONO</constant>.
-Only <constant>V4L2_TUNER_ANALOG_TV</constant> tuners support this
-mode.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="all" id="tuner-matrix">
- <title>Tuner Audio Matrix</title>
- <tgroup cols="6" align="center">
- <colspec align="left" />
- <colspec colname="c2" colwidth="1*" />
- <colspec colwidth="1*" />
- <colspec colwidth="1*" />
- <colspec colnum="6" colname="c6" colwidth="1*" />
- <spanspec namest="c2" nameend="c6" spanname="hspan" align="center" />
- <thead>
- <row>
- <entry></entry>
- <entry spanname="hspan">Selected
-<constant>V4L2_TUNER_MODE_</constant></entry>
- </row>
- <row>
- <entry>Received <constant>V4L2_TUNER_SUB_</constant></entry>
- <entry><constant>MONO</constant></entry>
- <entry><constant>STEREO</constant></entry>
- <entry><constant>LANG1</constant></entry>
- <entry><constant>LANG2 = SAP</constant></entry>
- <entry><constant>LANG1_LANG2</constant><footnote><para>This
-mode has been added in Linux 2.6.17 and may not be supported by older
-drivers.</para></footnote></entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>MONO</constant></entry>
- <entry>Mono</entry>
- <entry>Mono/Mono</entry>
- <entry>Mono</entry>
- <entry>Mono</entry>
- <entry>Mono/Mono</entry>
- </row>
- <row>
- <entry><constant>MONO | SAP</constant></entry>
- <entry>Mono</entry>
- <entry>Mono/Mono</entry>
- <entry>Mono</entry>
- <entry>SAP</entry>
- <entry>Mono/SAP (preferred) or Mono/Mono</entry>
- </row>
- <row>
- <entry><constant>STEREO</constant></entry>
- <entry>L+R</entry>
- <entry>L/R</entry>
- <entry>Stereo L/R (preferred) or Mono L+R</entry>
- <entry>Stereo L/R (preferred) or Mono L+R</entry>
- <entry>L/R (preferred) or L+R/L+R</entry>
- </row>
- <row>
- <entry><constant>STEREO | SAP</constant></entry>
- <entry>L+R</entry>
- <entry>L/R</entry>
- <entry>Stereo L/R (preferred) or Mono L+R</entry>
- <entry>SAP</entry>
- <entry>L+R/SAP (preferred) or L/R or L+R/L+R</entry>
- </row>
- <row>
- <entry><constant>LANG1 | LANG2</constant></entry>
- <entry>Language&nbsp;1</entry>
- <entry>Lang1/Lang2 (deprecated<footnote><para>Playback of
-both languages in <constant>MODE_STEREO</constant> is deprecated. In
-the future drivers should produce only the primary language in this
-mode. Applications should request
-<constant>MODE_LANG1_LANG2</constant> to record both languages or a
-stereo signal.</para></footnote>) or
-Lang1/Lang1</entry>
- <entry>Language&nbsp;1</entry>
- <entry>Language&nbsp;2</entry>
- <entry>Lang1/Lang2 (preferred) or Lang1/Lang1</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-tuner; <structfield>index</structfield> is
-out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-log-status.xml b/Documentation/DocBook/media/v4l/vidioc-log-status.xml
deleted file mode 100644
index 5ded7d35e27b..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-log-status.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<refentry id="vidioc-log-status">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_LOG_STATUS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_LOG_STATUS</refname>
- <refpurpose>Log driver status information</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- </refsynopsisdiv>
-
- <refsect1>
- <title>Description</title>
-
- <para>As the video/audio devices become more complicated it
-becomes harder to debug problems. When this ioctl is called the driver
-will output the current device status to the kernel log. This is
-particular useful when dealing with problems like no sound, no video
-and incorrectly tuned channels. Also many modern devices autodetect
-video and audio standards and this ioctl will report what the device
-thinks what the standard is. Mismatches may give an indication where
-the problem is.</para>
-
- <para>This ioctl is optional and not all drivers support it. It
-was introduced in Linux 2.6.15.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-overlay.xml b/Documentation/DocBook/media/v4l/vidioc-overlay.xml
deleted file mode 100644
index 250a7de1877f..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-overlay.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<refentry id="vidioc-overlay">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_OVERLAY</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_OVERLAY</refname>
- <refpurpose>Start or stop video overlay</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const int *<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_OVERLAY</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl is part of the <link linkend="overlay">video
- overlay</link> I/O method. Applications call
- <constant>VIDIOC_OVERLAY</constant> to start or stop the
- overlay. It takes a pointer to an integer which must be set to
- zero by the application to stop overlay, to one to start.</para>
-
- <para>Drivers do not support &VIDIOC-STREAMON; or
-&VIDIOC-STREAMOFF; with <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The overlay parameters have not been set up. See <xref
-linkend="overlay" /> for the necessary steps.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml b/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
deleted file mode 100644
index 7bde698760e4..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-prepare-buf.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<refentry id="vidioc-prepare-buf">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_PREPARE_BUF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_PREPARE_BUF</refname>
- <refpurpose>Prepare a buffer for I/O</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_buffer *<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_PREPARE_BUF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Applications can optionally call the
-<constant>VIDIOC_PREPARE_BUF</constant> ioctl to pass ownership of the buffer
-to the driver before actually enqueuing it, using the
-<constant>VIDIOC_QBUF</constant> ioctl, and to prepare it for future I/O.
-Such preparations may include cache invalidation or cleaning. Performing them
-in advance saves time during the actual I/O. In case such cache operations are
-not required, the application can use one of
-<constant>V4L2_BUF_FLAG_NO_CACHE_INVALIDATE</constant> and
-<constant>V4L2_BUF_FLAG_NO_CACHE_CLEAN</constant> flags to skip the respective
-step.</para>
-
- <para>The <structname>v4l2_buffer</structname> structure is
-specified in <xref linkend="buffer" />.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>File I/O is in progress.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The buffer <structfield>type</structfield> is not
-supported, or the <structfield>index</structfield> is out of bounds,
-or no buffers have been allocated yet, or the
-<structfield>userptr</structfield> or
-<structfield>length</structfield> are invalid.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
deleted file mode 100644
index 8b98a0e421fc..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
+++ /dev/null
@@ -1,202 +0,0 @@
-<refentry id="vidioc-qbuf">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QBUF, VIDIOC_DQBUF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QBUF</refname>
- <refname>VIDIOC_DQBUF</refname>
- <refpurpose>Exchange a buffer with the driver</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_buffer *<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_QBUF, VIDIOC_DQBUF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Applications call the <constant>VIDIOC_QBUF</constant> ioctl
-to enqueue an empty (capturing) or filled (output) buffer in the
-driver's incoming queue. The semantics depend on the selected I/O
-method.</para>
-
- <para>To enqueue a buffer applications set the <structfield>type</structfield>
-field of a &v4l2-buffer; to the same buffer type as was previously used
-with &v4l2-format; <structfield>type</structfield> and &v4l2-requestbuffers;
-<structfield>type</structfield>. Applications must also set the
-<structfield>index</structfield> field. Valid index numbers range from
-zero to the number of buffers allocated with &VIDIOC-REQBUFS;
-(&v4l2-requestbuffers; <structfield>count</structfield>) minus one. The
-contents of the struct <structname>v4l2_buffer</structname> returned
-by a &VIDIOC-QUERYBUF; ioctl will do as well. When the buffer is
-intended for output (<structfield>type</structfield> is
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>, or
-<constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>) applications must also
-initialize the <structfield>bytesused</structfield>,
-<structfield>field</structfield> and
-<structfield>timestamp</structfield> fields, see <xref
-linkend="buffer" /> for details.
-Applications must also set <structfield>flags</structfield> to 0.
-The <structfield>reserved2</structfield> and
-<structfield>reserved</structfield> fields must be set to 0. When using
-the <link linkend="planar-apis">multi-planar API</link>, the
-<structfield>m.planes</structfield> field must contain a userspace pointer
-to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>
-field must be set to the number of elements in that array.
-</para>
-
- <para>To enqueue a <link linkend="mmap">memory mapped</link>
-buffer applications set the <structfield>memory</structfield>
-field to <constant>V4L2_MEMORY_MMAP</constant>. When
-<constant>VIDIOC_QBUF</constant> is called with a pointer to this
-structure the driver sets the
-<constant>V4L2_BUF_FLAG_MAPPED</constant> and
-<constant>V4L2_BUF_FLAG_QUEUED</constant> flags and clears the
-<constant>V4L2_BUF_FLAG_DONE</constant> flag in the
-<structfield>flags</structfield> field, or it returns an
-&EINVAL;.</para>
-
- <para>To enqueue a <link linkend="userp">user pointer</link>
-buffer applications set the <structfield>memory</structfield>
-field to <constant>V4L2_MEMORY_USERPTR</constant>, the
-<structfield>m.userptr</structfield> field to the address of the
-buffer and <structfield>length</structfield> to its size. When the multi-planar
-API is used, <structfield>m.userptr</structfield> and
-<structfield>length</structfield> members of the passed array of &v4l2-plane;
-have to be used instead. When <constant>VIDIOC_QBUF</constant> is called with
-a pointer to this structure the driver sets the
-<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
-<constant>V4L2_BUF_FLAG_MAPPED</constant> and
-<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
-<structfield>flags</structfield> field, or it returns an error code.
-This ioctl locks the memory pages of the buffer in physical memory,
-they cannot be swapped out to disk. Buffers remain locked until
-dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
-called, or until the device is closed.</para>
-
- <para>To enqueue a <link linkend="dmabuf">DMABUF</link> buffer applications
-set the <structfield>memory</structfield> field to
-<constant>V4L2_MEMORY_DMABUF</constant> and the <structfield>m.fd</structfield>
-field to a file descriptor associated with a DMABUF buffer. When the
-multi-planar API is used the <structfield>m.fd</structfield> fields of the
-passed array of &v4l2-plane; have to be used instead. When
-<constant>VIDIOC_QBUF</constant> is called with a pointer to this structure the
-driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
-<constant>V4L2_BUF_FLAG_MAPPED</constant> and
-<constant>V4L2_BUF_FLAG_DONE</constant> flags in the
-<structfield>flags</structfield> field, or it returns an error code. This
-ioctl locks the buffer. Locking a buffer means passing it to a driver for a
-hardware access (usually DMA). If an application accesses (reads/writes) a
-locked buffer then the result is undefined. Buffers remain locked until
-dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is called, or
-until the device is closed.</para>
-
- <para>Applications call the <constant>VIDIOC_DQBUF</constant>
-ioctl to dequeue a filled (capturing) or displayed (output) buffer
-from the driver's outgoing queue. They just set the
-<structfield>type</structfield>, <structfield>memory</structfield>
-and <structfield>reserved</structfield>
-fields of a &v4l2-buffer; as above, when <constant>VIDIOC_DQBUF</constant>
-is called with a pointer to this structure the driver fills the
-remaining fields or returns an error code. The driver may also set
-<constant>V4L2_BUF_FLAG_ERROR</constant> in the <structfield>flags</structfield>
-field. It indicates a non-critical (recoverable) streaming error. In such case
-the application may continue as normal, but should be aware that data in the
-dequeued buffer might be corrupted. When using the multi-planar API, the
-planes array must be passed in as well.</para>
-
- <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
-buffer is in the outgoing queue. When the
-<constant>O_NONBLOCK</constant> flag was given to the &func-open;
-function, <constant>VIDIOC_DQBUF</constant> returns immediately
-with an &EAGAIN; when no buffer is available.</para>
-
- <para>The <structname>v4l2_buffer</structname> structure is
-specified in <xref linkend="buffer" />.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EAGAIN</errorcode></term>
- <listitem>
- <para>Non-blocking I/O has been selected using
-<constant>O_NONBLOCK</constant> and no buffer was in the outgoing
-queue.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The buffer <structfield>type</structfield> is not
-supported, or the <structfield>index</structfield> is out of bounds,
-or no buffers have been allocated yet, or the
-<structfield>userptr</structfield> or
-<structfield>length</structfield> are invalid.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EIO</errorcode></term>
- <listitem>
- <para><constant>VIDIOC_DQBUF</constant> failed due to an
-internal error. Can also indicate temporary problems like signal
-loss. Note the driver might dequeue an (empty) buffer despite
-returning an error, or even stop capturing. Reusing such buffer may be unsafe
-though and its details (e.g. <structfield>index</structfield>) may not be
-returned either. It is recommended that drivers indicate recoverable errors
-by setting the <constant>V4L2_BUF_FLAG_ERROR</constant> and returning 0 instead.
-In that case the application should be able to safely reuse the buffer and
-continue streaming.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EPIPE</errorcode></term>
- <listitem>
- <para><constant>VIDIOC_DQBUF</constant> returns this on an empty
-capture queue for mem2mem codecs if a buffer with the
-<constant>V4L2_BUF_FLAG_LAST</constant> was already dequeued and no new buffers
-are expected to become available.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
deleted file mode 100644
index d41bf47ee5a2..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<refentry id="vidioc-query-dv-timings">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QUERY_DV_TIMINGS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QUERY_DV_TIMINGS</refname>
- <refname>VIDIOC_SUBDEV_QUERY_DV_TIMINGS</refname>
- <refpurpose>Sense the DV preset received by the current
-input</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_dv_timings *<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_QUERY_DV_TIMINGS, VIDIOC_SUBDEV_QUERY_DV_TIMINGS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The hardware may be able to detect the current DV timings
-automatically, similar to sensing the video standard. To do so, applications
-call <constant>VIDIOC_QUERY_DV_TIMINGS</constant> with a pointer to a
-&v4l2-dv-timings;. Once the hardware detects the timings, it will fill in the
-timings structure.</para>
-
-<para>Please note that drivers shall <emphasis>not</emphasis> switch timings automatically
-if new timings are detected. Instead, drivers should send the
-<constant>V4L2_EVENT_SOURCE_CHANGE</constant> event (if they support this) and expect
-that userspace will take action by calling <constant>VIDIOC_QUERY_DV_TIMINGS</constant>.
-The reason is that new timings usually mean different buffer sizes as well, and you
-cannot change buffer sizes on the fly. In general, applications that receive the
-Source Change event will have to call <constant>VIDIOC_QUERY_DV_TIMINGS</constant>,
-and if the detected timings are valid they will have to stop streaming, set the new
-timings, allocate new buffers and start streaming again.</para>
-
-<para>If the timings could not be detected because there was no signal, then
-<errorcode>ENOLINK</errorcode> is returned. If a signal was detected, but
-it was unstable and the receiver could not lock to the signal, then
-<errorcode>ENOLCK</errorcode> is returned. If the receiver could lock to the signal,
-but the format is unsupported (e.g. because the pixelclock is out of range
-of the hardware capabilities), then the driver fills in whatever timings it
-could find and returns <errorcode>ERANGE</errorcode>. In that case the application
-can call &VIDIOC-DV-TIMINGS-CAP; to compare the found timings with the hardware's
-capabilities in order to give more precise feedback to the user.
-</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Digital video timings are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOLINK</errorcode></term>
- <listitem>
- <para>No timings could be detected because no signal was found.
-</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOLCK</errorcode></term>
- <listitem>
- <para>The signal was unstable and the hardware could not lock on to it.
-</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ERANGE</errorcode></term>
- <listitem>
- <para>Timings were found, but they are out of range of the hardware
-capabilities.
-</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querybuf.xml b/Documentation/DocBook/media/v4l/vidioc-querybuf.xml
deleted file mode 100644
index 50bfcb5e8508..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-querybuf.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<refentry id="vidioc-querybuf">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYBUF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QUERYBUF</refname>
- <refpurpose>Query the status of a buffer</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_buffer *<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_QUERYBUF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl is part of the <link linkend="mmap">streaming
-</link> I/O method. It can be used to query the status of a
-buffer at any time after buffers have been allocated with the
-&VIDIOC-REQBUFS; ioctl.</para>
-
- <para>Applications set the <structfield>type</structfield> field
- of a &v4l2-buffer; to the same buffer type as was previously used with
-&v4l2-format; <structfield>type</structfield> and &v4l2-requestbuffers;
-<structfield>type</structfield>, and the <structfield>index</structfield>
- field. Valid index numbers range from zero
-to the number of buffers allocated with &VIDIOC-REQBUFS;
- (&v4l2-requestbuffers; <structfield>count</structfield>) minus one.
-The <structfield>reserved</structfield> and <structfield>reserved2 </structfield>
-fields must be set to 0.
-When using the <link linkend="planar-apis">multi-planar API</link>, the
-<structfield>m.planes</structfield> field must contain a userspace pointer to an
-array of &v4l2-plane; and the <structfield>length</structfield> field has
-to be set to the number of elements in that array.
-After calling <constant>VIDIOC_QUERYBUF</constant> with a pointer to
- this structure drivers return an error code or fill the rest of
-the structure.</para>
-
- <para>In the <structfield>flags</structfield> field the
-<constant>V4L2_BUF_FLAG_MAPPED</constant>,
-<constant>V4L2_BUF_FLAG_PREPARED</constant>,
-<constant>V4L2_BUF_FLAG_QUEUED</constant> and
-<constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
-<structfield>memory</structfield> field will be set to the current
-I/O method. For the single-planar API, the <structfield>m.offset</structfield>
-contains the offset of the buffer from the start of the device memory,
-the <structfield>length</structfield> field its size. For the multi-planar API,
-fields <structfield>m.mem_offset</structfield> and
-<structfield>length</structfield> in the <structfield>m.planes</structfield>
-array elements will be used instead and the <structfield>length</structfield>
-field of &v4l2-buffer; is set to the number of filled-in array elements.
-The driver may or may not set the remaining fields and flags, they are
-meaningless in this context.</para>
-
- <para>The <structname>v4l2_buffer</structname> structure is
- specified in <xref linkend="buffer" />.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The buffer <structfield>type</structfield> is not
-supported, or the <structfield>index</structfield> is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
deleted file mode 100644
index cd82148dedd7..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ /dev/null
@@ -1,350 +0,0 @@
-<refentry id="vidioc-querycap">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYCAP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QUERYCAP</refname>
- <refpurpose>Query device capabilities</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_capability *<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_QUERYCAP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>All V4L2 devices support the
-<constant>VIDIOC_QUERYCAP</constant> ioctl. It is used to identify
-kernel devices compatible with this specification and to obtain
-information about driver and hardware capabilities. The ioctl takes a
-pointer to a &v4l2-capability; which is filled by the driver. When the
-driver is not compatible with this specification the ioctl returns an
-&EINVAL;.</para>
-
- <table pgwide="1" frame="none" id="v4l2-capability">
- <title>struct <structname>v4l2_capability</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u8</entry>
- <entry><structfield>driver</structfield>[16]</entry>
- <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.</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>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>card</structfield>[32]</entry>
- <entry>Name of the device, a NUL-terminated UTF-8 string.
-For example: "Yoyodyne TV/FM". One driver may support different brands
-or models of video hardware. This information is intended for users,
-for example in a menu of available devices. Since multiple TV cards of
-the same brand may be installed which are supported by the same
-driver, this name should be combined with the character device file
-name (&eg; <filename>/dev/video2</filename>) or the
-<structfield>bus_info</structfield> string to avoid
-ambiguities.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>bus_info</structfield>[32]</entry>
- <entry>Location of the device in the system, a
-NUL-terminated ASCII string. For example: "PCI:0000:05:06.0". This
-information is intended for users, to distinguish multiple
-identical devices. If no such information is available the field must
-simply count the devices controlled by the driver ("platform:vivi-000").
-The bus_info must start with "PCI:" for PCI boards, "PCIe:" for PCI Express boards,
-"usb-" for USB devices, "I2C:" for i2c devices, "ISA:" for ISA devices,
-"parport" for parallel port devices and "platform:" for platform devices.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>version</structfield></entry>
- <entry><para>Version number of the driver.</para>
-<para>Starting with kernel 3.1, the version reported is provided by the
-V4L2 subsystem following the kernel numbering scheme. However, it
-may not always return the same version as the kernel if, for example,
-a 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>
- <entry spanname="hspan"><para>
-<programlisting>
-#define KERNEL_VERSION(a,b,c) (((a) &lt;&lt; 16) + ((b) &lt;&lt; 8) + (c))
-
-__u32 version = KERNEL_VERSION(0, 8, 1);
-
-printf ("Version: %u.%u.%u\n",
- (version &gt;&gt; 16) &amp; 0xFF,
- (version &gt;&gt; 8) &amp; 0xFF,
- version &amp; 0xFF);
-</programlisting></para></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>capabilities</structfield></entry>
- <entry>Available capabilities of the physical device as a whole, see <xref
- linkend="device-capabilities" />. The same physical device can export
- multiple devices in /dev (e.g. /dev/videoX, /dev/vbiY and /dev/radioZ).
- The <structfield>capabilities</structfield> field should contain a union
- of all capabilities available around the several V4L2 devices exported
- to userspace.
- For all those devices the <structfield>capabilities</structfield> field
- returns the same set of capabilities. This allows applications to open
- just one of the devices (typically the video device) and discover whether
- video, vbi and/or radio are also supported.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>device_caps</structfield></entry>
- <entry>Device capabilities of the opened device, see <xref
- linkend="device-capabilities" />. Should contain the available capabilities
- of that specific device node. So, for example, <structfield>device_caps</structfield>
- of a radio device will only contain radio related capabilities and
- no video or vbi capabilities. This field is only set if the <structfield>capabilities</structfield>
- field contains the <constant>V4L2_CAP_DEVICE_CAPS</constant> capability.
- Only the <structfield>capabilities</structfield> field can have the
- <constant>V4L2_CAP_DEVICE_CAPS</constant> capability, <structfield>device_caps</structfield>
- will never set <constant>V4L2_CAP_DEVICE_CAPS</constant>.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[3]</entry>
- <entry>Reserved for future extensions. Drivers must set
-this array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="device-capabilities">
- <title>Device Capabilities Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CAP_VIDEO_CAPTURE</constant></entry>
- <entry>0x00000001</entry>
- <entry>The device supports the single-planar API through the <link
-linkend="capture">Video Capture</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant></entry>
- <entry>0x00001000</entry>
- <entry>The device supports the
- <link linkend="planar-apis">multi-planar API</link> through the
- <link linkend="capture">Video Capture</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_OUTPUT</constant></entry>
- <entry>0x00000002</entry>
- <entry>The device supports the single-planar API through the <link
-linkend="output">Video Output</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant></entry>
- <entry>0x00002000</entry>
- <entry>The device supports the
- <link linkend="planar-apis">multi-planar API</link> through the
- <link linkend="output">Video Output</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_M2M</constant></entry>
- <entry>0x00004000</entry>
- <entry>The device supports the single-planar API through the
- Video Memory-To-Memory interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_M2M_MPLANE</constant></entry>
- <entry>0x00008000</entry>
- <entry>The device supports the
- <link linkend="planar-apis">multi-planar API</link> through the
- Video Memory-To-Memory interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_OVERLAY</constant></entry>
- <entry>0x00000004</entry>
- <entry>The device supports the <link
-linkend="overlay">Video Overlay</link> interface. A video overlay device
-typically stores captured images directly in the video memory of a
-graphics card, with hardware clipping and scaling.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VBI_CAPTURE</constant></entry>
- <entry>0x00000010</entry>
- <entry>The device supports the <link linkend="raw-vbi">Raw
-VBI Capture</link> interface, providing Teletext and Closed Caption
-data.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VBI_OUTPUT</constant></entry>
- <entry>0x00000020</entry>
- <entry>The device supports the <link linkend="raw-vbi">Raw VBI Output</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_SLICED_VBI_CAPTURE</constant></entry>
- <entry>0x00000040</entry>
- <entry>The device supports the <link linkend="sliced">Sliced VBI Capture</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_SLICED_VBI_OUTPUT</constant></entry>
- <entry>0x00000080</entry>
- <entry>The device supports the <link linkend="sliced">Sliced VBI Output</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_RDS_CAPTURE</constant></entry>
- <entry>0x00000100</entry>
- <entry>The device supports the <link linkend="rds">RDS</link> capture interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant></entry>
- <entry>0x00000200</entry>
- <entry>The device supports the <link linkend="osd">Video
-Output Overlay</link> (OSD) interface. Unlike the <wordasword>Video
-Overlay</wordasword> interface, this is a secondary function of video
-output devices and overlays an image onto an outgoing video signal.
-When the driver sets this flag, it must clear the
-<constant>V4L2_CAP_VIDEO_OVERLAY</constant> flag and vice
-versa.<footnote><para>The &v4l2-framebuffer; lacks an
-&v4l2-buf-type; field, therefore the type of overlay is implied by the
-driver capabilities.</para></footnote></entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_HW_FREQ_SEEK</constant></entry>
- <entry>0x00000400</entry>
- <entry>The device supports the &VIDIOC-S-HW-FREQ-SEEK; ioctl for
-hardware frequency seeking.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_RDS_OUTPUT</constant></entry>
- <entry>0x00000800</entry>
- <entry>The device supports the <link linkend="rds">RDS</link> output interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_TUNER</constant></entry>
- <entry>0x00010000</entry>
- <entry>The device has some sort of tuner to
-receive RF-modulated video signals. For more information about
-tuner programming see
-<xref linkend="tuner" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_AUDIO</constant></entry>
- <entry>0x00020000</entry>
- <entry>The device has audio inputs or outputs. It may or
-may not support audio recording or playback, in PCM or compressed
-formats. PCM audio support must be implemented as ALSA or OSS
-interface. For more information on audio inputs and outputs see <xref
- linkend="audio" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_RADIO</constant></entry>
- <entry>0x00040000</entry>
- <entry>This is a radio receiver.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_MODULATOR</constant></entry>
- <entry>0x00080000</entry>
- <entry>The device has some sort of modulator to
-emit RF-modulated video/audio signals. For more information about
-modulator programming see
-<xref linkend="tuner" />.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_SDR_CAPTURE</constant></entry>
- <entry>0x00100000</entry>
- <entry>The device supports the
-<link linkend="sdr">SDR Capture</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></entry>
- <entry>0x00200000</entry>
- <entry>The device supports the &v4l2-pix-format; extended
-fields.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_SDR_OUTPUT</constant></entry>
- <entry>0x00400000</entry>
- <entry>The device supports the
-<link linkend="sdr">SDR Output</link> interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_READWRITE</constant></entry>
- <entry>0x01000000</entry>
- <entry>The device supports the <link
-linkend="rw">read()</link> and/or <link linkend="rw">write()</link>
-I/O methods.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_ASYNCIO</constant></entry>
- <entry>0x02000000</entry>
- <entry>The device supports the <link
-linkend="async">asynchronous</link> I/O methods.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_STREAMING</constant></entry>
- <entry>0x04000000</entry>
- <entry>The device supports the <link
-linkend="mmap">streaming</link> I/O method.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CAP_DEVICE_CAPS</constant></entry>
- <entry>0x80000000</entry>
- <entry>The driver fills the <structfield>device_caps</structfield>
- field. This capability can only appear in the <structfield>capabilities</structfield>
- field and never in the <structfield>device_caps</structfield> field.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
deleted file mode 100644
index 55b7582cf314..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
+++ /dev/null
@@ -1,661 +0,0 @@
-<refentry id="vidioc-queryctrl">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QUERYCTRL</refname>
- <refname>VIDIOC_QUERY_EXT_CTRL</refname>
- <refname>VIDIOC_QUERYMENU</refname>
- <refpurpose>Enumerate controls and menu control items</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_queryctrl *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>struct v4l2_querymenu *<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_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To query the attributes of a control applications set the
-<structfield>id</structfield> field of a &v4l2-queryctrl; and call the
-<constant>VIDIOC_QUERYCTRL</constant> ioctl with a pointer to this
-structure. The driver fills the rest of the structure or returns an
-&EINVAL; when the <structfield>id</structfield> is invalid.</para>
-
- <para>It is possible to enumerate controls by calling
-<constant>VIDIOC_QUERYCTRL</constant> with successive
-<structfield>id</structfield> values starting from
-<constant>V4L2_CID_BASE</constant> up to and exclusive
-<constant>V4L2_CID_LASTP1</constant>. Drivers may return
-<errorcode>EINVAL</errorcode> if a control in this range is not
-supported. Further applications can enumerate private controls, which
-are not defined in this specification, by starting at
-<constant>V4L2_CID_PRIVATE_BASE</constant> and incrementing
-<structfield>id</structfield> until the driver returns
-<errorcode>EINVAL</errorcode>.</para>
-
- <para>In both cases, when the driver sets the
-<constant>V4L2_CTRL_FLAG_DISABLED</constant> flag in the
-<structfield>flags</structfield> field this control is permanently
-disabled and should be ignored by the application.<footnote>
- <para><constant>V4L2_CTRL_FLAG_DISABLED</constant> was
-intended for two purposes: Drivers can skip predefined controls not
-supported by the hardware (although returning EINVAL would do as
-well), or disable predefined and private controls after hardware
-detection without the trouble of reordering control arrays and indices
-(EINVAL cannot be used to skip private controls because it would
-prematurely end the enumeration).</para></footnote></para>
-
- <para>When the application ORs <structfield>id</structfield> with
-<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
-next supported non-compound control, or <errorcode>EINVAL</errorcode>
-if there is none. In addition, the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
-flag can be specified to enumerate all compound controls (i.e. controls
-with type &ge; <constant>V4L2_CTRL_COMPOUND_TYPES</constant> and/or array
-control, in other words controls that contain more than one value).
-Specify both <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
-<constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> in order to enumerate
-all controls, compound or not. Drivers which do not support these flags yet
-always return <errorcode>EINVAL</errorcode>.</para>
-
- <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
-introduced in order to better support controls that can use compound
-types, and to expose additional control information that cannot be
-returned in &v4l2-queryctrl; since that structure is full.</para>
-
- <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
-same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
-<structfield>reserved</structfield> array must be zeroed as well.</para>
-
- <para>Additional information is required for menu controls: the
-names of the menu items. To query them applications set the
-<structfield>id</structfield> and <structfield>index</structfield>
-fields of &v4l2-querymenu; and call the
-<constant>VIDIOC_QUERYMENU</constant> ioctl with a pointer to this
-structure. The driver fills the rest of the structure or returns an
-&EINVAL; when the <structfield>id</structfield> or
-<structfield>index</structfield> is invalid. Menu items are enumerated
-by calling <constant>VIDIOC_QUERYMENU</constant> with successive
-<structfield>index</structfield> values from &v4l2-queryctrl;
-<structfield>minimum</structfield> to
-<structfield>maximum</structfield>, inclusive. Note that it is possible
-for <constant>VIDIOC_QUERYMENU</constant> to return an &EINVAL; for some
-indices between <structfield>minimum</structfield> and <structfield>maximum</structfield>.
-In that case that particular menu item is not supported by this driver. Also note that
-the <structfield>minimum</structfield> value is not necessarily 0.</para>
-
- <para>See also the examples in <xref linkend="control" />.</para>
-
- <table pgwide="1" frame="none" id="v4l2-queryctrl">
- <title>struct <structname>v4l2_queryctrl</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry>Identifies the control, set by the application. See
-<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
-with V4L2_CTRL_FLAG_NEXT_CTRL the driver clears the flag and returns
-the first control with a higher ID. Drivers which do not support this
-flag yet always return an &EINVAL;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of control, see <xref
- linkend="v4l2-ctrl-type" />.</entry>
- </row>
- <row>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the control, a NUL-terminated ASCII
-string. This information is intended for the user.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>minimum</structfield></entry>
- <entry>Minimum value, inclusive. This field gives a lower
-bound for the control. See &v4l2-ctrl-type; how the minimum value is to
-be used for each possible control type. Note that this a signed 32-bit value.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>maximum</structfield></entry>
- <entry>Maximum value, inclusive. This field gives an upper
-bound for the control. See &v4l2-ctrl-type; how the maximum value is to
-be used for each possible control type. Note that this a signed 32-bit value.</entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>step</structfield></entry>
- <entry><para>This field gives a step size for the control.
-See &v4l2-ctrl-type; how the step value is to be used for each possible
-control type. Note that this an unsigned 32-bit value.
-</para><para>Generally drivers should not scale hardware
-control values. It may be necessary for example when the
-<structfield>name</structfield> or <structfield>id</structfield> imply
-a particular unit and the hardware actually accepts only multiples of
-said unit. If so, drivers must take care values are properly rounded
-when scaling, such that errors will not accumulate on repeated
-read-write cycles.</para><para>This field gives the smallest change of
-an integer control actually affecting hardware. Often the information
-is needed when the user can change controls by keyboard or GUI
-buttons, rather than a slider. When for example a hardware register
-accepts values 0-511 and the driver reports 0-65535, step should be
-128.</para><para>Note that although signed, the step value is supposed to
-be always positive.</para></entry>
- </row>
- <row>
- <entry>__s32</entry>
- <entry><structfield>default_value</structfield></entry>
- <entry>The default value of a
-<constant>V4L2_CTRL_TYPE_INTEGER</constant>,
-<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
-<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
-Not valid for other types of controls.
-Note that drivers reset controls to their default value only when the
-driver is first loaded, never afterwards.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Control flags, see <xref
- linkend="control-flags" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
- <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>id</structfield></entry>
- <entry>Identifies the control, set by the application. See
-<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
-with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
-flag and returns the first non-compound control with a higher ID. When the
-ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> the driver
-clears the flag and returns the first compound control with a higher ID.
-Set both to get the first control (compound or not) with a higher ID.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of control, see <xref
- linkend="v4l2-ctrl-type" />.</entry>
- </row>
- <row>
- <entry>char</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the control, a NUL-terminated ASCII
-string. This information is intended for the user.</entry>
- </row>
- <row>
- <entry>__s64</entry>
- <entry><structfield>minimum</structfield></entry>
- <entry>Minimum value, inclusive. This field gives a lower
-bound for the control. See &v4l2-ctrl-type; how the minimum value is to
-be used for each possible control type. Note that this a signed 64-bit value.</entry>
- </row>
- <row>
- <entry>__s64</entry>
- <entry><structfield>maximum</structfield></entry>
- <entry>Maximum value, inclusive. This field gives an upper
-bound for the control. See &v4l2-ctrl-type; how the maximum value is to
-be used for each possible control type. Note that this a signed 64-bit value.</entry>
- </row>
- <row>
- <entry>__u64</entry>
- <entry><structfield>step</structfield></entry>
- <entry><para>This field gives a step size for the control.
-See &v4l2-ctrl-type; how the step value is to be used for each possible
-control type. Note that this an unsigned 64-bit value.
-</para><para>Generally drivers should not scale hardware
-control values. It may be necessary for example when the
-<structfield>name</structfield> or <structfield>id</structfield> imply
-a particular unit and the hardware actually accepts only multiples of
-said unit. If so, drivers must take care values are properly rounded
-when scaling, such that errors will not accumulate on repeated
-read-write cycles.</para><para>This field gives the smallest change of
-an integer control actually affecting hardware. Often the information
-is needed when the user can change controls by keyboard or GUI
-buttons, rather than a slider. When for example a hardware register
-accepts values 0-511 and the driver reports 0-65535, step should be
-128.</para></entry>
- </row>
- <row>
- <entry>__s64</entry>
- <entry><structfield>default_value</structfield></entry>
- <entry>The default value of a
-<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
-<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
-<constant>_MENU</constant>, <constant>_INTEGER_MENU</constant>,
-<constant>_U8</constant> or <constant>_U16</constant> control.
-Not valid for other types of controls.
-Note that drivers reset controls to their default value only when the
-driver is first loaded, never afterwards.
-</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Control flags, see <xref
- linkend="control-flags" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>elem_size</structfield></entry>
- <entry>The size in bytes of a single element of the array.
-Given a char pointer <constant>p</constant> to a 3-dimensional array you can find the
-position of cell <constant>(z, y, x)</constant> as follows:
-<constant>p + ((z * dims[1] + y) * dims[0] + x) * elem_size</constant>. <structfield>elem_size</structfield>
-is always valid, also when the control isn't an array. For string controls
-<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
-</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>elems</structfield></entry>
- <entry>The number of elements in the N-dimensional array. If this control
-is not an array, then <structfield>elems</structfield> is 1. The <structfield>elems</structfield>
-field can never be 0.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>nr_of_dims</structfield></entry>
- <entry>The number of dimension in the N-dimensional array. If this control
-is not an array, then this field is 0.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>dims[V4L2_CTRL_MAX_DIMS]</structfield></entry>
- <entry>The size of each dimension. The first <structfield>nr_of_dims</structfield>
-elements of this array must be non-zero, all remaining elements must be zero.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[32]</entry>
- <entry>Reserved for future extensions. Applications and drivers
-must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-querymenu">
- <title>struct <structname>v4l2_querymenu</structname></title>
- <tgroup cols="4">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry></entry>
- <entry><structfield>id</structfield></entry>
- <entry>Identifies the control, set by the application
-from the respective &v4l2-queryctrl;
-<structfield>id</structfield>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry></entry>
- <entry><structfield>index</structfield></entry>
- <entry>Index of the menu item, starting at zero, set by
- the application.</entry>
- </row>
- <row>
- <entry>union</entry>
- <entry></entry>
- <entry></entry>
- <entry></entry>
- </row>
- <row>
- <entry></entry>
- <entry>__u8</entry>
- <entry><structfield>name</structfield>[32]</entry>
- <entry>Name of the menu item, a NUL-terminated ASCII
-string. This information is intended for the user. This field is valid
-for <constant>V4L2_CTRL_FLAG_MENU</constant> type controls.</entry>
- </row>
- <row>
- <entry></entry>
- <entry>__s64</entry>
- <entry><structfield>value</structfield></entry>
- <entry>
- Value of the integer menu item. This field is valid for
- <constant>V4L2_CTRL_FLAG_INTEGER_MENU</constant> type
- controls.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry></entry>
- <entry><structfield>reserved</structfield></entry>
- <entry>Reserved for future extensions. Drivers must set
-the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-ctrl-type">
- <title>enum v4l2_ctrl_type</title>
- <tgroup cols="5" align="left">
- <colspec colwidth="30*" />
- <colspec colwidth="5*" align="center" />
- <colspec colwidth="5*" align="center" />
- <colspec colwidth="5*" align="center" />
- <colspec colwidth="55*" />
- <thead>
- <row>
- <entry>Type</entry>
- <entry><structfield>minimum</structfield></entry>
- <entry><structfield>step</structfield></entry>
- <entry><structfield>maximum</structfield></entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CTRL_TYPE_INTEGER</constant></entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>An integer-valued control ranging from minimum to
-maximum inclusive. The step value indicates the increment between
-values.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_BOOLEAN</constant></entry>
- <entry>0</entry>
- <entry>1</entry>
- <entry>1</entry>
- <entry>A boolean-valued control. Zero corresponds to
-"disabled", and one means "enabled".</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_MENU</constant></entry>
- <entry>&ge; 0</entry>
- <entry>1</entry>
- <entry>N-1</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_INTEGER_MENU</constant></entry>
- <entry>&ge; 0</entry>
- <entry>1</entry>
- <entry>N-1</entry>
- <entry>
- The control has a menu of N choices. The values of the
- menu items can be enumerated with the
- <constant>VIDIOC_QUERYMENU</constant> ioctl. This is
- similar to <constant>V4L2_CTRL_TYPE_MENU</constant>
- except that instead of strings, the menu items are
- signed 64-bit integers.
- </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>
- <entry>0</entry>
- <entry>0</entry>
- <entry>0</entry>
- <entry>A control which performs an action when set.
-Drivers must ignore the value passed with
-<constant>VIDIOC_S_CTRL</constant> and return an &EINVAL; on a
-<constant>VIDIOC_G_CTRL</constant> attempt.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>A 64-bit integer valued control. Minimum, maximum
-and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
-Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
-min/max/step values, they should be interpreted as n/a when using
-<constant>VIDIOC_QUERYCTRL</constant>.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
- <entry>&ge; 0</entry>
- <entry>&ge; 1</entry>
- <entry>&ge; 0</entry>
- <entry>The minimum and maximum string lengths. The step size
-means that the string must be (minimum + N * step) characters long for
-N &ge; 0. These lengths do not include the terminating zero, so in order to
-pass a string of length 8 to &VIDIOC-S-EXT-CTRLS; you need to set the
-<structfield>size</structfield> field of &v4l2-ext-control; to 9. For &VIDIOC-G-EXT-CTRLS; you can
-set the <structfield>size</structfield> field to <structfield>maximum</structfield> + 1.
-Which character encoding is used will depend on the string control itself and
-should be part of the control documentation.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_CTRL_CLASS</constant></entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
- <entry>This is not a control. When
-<constant>VIDIOC_QUERYCTRL</constant> is called with a control ID
-equal to a control class code (see <xref linkend="ctrl-class" />) + 1, the
-ioctl returns the name of the control class and this control type.
-Older drivers which do not support this feature return an
-&EINVAL;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_U8</constant></entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>An unsigned 8-bit valued control ranging from minimum to
-maximum inclusive. The step value indicates the increment between
-values.
-</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_U16</constant></entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>An unsigned 16-bit valued control ranging from minimum to
-maximum inclusive. The step value indicates the increment between
-values.
-</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_TYPE_U32</constant></entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>any</entry>
- <entry>An unsigned 32-bit valued control ranging from minimum to
-maximum inclusive. The step value indicates the increment between
-values.
-</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="control-flags">
- <title>Control Flags</title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry><constant>V4L2_CTRL_FLAG_DISABLED</constant></entry>
- <entry>0x0001</entry>
- <entry>This control is permanently disabled and should be
-ignored by the application. Any attempt to change the control will
-result in an &EINVAL;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_GRABBED</constant></entry>
- <entry>0x0002</entry>
- <entry>This control is temporarily unchangeable, for
-example because another application took over control of the
-respective resource. Such controls may be displayed specially in a
-user interface. Attempts to change the control may result in an
-&EBUSY;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_READ_ONLY</constant></entry>
- <entry>0x0004</entry>
- <entry>This control is permanently readable only. Any
-attempt to change the control will result in an &EINVAL;.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_UPDATE</constant></entry>
- <entry>0x0008</entry>
- <entry>A hint that changing this control may affect the
-value of other controls within the same control class. Applications
-should update their user interface accordingly.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_INACTIVE</constant></entry>
- <entry>0x0010</entry>
- <entry>This control is not applicable to the current
-configuration and should be displayed accordingly in a user interface.
-For example the flag may be set on a MPEG audio level 2 bitrate
-control when MPEG audio encoding level 1 was selected with another
-control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_SLIDER</constant></entry>
- <entry>0x0020</entry>
- <entry>A hint that this control is best represented as a
-slider-like element in a user interface.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_WRITE_ONLY</constant></entry>
- <entry>0x0040</entry>
- <entry>This control is permanently writable only. Any
-attempt to read the control will result in an &EACCES; error code. This
-flag is typically present for relative controls or action controls where
-writing a value will cause the device to carry out a given action
-(&eg; motor control) but no meaningful value can be returned.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_VOLATILE</constant></entry>
- <entry>0x0080</entry>
- <entry>This control is volatile, which means that the value of the control
-changes continuously. A typical example would be the current gain value if the device
-is in auto-gain mode. In such a case the hardware calculates the gain value based on
-the lighting conditions which can change over time. Note that setting a new value for
-a volatile control will have no effect and no <constant>V4L2_EVENT_CTRL_CH_VALUE</constant>
-will be sent, unless the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant> flag
-(see below) is also set. Otherwise the new value will just be ignored.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
- <entry>0x0100</entry>
- <entry>This control has a pointer type, so its value has to be accessed
-using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
-that are an array, string, or have a compound type. In all cases you have to set a
-pointer to memory containing the payload of the control.</entry>
- </row>
- <row>
- <entry><constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant></entry>
- <entry>0x0200</entry>
- <entry>The value provided to the control will be propagated to the driver
-even if it remains constant. This is required when the control represents an action
-on the hardware. For example: clearing an error flag or triggering the flash. All the
-controls of the type <constant>V4L2_CTRL_TYPE_BUTTON</constant> have this flag set.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-queryctrl; <structfield>id</structfield>
-is invalid. The &v4l2-querymenu; <structfield>id</structfield> is
-invalid or <structfield>index</structfield> is out of range (less than
-<structfield>minimum</structfield> or greater than <structfield>maximum</structfield>)
-or this particular menu item is not supported by the driver.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EACCES</errorcode></term>
- <listitem>
- <para>An attempt was made to read a write-only control.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querystd.xml b/Documentation/DocBook/media/v4l/vidioc-querystd.xml
deleted file mode 100644
index 3ceae35fab03..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-querystd.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<refentry id="vidioc-querystd">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYSTD</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_QUERYSTD</refname>
- <refpurpose>Sense the video standard received by the current
-input</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>v4l2_std_id *<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_QUERYSTD</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The hardware may be able to detect the current video
-standard automatically. To do so, applications call <constant>
-VIDIOC_QUERYSTD</constant> with a pointer to a &v4l2-std-id; type. The
-driver stores here a set of candidates, this can be a single flag or a
-set of supported standards if for example the hardware can only
-distinguish between 50 and 60 Hz systems. If no signal was detected,
-then the driver will return V4L2_STD_UNKNOWN. When detection is not
-possible or fails, the set must contain all standards supported by the
-current video input or output.</para>
-
-<para>Please note that drivers shall <emphasis>not</emphasis> switch the video standard
-automatically if a new video standard is detected. Instead, drivers should send the
-<constant>V4L2_EVENT_SOURCE_CHANGE</constant> event (if they support this) and expect
-that userspace will take action by calling <constant>VIDIOC_QUERYSTD</constant>.
-The reason is that a new video standard can mean different buffer sizes as well, and you
-cannot change buffer sizes on the fly. In general, applications that receive the
-Source Change event will have to call <constant>VIDIOC_QUERYSTD</constant>,
-and if the detected video standard is valid they will have to stop streaming, set the new
-standard, allocate new buffers and start streaming again.</para>
-
- </refsect1>
-
- <refsect1>
- &return-value;
- <variablelist>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>Standard video timings are not supported for this input or output.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml b/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
deleted file mode 100644
index 6f529e100ea4..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-<refentry id="vidioc-reqbufs">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_REQBUFS</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_REQBUFS</refname>
- <refpurpose>Initiate Memory Mapping, User Pointer or DMA Buffer I/O</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_requestbuffers *<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_REQBUFS</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
-<para>This ioctl is used to initiate <link linkend="mmap">memory mapped</link>,
-<link linkend="userp">user pointer</link> or <link
-linkend="dmabuf">DMABUF</link> based I/O. Memory mapped buffers are located in
-device memory and must be allocated with this ioctl before they can be mapped
-into the application's address space. User buffers are allocated by
-applications themselves, and this ioctl is merely used to switch the driver
-into user pointer I/O mode and to setup some internal structures.
-Similarly, DMABUF buffers are allocated by applications through a device
-driver, and this ioctl only configures the driver into DMABUF I/O mode without
-performing any direct allocation.</para>
-
- <para>To allocate device buffers applications initialize all fields of the
-<structname>v4l2_requestbuffers</structname> structure. They set the
-<structfield>type</structfield> field to the respective stream or buffer type,
-the <structfield>count</structfield> field to the desired number of buffers,
-<structfield>memory</structfield> must be set to the requested I/O method and
-the <structfield>reserved</structfield> array must be zeroed. When the ioctl is
-called with a pointer to this structure the driver will attempt to allocate the
-requested number of buffers and it stores the actual number allocated in the
-<structfield>count</structfield> field. It can be smaller than the number
-requested, even zero, when the driver runs out of free memory. A larger number
-is also possible when the driver requires more buffers to function correctly.
-For example video output requires at least two buffers, one displayed and one
-filled by the application.</para>
- <para>When the I/O method is not supported the ioctl
-returns an &EINVAL;.</para>
-
- <para>Applications can call <constant>VIDIOC_REQBUFS</constant>
-again to change the number of buffers, however this cannot succeed
-when any buffers are still mapped. A <structfield>count</structfield>
-value of zero frees all buffers, after aborting or finishing any DMA
-in progress, an implicit &VIDIOC-STREAMOFF;. <!-- mhs: I see no
-reason why munmap()ping one or even all buffers must imply
-streamoff.--></para>
-
- <table pgwide="1" frame="none" id="v4l2-requestbuffers">
- <title>struct <structname>v4l2_requestbuffers</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>count</structfield></entry>
- <entry>The number of buffers requested or granted.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>Type of the stream or buffers, this is the same
-as the &v4l2-format; <structfield>type</structfield> field. See <xref
- linkend="v4l2-buf-type" /> for valid values.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>memory</structfield></entry>
- <entry>Applications set this field to
-<constant>V4L2_MEMORY_MMAP</constant>,
-<constant>V4L2_MEMORY_DMABUF</constant> or
-<constant>V4L2_MEMORY_USERPTR</constant>. See <xref linkend="v4l2-memory"
-/>.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[2]</entry>
- <entry>A place holder for future extensions. Drivers and applications
-must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The buffer type (<structfield>type</structfield> field) or the
-requested I/O method (<structfield>memory</structfield>) is not
-supported.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml b/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
deleted file mode 100644
index a5fc4c4880f3..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
+++ /dev/null
@@ -1,188 +0,0 @@
-<refentry id="vidioc-s-hw-freq-seek">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_S_HW_FREQ_SEEK</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_S_HW_FREQ_SEEK</refname>
- <refpurpose>Perform a hardware frequency seek</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_hw_freq_seek
-*<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_S_HW_FREQ_SEEK</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>Start a hardware frequency seek from the current frequency.
-To do this applications initialize the <structfield>tuner</structfield>,
-<structfield>type</structfield>, <structfield>seek_upward</structfield>,
-<structfield>wrap_around</structfield>, <structfield>spacing</structfield>,
-<structfield>rangelow</structfield> and <structfield>rangehigh</structfield>
-fields, and zero out the <structfield>reserved</structfield> array of a
-&v4l2-hw-freq-seek; and call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant>
-ioctl with a pointer to this structure.</para>
-
- <para>The <structfield>rangelow</structfield> and
-<structfield>rangehigh</structfield> fields can be set to a non-zero value to
-tell the driver to search a specific band. If the &v4l2-tuner;
-<structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_HWSEEK_PROG_LIM</constant> flag set, these values
-must fall within one of the bands returned by &VIDIOC-ENUM-FREQ-BANDS;. If
-the <constant>V4L2_TUNER_CAP_HWSEEK_PROG_LIM</constant> flag is not set,
-then these values must exactly match those of one of the bands returned by
-&VIDIOC-ENUM-FREQ-BANDS;. If the current frequency of the tuner does not fall
-within the selected band it will be clamped to fit in the band before the
-seek is started.</para>
-
- <para>If an error is returned, then the original frequency will
- be restored.</para>
-
- <para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para>
-
- <para>If this ioctl is called from a non-blocking filehandle, then &EAGAIN; is
- returned and no seek takes place.</para>
-
- <table pgwide="1" frame="none" id="v4l2-hw-freq-seek">
- <title>struct <structname>v4l2_hw_freq_seek</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>tuner</structfield></entry>
- <entry>The tuner index number. This is the
-same value as in the &v4l2-input; <structfield>tuner</structfield>
-field and the &v4l2-tuner; <structfield>index</structfield> field.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>type</structfield></entry>
- <entry>The tuner type. This is the same value as in the
-&v4l2-tuner; <structfield>type</structfield> field. See <xref
- linkend="v4l2-tuner-type" /></entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>seek_upward</structfield></entry>
- <entry>If non-zero, seek upward from the current frequency, else seek downward.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>wrap_around</structfield></entry>
- <entry>If non-zero, wrap around when at the end of the frequency range, else stop seeking.
- The &v4l2-tuner; <structfield>capability</structfield> field will tell you what the
- hardware supports.
- </entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>spacing</structfield></entry>
- <entry>If non-zero, defines the hardware seek resolution in Hz. The driver selects the nearest value that is supported by the device. If spacing is zero a reasonable default value is used.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangelow</structfield></entry>
- <entry>If non-zero, the lowest tunable frequency of the band to
-search in units of 62.5 kHz, or if the &v4l2-tuner;
-<structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz or if the &v4l2-tuner;
-<structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_1HZ</constant> flag set, in units of 1 Hz.
-If <structfield>rangelow</structfield> is zero a reasonable default value
-is used.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>rangehigh</structfield></entry>
- <entry>If non-zero, the highest tunable frequency of the band to
-search in units of 62.5 kHz, or if the &v4l2-tuner;
-<structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_LOW</constant> flag set, in units of 62.5 Hz or if the &v4l2-tuner;
-<structfield>capability</structfield> field has the
-<constant>V4L2_TUNER_CAP_1HZ</constant> flag set, in units of 1 Hz.
-If <structfield>rangehigh</structfield> is zero a reasonable default value
-is used.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[5]</entry>
- <entry>Reserved for future extensions. Applications
- must set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The <structfield>tuner</structfield> index is out of
-bounds, the <structfield>wrap_around</structfield> value is not supported or
-one of the values in the <structfield>type</structfield>,
-<structfield>rangelow</structfield> or <structfield>rangehigh</structfield>
-fields is wrong.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EAGAIN</errorcode></term>
- <listitem>
- <para>Attempted to call <constant>VIDIOC_S_HW_FREQ_SEEK</constant>
- with the filehandle in non-blocking mode.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENODATA</errorcode></term>
- <listitem>
- <para>The hardware seek found no channels.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>Another hardware seek is already in progress.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
deleted file mode 100644
index 89fd7ce964f9..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml
+++ /dev/null
@@ -1,136 +0,0 @@
-<refentry id="vidioc-streamon">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_STREAMON, VIDIOC_STREAMOFF</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_STREAMON</refname>
- <refname>VIDIOC_STREAMOFF</refname>
- <refpurpose>Start or stop streaming I/O</refpurpose>
- </refnamediv>
-
- <refsynopsisdiv>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const int *<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_STREAMON, VIDIOC_STREAMOFF</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The <constant>VIDIOC_STREAMON</constant> and
-<constant>VIDIOC_STREAMOFF</constant> ioctl start and stop the capture
-or output process during streaming (<link linkend="mmap">memory
-mapping</link>, <link linkend="userp">user pointer</link> or
-<link linkend="dmabuf">DMABUF</link>) I/O.</para>
-
- <para>Capture hardware is disabled and no input
-buffers are filled (if there are any empty buffers in the incoming
-queue) until <constant>VIDIOC_STREAMON</constant> has been called.
-Output hardware is disabled and no video signal is
-produced until <constant>VIDIOC_STREAMON</constant> has been called.
-The ioctl will succeed when at least one output buffer is in the
-incoming queue.</para>
-
- <para>Memory-to-memory devices will not start until
-<constant>VIDIOC_STREAMON</constant> has been called for both the capture
-and output stream types.</para>
-
- <para>If <constant>VIDIOC_STREAMON</constant> fails then any already
-queued buffers will remain queued.</para>
-
- <para>The <constant>VIDIOC_STREAMOFF</constant> ioctl, apart of
-aborting or finishing any DMA in progress, unlocks any user pointer
-buffers locked in physical memory, and it removes all buffers from the
-incoming and outgoing queues. That means all images captured but not
-dequeued yet will be lost, likewise all images enqueued for output but
-not transmitted yet. I/O returns to the same state as after calling
-&VIDIOC-REQBUFS; and can be restarted accordingly.</para>
-
- <para>If buffers have been queued with &VIDIOC-QBUF; and
-<constant>VIDIOC_STREAMOFF</constant> is called without ever having
-called <constant>VIDIOC_STREAMON</constant>, then those queued buffers
-will also be removed from the incoming queue and all are returned to the
-same state as after calling &VIDIOC-REQBUFS; and can be restarted
-accordingly.</para>
-
- <para>Both ioctls take a pointer to an integer, the desired buffer or
-stream type. This is the same as &v4l2-requestbuffers;
-<structfield>type</structfield>.</para>
-
- <para>If <constant>VIDIOC_STREAMON</constant> is called when streaming
-is already in progress, or if <constant>VIDIOC_STREAMOFF</constant> is called
-when streaming is already stopped, then 0 is returned. Nothing happens in the
-case of <constant>VIDIOC_STREAMON</constant>, but <constant>VIDIOC_STREAMOFF</constant>
-will return queued buffers to their starting state as mentioned above.</para>
-
- <para>Note that applications can be preempted for unknown periods right
-before or after the <constant>VIDIOC_STREAMON</constant> or
-<constant>VIDIOC_STREAMOFF</constant> calls, there is no notion of
-starting or stopping "now". Buffer timestamps can be used to
-synchronize with other events.</para>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <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>
- <term><errorcode>EPIPE</errorcode></term>
- <listitem>
- <para>The driver implements <link
- linkend="pad-level-formats">pad-level format configuration</link> and
- the pipeline configuration is invalid.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>ENOLINK</errorcode></term>
- <listitem>
- <para>The driver implements Media Controller interface and
- the pipeline link configuration is invalid.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
deleted file mode 100644
index 9d0251a27e5f..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
+++ /dev/null
@@ -1,151 +0,0 @@
-<refentry id="vidioc-subdev-enum-frame-interval">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname>
- <refpurpose>Enumerate frame intervals</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_subdev_frame_interval_enum *
- <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_SUBDEV_ENUM_FRAME_INTERVAL</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl lets applications enumerate available frame intervals on a
- given sub-device pad. Frame intervals only makes sense for sub-devices that
- can control the frame period on their own. This includes, for instance,
- image sensors and TV tuners.</para>
-
- <para>For the common use case of image sensors, the frame intervals
- available on the sub-device output pad depend on the frame format and size
- on the same pad. Applications must thus specify the desired format and size
- when enumerating frame intervals.</para>
-
- <para>To enumerate frame intervals applications initialize the
- <structfield>index</structfield>, <structfield>pad</structfield>,
- <structfield>which</structfield>, <structfield>code</structfield>,
- <structfield>width</structfield> and <structfield>height</structfield>
- fields of &v4l2-subdev-frame-interval-enum; and call the
- <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
- to this structure. Drivers fill the rest of the structure or return
- an &EINVAL; if one of the input fields is invalid. All frame intervals are
- enumerable by beginning at index zero and incrementing by one until
- <errorcode>EINVAL</errorcode> is returned.</para>
-
- <para>Available frame intervals may depend on the current 'try' formats
- at other pads of the sub-device, as well as on the current active links. See
- &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
-
- <para>Sub-devices that support the frame interval enumeration ioctl should
- implemented it on a single pad only. Its behaviour when supported on
- multiple pads of the same sub-device is not defined.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum">
- <title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the format in the enumeration, set by the
- application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>code</structfield></entry>
- <entry>The media bus format code, as defined in
- <xref linkend="v4l2-mbus-format" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>width</structfield></entry>
- <entry>Frame width, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>height</structfield></entry>
- <entry>Frame height, in pixels.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>interval</structfield></entry>
- <entry>Period, in seconds, between consecutive video frames.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Frame intervals to be enumerated, from &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-frame-interval-enum;
- <structfield>pad</structfield> references a non-existing pad, one of
- the <structfield>code</structfield>, <structfield>width</structfield>
- or <structfield>height</structfield> fields are invalid for the given
- pad or the <structfield>index</structfield> field is out of bounds.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
deleted file mode 100644
index 9b91b8332ba9..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
+++ /dev/null
@@ -1,153 +0,0 @@
-<refentry id="vidioc-subdev-enum-frame-size">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refname>
- <refpurpose>Enumerate media bus frame sizes</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_subdev_frame_size_enum *
- <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_SUBDEV_ENUM_FRAME_SIZE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>This ioctl allows applications to enumerate all frame sizes
- supported by a sub-device on the given pad for the given media bus format.
- Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
- ioctl.</para>
-
- <para>To enumerate frame sizes applications initialize the
- <structfield>pad</structfield>, <structfield>which</structfield> ,
- <structfield>code</structfield> and <structfield>index</structfield>
- fields of the &v4l2-subdev-mbus-code-enum; and call the
- <constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant> ioctl with a pointer to
- the structure. Drivers fill the minimum and maximum frame sizes or return
- an &EINVAL; if one of the input parameters is invalid.</para>
-
- <para>Sub-devices that only support discrete frame sizes (such as most
- sensors) will return one or more frame sizes with identical minimum and
- maximum values.</para>
-
- <para>Not all possible sizes in given [minimum, maximum] ranges need to be
- supported. For instance, a scaler that uses a fixed-point scaling ratio
- might not be able to produce every frame size between the minimum and
- maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to
- try the sub-device for an exact supported frame size.</para>
-
- <para>Available frame sizes may depend on the current 'try' formats at other
- pads of the sub-device, as well as on the current active links and the
- current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more
- information about try formats.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-frame-size-enum">
- <title>struct <structname>v4l2_subdev_frame_size_enum</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the format in the enumeration, set by the
- application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>code</structfield></entry>
- <entry>The media bus format code, as defined in
- <xref linkend="v4l2-mbus-format" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_width</structfield></entry>
- <entry>Minimum frame width, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_width</structfield></entry>
- <entry>Maximum frame width, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>min_height</structfield></entry>
- <entry>Minimum frame height, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>max_height</structfield></entry>
- <entry>Maximum frame height, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Frame sizes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-frame-size-enum; <structfield>pad</structfield>
- references a non-existing pad, the <structfield>code</structfield> is
- invalid for the given pad or the <structfield>index</structfield>
- field is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
deleted file mode 100644
index c67256ada87a..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<refentry id="vidioc-subdev-enum-mbus-code">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_ENUM_MBUS_CODE</refname>
- <refpurpose>Enumerate media bus formats</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_subdev_mbus_code_enum *
- <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_SUBDEV_ENUM_MBUS_CODE</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>To enumerate media bus formats available at a given sub-device pad
- applications initialize the <structfield>pad</structfield>, <structfield>which</structfield>
- and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
- call the <constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant> ioctl with a
- pointer to this structure. Drivers fill the rest of the structure or return
- an &EINVAL; if either the <structfield>pad</structfield> or
- <structfield>index</structfield> are invalid. All media bus formats are
- enumerable by beginning at index zero and incrementing by one until
- <errorcode>EINVAL</errorcode> is returned.</para>
-
- <para>Available media bus formats may depend on the current 'try' formats
- at other pads of the sub-device, as well as on the current active links. See
- &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-mbus-code-enum">
- <title>struct <structname>v4l2_subdev_mbus_code_enum</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>index</structfield></entry>
- <entry>Number of the format in the enumeration, set by the
- application.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>code</structfield></entry>
- <entry>The media bus format code, as defined in
- <xref linkend="v4l2-mbus-format" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Media bus format codes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-mbus-code-enum; <structfield>pad</structfield>
- references a non-existing pad, or the <structfield>index</structfield>
- field is out of bounds.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml
deleted file mode 100644
index 4cddd788c589..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-crop.xml
+++ /dev/null
@@ -1,158 +0,0 @@
-<refentry id="vidioc-subdev-g-crop">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_G_CROP</refname>
- <refname>VIDIOC_SUBDEV_S_CROP</refname>
- <refpurpose>Get or set the crop rectangle on a subdev pad</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_subdev_crop *<parameter>argp</parameter></paramdef>
- </funcprototype>
- </funcsynopsis>
- <funcsynopsis>
- <funcprototype>
- <funcdef>int <function>ioctl</function></funcdef>
- <paramdef>int <parameter>fd</parameter></paramdef>
- <paramdef>int <parameter>request</parameter></paramdef>
- <paramdef>const struct v4l2_subdev_crop *<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_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <note>
- <title>Obsolete</title>
-
- <para>This is an <link linkend="obsolete">obsolete</link>
- interface and may be removed in the future. It is superseded by
- <link linkend="vidioc-subdev-g-selection">the selection
- API</link>.</para>
- </note>
-
- <para>To retrieve the current crop rectangle applications set the
- <structfield>pad</structfield> field of a &v4l2-subdev-crop; to the
- desired pad number as reported by the media API and the
- <structfield>which</structfield> field to
- <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. They then call the
- <constant>VIDIOC_SUBDEV_G_CROP</constant> ioctl with a pointer to this
- structure. The driver fills the members of the <structfield>rect</structfield>
- field or returns &EINVAL; if the input arguments are invalid, or if cropping
- is not supported on the given pad.</para>
-
- <para>To change the current crop rectangle applications set both the
- <structfield>pad</structfield> and <structfield>which</structfield> fields
- and all members of the <structfield>rect</structfield> field. They then call
- the <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctl with a pointer to this
- structure. The driver verifies the requested crop rectangle, adjusts it
- based on the hardware capabilities and configures the device. Upon return
- the &v4l2-subdev-crop; contains the current format as would be returned
- by a <constant>VIDIOC_SUBDEV_G_CROP</constant> call.</para>
-
- <para>Applications can query the device capabilities by setting the
- <structfield>which</structfield> to
- <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' crop
- rectangles are not applied to the device by the driver, but are mangled
- exactly as active crop rectangles and stored in the sub-device file handle.
- Two applications querying the same sub-device would thus not interact with
- each other.</para>
-
- <para>Drivers must not return an error solely because the requested crop
- rectangle doesn't match the device capabilities. They must instead modify
- the rectangle to match what the hardware can provide. The modified format
- should be as close as possible to the original request.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-crop">
- <title>struct <structname>v4l2_subdev_crop</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media framework.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Crop rectangle to get or set, from
- &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>rect</structfield></entry>
- <entry>Crop rectangle boundaries, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The crop rectangle can't be changed because the pad is currently
- busy. This can be caused, for instance, by an active video stream on
- the pad. The ioctl must not be retried without performing another
- action to fix the problem first. Only returned by
- <constant>VIDIOC_SUBDEV_S_CROP</constant></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-crop; <structfield>pad</structfield>
- references a non-existing pad, the <structfield>which</structfield>
- field references a non-existing format, or cropping is not supported
- on the given subdev pad.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
deleted file mode 100644
index 781089cba453..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-fmt.xml
+++ /dev/null
@@ -1,177 +0,0 @@
-<refentry id="vidioc-subdev-g-fmt">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_G_FMT</refname>
- <refname>VIDIOC_SUBDEV_S_FMT</refname>
- <refpurpose>Get or set the data format on a subdev pad</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_subdev_format *<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_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls are used to negotiate the frame format at specific
- subdev pads in the image pipeline.</para>
-
- <para>To retrieve the current format applications set the
- <structfield>pad</structfield> field of a &v4l2-subdev-format; to the
- desired pad number as reported by the media API and the
- <structfield>which</structfield> field to
- <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. When they call the
- <constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl with a pointer to this
- structure the driver fills the members of the <structfield>format</structfield>
- field.</para>
-
- <para>To change the current format applications set both the
- <structfield>pad</structfield> and <structfield>which</structfield> fields
- and all members of the <structfield>format</structfield> field. When they
- call the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl with a pointer to this
- structure the driver verifies the requested format, adjusts it based on the
- hardware capabilities and configures the device. Upon return the
- &v4l2-subdev-format; contains the current format as would be returned by a
- <constant>VIDIOC_SUBDEV_G_FMT</constant> call.</para>
-
- <para>Applications can query the device capabilities by setting the
- <structfield>which</structfield> to
- <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' formats are not
- applied to the device by the driver, but are changed exactly as active
- formats and stored in the sub-device file handle. Two applications querying
- the same sub-device would thus not interact with each other.</para>
-
- <para>For instance, to try a format at the output pad of a sub-device,
- applications would first set the try format at the sub-device input with the
- <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl. They would then either
- retrieve the default format at the output pad with the
- <constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl, or set the desired output
- pad format with the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl and check
- the returned value.</para>
-
- <para>Try formats do not depend on active formats, but can depend on the
- current links configuration or sub-device controls value. For instance, a
- low-pass noise filter might crop pixels at the frame boundaries, modifying
- its output frame size.</para>
-
- <para>Drivers must not return an error solely because the requested format
- doesn't match the device capabilities. They must instead modify the format
- to match what the hardware can provide. The modified format should be as
- close as possible to the original request.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-format">
- <title>struct <structname>v4l2_subdev_format</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Format to modified, from &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>&v4l2-mbus-framefmt;</entry>
- <entry><structfield>format</structfield></entry>
- <entry>Definition of an image format, see <xref
- linkend="v4l2-mbus-framefmt" /> for details.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-format-whence">
- <title>enum <structname>v4l2_subdev_format_whence</structname></title>
- <tgroup cols="3">
- &cs-def;
- <tbody valign="top">
- <row>
- <entry>V4L2_SUBDEV_FORMAT_TRY</entry>
- <entry>0</entry>
- <entry>Try formats, used for querying device capabilities.</entry>
- </row>
- <row>
- <entry>V4L2_SUBDEV_FORMAT_ACTIVE</entry>
- <entry>1</entry>
- <entry>Active formats, applied to the hardware.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The format can't be changed because the pad is currently busy.
- This can be caused, for instance, by an active video stream on the
- pad. The ioctl must not be retried without performing another action
- to fix the problem first. Only returned by
- <constant>VIDIOC_SUBDEV_S_FMT</constant></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-format; <structfield>pad</structfield>
- references a non-existing pad, or the <structfield>which</structfield>
- field references a non-existing format.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
deleted file mode 100644
index 848ec789ddaa..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-frame-interval.xml
+++ /dev/null
@@ -1,135 +0,0 @@
-<refentry id="vidioc-subdev-g-frame-interval">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname>
- <refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname>
- <refpurpose>Get or set the frame interval on a subdev pad</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_subdev_frame_interval *<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_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>These ioctls are used to get and set the frame interval at specific
- subdev pads in the image pipeline. The frame interval only makes sense for
- sub-devices that can control the frame period on their own. This includes,
- for instance, image sensors and TV tuners. Sub-devices that don't support
- frame intervals must not implement these ioctls.</para>
-
- <para>To retrieve the current frame interval applications set the
- <structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to
- the desired pad number as reported by the media controller API. When they
- call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a
- pointer to this structure the driver fills the members of the
- <structfield>interval</structfield> field.</para>
-
- <para>To change the current frame interval applications set both the
- <structfield>pad</structfield> field and all members of the
- <structfield>interval</structfield> field. When they call the
- <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to
- this structure the driver verifies the requested interval, adjusts it based
- on the hardware capabilities and configures the device. Upon return the
- &v4l2-subdev-frame-interval; contains the current frame interval as would be
- returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call.
- </para>
-
- <para>Drivers must not return an error solely because the requested interval
- doesn't match the device capabilities. They must instead modify the interval
- to match what the hardware can provide. The modified interval should be as
- close as possible to the original request.</para>
-
- <para>Sub-devices that support the frame interval ioctls should implement
- them on a single pad only. Their behaviour when supported on multiple pads
- of the same sub-device is not defined.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval">
- <title>struct <structname>v4l2_subdev_frame_interval</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media controller API.</entry>
- </row>
- <row>
- <entry>&v4l2-fract;</entry>
- <entry><structfield>interval</structfield></entry>
- <entry>Period, in seconds, between consecutive video frames.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[9]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The frame interval can't be changed because the pad is currently
- busy. This can be caused, for instance, by an active video stream on
- the pad. The ioctl must not be retried without performing another
- action to fix the problem first. Only returned by
- <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield>
- references a non-existing pad, or the pad doesn't support frame
- intervals.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
deleted file mode 100644
index 8346b2e4a703..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
+++ /dev/null
@@ -1,159 +0,0 @@
-<refentry id="vidioc-subdev-g-selection">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBDEV_G_SELECTION, VIDIOC_SUBDEV_S_SELECTION</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBDEV_G_SELECTION</refname>
- <refname>VIDIOC_SUBDEV_S_SELECTION</refname>
- <refpurpose>Get or set selection rectangles on a subdev pad</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_subdev_selection *<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_SUBDEV_G_SELECTION, VIDIOC_SUBDEV_S_SELECTION</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><parameter>argp</parameter></term>
- <listitem>
- <para></para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
-
- <para>The selections are used to configure various image
- processing functionality performed by the subdevs which affect the
- image size. This currently includes cropping, scaling and
- composition.</para>
-
- <para>The selection API replaces <link
- linkend="vidioc-subdev-g-crop">the old subdev crop API</link>. All
- the function of the crop API, and more, are supported by the
- selections API.</para>
-
- <para>See <xref linkend="subdev"></xref> for
- more information on how each selection target affects the image
- processing pipeline inside the subdevice.</para>
-
- <refsect2>
- <title>Types of selection targets</title>
-
- <para>There are two types of selection targets: actual and bounds. The
- actual targets are the targets which configure the hardware. The BOUNDS
- target will return a rectangle that contain all possible actual
- rectangles.</para>
- </refsect2>
-
- <refsect2>
- <title>Discovering supported features</title>
-
- <para>To discover which targets are supported, the user can
- perform <constant>VIDIOC_SUBDEV_G_SELECTION</constant> on them.
- Any unsupported target will return
- <constant>EINVAL</constant>.</para>
-
- <para>Selection targets and flags are documented in <xref
- linkend="v4l2-selections-common"/>.</para>
-
- <table pgwide="1" frame="none" id="v4l2-subdev-selection">
- <title>struct <structname>v4l2_subdev_selection</structname></title>
- <tgroup cols="3">
- &cs-str;
- <tbody valign="top">
- <row>
- <entry>__u32</entry>
- <entry><structfield>which</structfield></entry>
- <entry>Active or try selection, from
- &v4l2-subdev-format-whence;.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>pad</structfield></entry>
- <entry>Pad number as reported by the media framework.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>target</structfield></entry>
- <entry>Target selection rectangle. See
- <xref linkend="v4l2-selections-common" />.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>flags</structfield></entry>
- <entry>Flags. See
- <xref linkend="v4l2-selection-flags" />.</entry>
- </row>
- <row>
- <entry>&v4l2-rect;</entry>
- <entry><structfield>r</structfield></entry>
- <entry>Selection rectangle, in pixels.</entry>
- </row>
- <row>
- <entry>__u32</entry>
- <entry><structfield>reserved</structfield>[8]</entry>
- <entry>Reserved for future extensions. Applications and drivers must
- set the array to zero.</entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </refsect2>
-
- </refsect1>
-
- <refsect1>
- &return-value;
-
- <variablelist>
- <varlistentry>
- <term><errorcode>EBUSY</errorcode></term>
- <listitem>
- <para>The selection rectangle can't be changed because the
- pad is currently busy. This can be caused, for instance, by
- an active video stream on the pad. The ioctl must not be
- retried without performing another action to fix the problem
- first. Only returned by
- <constant>VIDIOC_SUBDEV_S_SELECTION</constant></para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><errorcode>EINVAL</errorcode></term>
- <listitem>
- <para>The &v4l2-subdev-selection;
- <structfield>pad</structfield> references a non-existing
- pad, the <structfield>which</structfield> field references a
- non-existing format, or the selection target is not
- supported on the given subdev pad.</para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
deleted file mode 100644
index 5fd0ee78f880..000000000000
--- a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
+++ /dev/null
@@ -1,130 +0,0 @@
-<refentry id="vidioc-subscribe-event">
- <refmeta>
- <refentrytitle>ioctl VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refentrytitle>
- &manvol;
- </refmeta>
-
- <refnamediv>
- <refname>VIDIOC_SUBSCRIBE_EVENT</refname>
- <refname>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, see <xref linkend="event-type" />. Note that
-<constant>V4L2_EVENT_ALL</constant> can be used with VIDIOC_UNSUBSCRIBE_EVENT
-for unsubscribing all events at once.</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 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>
-
- </refsect1>
- <refsect1>
- &return-value;
- </refsect1>
-</refentry>
diff --git a/Documentation/DocBook/media/vbi_525.gif.b64 b/Documentation/DocBook/media/vbi_525.gif.b64
deleted file mode 100644
index d5dcf06f2aef..000000000000
--- a/Documentation/DocBook/media/vbi_525.gif.b64
+++ /dev/null
@@ -1,84 +0,0 @@
-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
deleted file mode 100644
index 831f49a02821..000000000000
--- a/Documentation/DocBook/media/vbi_625.gif.b64
+++ /dev/null
@@ -1,90 +0,0 @@
-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
deleted file mode 100644
index cdafabed5c11..000000000000
--- a/Documentation/DocBook/media/vbi_hsync.gif.b64
+++ /dev/null
@@ -1,43 +0,0 @@
-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
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl
deleted file mode 100644
index a2765d8ad05c..000000000000
--- a/Documentation/DocBook/media_api.tmpl
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
- "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
-<!ENTITY % media-entities SYSTEM "./media-entities.tmpl"> %media-entities;
-<!ENTITY media-indices SYSTEM "./media-indices.tmpl">
-
-<!ENTITY eg "e.&nbsp;g.">
-<!ENTITY ie "i.&nbsp;e.">
-<!ENTITY fd "File descriptor returned by <link linkend='func-open'><function>open()</function></link>.">
-<!ENTITY fe_fd "File descriptor returned by <link linkend='frontend_f_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. 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. -->
-<!ENTITY cs-str "<colspec colname='c1' colwidth='1*' /><colspec colname='c2' colwidth='1*' /><colspec colname='c3' colwidth='2*' /><spanspec spanname='hspan' namest='c1' nameend='c3' />">
-<!ENTITY cs-ustr "<colspec colname='c1' colwidth='1*' /><colspec colname='c2' colwidth='1*' /><colspec colname='c3' colwidth='1*' /><colspec colname='c4' colwidth='2*' /><spanspec spanname='hspan' namest='c1' nameend='c4' />">
-<!ENTITY cs-def "<colspec colname='c1' colwidth='3*' /><colspec colname='c2' colwidth='1*' /><colspec colname='c3' colwidth='4*' /><spanspec spanname='hspan' namest='c1' nameend='c3' />">
-
-<!-- Video for Linux mailing list address. -->
-<!ENTITY v4l-ml "<ulink url='https://linuxtv.org/lists.php'>https://linuxtv.org/lists.php</ulink>">
-
-<!-- LinuxTV v4l-dvb repository. -->
-<!ENTITY v4l-dvb "<ulink url='https://linuxtv.org/repo/'>https://linuxtv.org/repo/</ulink>">
-<!ENTITY dash-ent-8 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-10 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-12 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-14 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-16 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-20 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-22 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-<!ENTITY dash-ent-24 "<entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry><entry>-</entry>">
-]>
-
-<book id="media_api" lang="en">
-<bookinfo>
- <title>LINUX MEDIA INFRASTRUCTURE API</title>
-
- <copyright>
- <year>2009-2015</year>
- <holder>LinuxTV Developers</holder>
- </copyright>
-
- <legalnotice>
- <para>Permission is granted to copy, distribute and/or modify
- this document under the terms of the GNU Free Documentation License,
- Version 1.1 or any later version published by the Free Software
- Foundation. A copy of the license is included in the chapter entitled
- "GNU Free Documentation License"</para>
- </legalnotice>
-</bookinfo>
-
-<toc></toc> <!-- autogenerated -->
-
-<preface>
- <title>Introduction</title>
-
- <para>This document covers the Linux Kernel to Userspace API's used by
- video and radio streaming devices, including video cameras,
- analog and digital TV receiver cards, AM/FM receiver cards,
- streaming capture and output devices, codec devices and remote
- controllers.</para>
- <para>A typical media device hardware is shown at
- <xref linkend="typical_media_device" />.</para>
- <figure id="typical_media_device">
- <title>Typical Media Device</title>
- <mediaobject>
- <imageobject>
- <imagedata fileref="typical_media_device.svg" format="SVG" />
- </imageobject>
- <textobject>
- <phrase>Typical Media Device Block Diagram</phrase>
- </textobject>
- </mediaobject>
- </figure>
- <para>The media infrastructure API was designed to control such
- devices. It is divided into five parts.</para>
- <para>The first part covers radio, video capture and output,
- cameras, analog TV devices and codecs.</para>
- <para>The second part covers the
- API used for digital TV and Internet reception via one of the
- several digital tv standards. While it is called as DVB API,
- in fact it covers several different video standards including
- DVB-T/T2, DVB-S/S2, DVB-C, ATSC, ISDB-T, ISDB-S,etc. The complete
- list of supported standards can be found at
- <xref linkend="fe-delivery-system-t" />.</para>
- <para>The third part covers the Remote Controller API.</para>
- <para>The fourth part covers the Media Controller API.</para>
- <para>The fifth part covers the CEC (Consumer Electronics Control) API.</para>
- <para>It should also be noted that a media device may also have audio
- components, like mixers, PCM capture, PCM playback, etc, which
- are controlled via ALSA API.</para>
- <para>For additional information and for the latest development code,
- see: <ulink url="https://linuxtv.org">https://linuxtv.org</ulink>.</para>
- <para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
-</preface>
-
-<part id="v4l2spec">
-&sub-v4l2;
-</part>
-<part id="dvbapi">
-&sub-dvbapi;
-</part>
-<part id="remotes">
-&sub-remote_controllers;
-</part>
-<part id="media_common">
-&sub-media-controller;
-</part>
-<part id="cec">
-&sub-cec-api;
-</part>
-
-<chapter id="gen_errors">
-&sub-gen-errors;
-</chapter>
-
-&sub-fdl-appendix;
-
-</book>
diff --git a/Documentation/Makefile.sphinx b/Documentation/Makefile.sphinx
index fd565e1f1368..857f1e273418 100644
--- a/Documentation/Makefile.sphinx
+++ b/Documentation/Makefile.sphinx
@@ -63,11 +63,12 @@ sgmldocs:
psdocs:
mandocs:
installmandocs:
-cleanmediadocs:
cleandocs:
$(Q)rm -rf $(BUILDDIR)
+endif # HAVE_SPHINX
+
dochelp:
@echo ' Linux kernel internal documentation in different formats (Sphinx):'
@echo ' htmldocs - HTML'
@@ -75,5 +76,3 @@ dochelp:
@echo ' epubdocs - EPUB'
@echo ' xmldocs - XML'
@echo ' cleandocs - clean all generated files'
-
-endif # HAVE_SPHINX
diff --git a/Documentation/binfmt_misc.txt b/Documentation/binfmt_misc.txt
index 6b1de7058371..ec83bbce547a 100644
--- a/Documentation/binfmt_misc.txt
+++ b/Documentation/binfmt_misc.txt
@@ -66,6 +66,13 @@ Here is what the fields mean:
This feature should be used with care as the interpreter
will run with root permissions when a setuid binary owned by root
is run with binfmt_misc.
+ 'F' - fix binary. The usual behaviour of binfmt_misc is to spawn the
+ binary lazily when the misc format file is invoked. However,
+ this doesn't work very well in the face of mount namespaces and
+ changeroots, so the F mode opens the binary as soon as the
+ emulation is installed and uses the opened image to spawn the
+ emulator, meaning it is always available once installed,
+ regardless of how the environment changes.
There are some restrictions:
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 026d13362aca..bcdb2b4c1f12 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -269,7 +269,7 @@ Arjan's proposed request priority scheme allows higher levels some broad
requests which haven't aged too much on the queue. Potentially this priority
could even be exposed to applications in some manner, providing higher level
tunability. Time based aging avoids starvation of lower priority
- requests. Some bits in the bi_rw flags field in the bio structure are
+ requests. Some bits in the bi_opf flags field in the bio structure are
intended to be used for this priority information.
@@ -432,7 +432,7 @@ struct bio {
struct bio *bi_next; /* request queue link */
struct block_device *bi_bdev; /* target device */
unsigned long bi_flags; /* status, command, etc */
- unsigned long bi_rw; /* low bits: r/w, high: priority */
+ unsigned long bi_opf; /* low bits: r/w, high: priority */
unsigned int bi_vcnt; /* how may bio_vec's */
struct bvec_iter bi_iter; /* current index into bio_vec array */
diff --git a/Documentation/block/queue-sysfs.txt b/Documentation/block/queue-sysfs.txt
index d515d58962b9..2a3904030dea 100644
--- a/Documentation/block/queue-sysfs.txt
+++ b/Documentation/block/queue-sysfs.txt
@@ -14,6 +14,12 @@ add_random (RW)
This file allows to turn off the disk entropy contribution. Default
value of this file is '1'(on).
+dax (RO)
+--------
+This file indicates whether the device supports Direct Access (DAX),
+used by CPU-addressable storage to bypass the pagecache. It shows '1'
+if true, '0' if not.
+
discard_granularity (RO)
-----------------------
This shows the size of internal allocation of the device in bytes, if
@@ -46,6 +52,12 @@ hw_sector_size (RO)
-------------------
This is the hardware sector size of the device, in bytes.
+io_poll (RW)
+------------
+When read, this file shows the total number of block IO polls and how
+many returned success. Writing '0' to this file will disable polling
+for this device. Writing any non-zero value will enable this feature.
+
iostats (RW)
-------------
This file is used to control (on/off) the iostats accounting of the
@@ -151,5 +163,11 @@ device state. This means that it might not be safe to toggle the
setting from "write back" to "write through", since that will also
eliminate cache flushes issued by the kernel.
+write_same_max_bytes (RO)
+-------------------------
+This is the number of bytes the device can write in a single write-same
+command. A value of '0' means write-same is not supported by this
+device.
+
Jens Axboe <jens.axboe@oracle.com>, February 2009
diff --git a/Documentation/cgroup-v1/cgroups.txt b/Documentation/cgroup-v1/cgroups.txt
index 947e6fe31ef9..308e5ff7207a 100644
--- a/Documentation/cgroup-v1/cgroups.txt
+++ b/Documentation/cgroup-v1/cgroups.txt
@@ -2,7 +2,7 @@
-------
Written by Paul Menage <menage@google.com> based on
-Documentation/cgroups/cpusets.txt
+Documentation/cgroup-v1/cpusets.txt
Original copyright statements from cpusets.txt:
Portions Copyright (C) 2004 BULL SA.
@@ -72,7 +72,7 @@ On their own, the only use for cgroups is for simple job
tracking. The intention is that other subsystems hook into the generic
cgroup support to provide new attributes for cgroups, such as
accounting/limiting the resources which processes in a cgroup can
-access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allow
+access. For example, cpusets (see Documentation/cgroup-v1/cpusets.txt) allow
you to associate a set of CPUs and a set of memory nodes with the
tasks in each cgroup.
diff --git a/Documentation/cgroup-v1/cpusets.txt b/Documentation/cgroup-v1/cpusets.txt
index e5cdcd445615..e5ac5da86682 100644
--- a/Documentation/cgroup-v1/cpusets.txt
+++ b/Documentation/cgroup-v1/cpusets.txt
@@ -48,7 +48,7 @@ hooks, beyond what is already present, required to manage dynamic
job placement on large systems.
Cpusets use the generic cgroup subsystem described in
-Documentation/cgroups/cgroups.txt.
+Documentation/cgroup-v1/cgroups.txt.
Requests by a task, using the sched_setaffinity(2) system call to
include CPUs in its CPU affinity mask, and using the mbind(2) and
diff --git a/Documentation/cgroup-v1/memcg_test.txt b/Documentation/cgroup-v1/memcg_test.txt
index 78a8c2963b38..5c7f310f32bb 100644
--- a/Documentation/cgroup-v1/memcg_test.txt
+++ b/Documentation/cgroup-v1/memcg_test.txt
@@ -6,7 +6,7 @@ Because VM is getting complex (one of reasons is memcg...), memcg's behavior
is complex. This is a document for memcg's internal behavior.
Please note that implementation details can be changed.
-(*) Topics on API should be in Documentation/cgroups/memory.txt)
+(*) Topics on API should be in Documentation/cgroup-v1/memory.txt)
0. How to record usage ?
2 objects are used.
@@ -256,7 +256,7 @@ Under below explanation, we assume CONFIG_MEM_RES_CTRL_SWAP=y.
You can see charges have been moved by reading *.usage_in_bytes or
memory.stat of both A and B.
- See 8.2 of Documentation/cgroups/memory.txt to see what value should be
+ See 8.2 of Documentation/cgroup-v1/memory.txt to see what value should be
written to move_charge_at_immigrate.
9.10 Memory thresholds
diff --git a/Documentation/device-mapper/dm-flakey.txt b/Documentation/device-mapper/dm-flakey.txt
index 6ff5c2327227..c43030718cef 100644
--- a/Documentation/device-mapper/dm-flakey.txt
+++ b/Documentation/device-mapper/dm-flakey.txt
@@ -42,7 +42,7 @@ Optional feature parameters:
<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
+ <flags>: Perform the replacement only if bio->bi_opf has all the
selected flags set.
Examples:
diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
index 6c9f0c8a846c..e85ce3dea480 100644
--- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
@@ -20,6 +20,8 @@ Optional properties:
2: Half-period mode
4: Quarter-period mode
- wakeup-source: Boolean, rotary encoder can wake up the system.
+- rotary-encoder,encoding: String, the method used to encode steps.
+ Supported are "gray" (the default and more common) and "binary".
Deprecated properties:
- rotary-encoder,half-period: Makes the driver work on half-period mode.
@@ -34,6 +36,7 @@ Example:
compatible = "rotary-encoder";
gpios = <&gpio 19 1>, <&gpio 20 0>; /* GPIO19 is inverted */
linux,axis = <0>; /* REL_X */
+ rotary-encoder,encoding = "gray";
rotary-encoder,relative-axis;
};
@@ -42,5 +45,6 @@ Example:
gpios = <&gpio 21 0>, <&gpio 22 0>;
linux,axis = <1>; /* ABS_Y */
rotary-encoder,steps = <24>;
+ rotary-encoder,encoding = "binary";
rotary-encoder,rollover;
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
new file mode 100644
index 000000000000..1112e0d794e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
@@ -0,0 +1,36 @@
+* GSL 1680 touchscreen controller
+
+Required properties:
+- compatible : "silead,gsl1680"
+- reg : I2C slave address of the chip (0x40)
+- interrupt-parent : a phandle pointing to the interrupt controller
+ serving the interrupt for this chip
+- interrupts : interrupt specification for the gsl1680 interrupt
+- power-gpios : Specification for the pin connected to the gsl1680's
+ shutdown input. This needs to be driven high to take the
+ gsl1680 out of its low power state
+- touchscreen-size-x : See touchscreen.txt
+- touchscreen-size-y : See touchscreen.txt
+
+Optional properties:
+- touchscreen-inverted-x : See touchscreen.txt
+- touchscreen-inverted-y : See touchscreen.txt
+- touchscreen-swapped-x-y : See touchscreen.txt
+- silead,max-fingers : maximum number of fingers the touchscreen can detect
+
+Example:
+
+i2c@00000000 {
+ gsl1680: touchscreen@40 {
+ compatible = "silead,gsl1680";
+ reg = <0x40>;
+ interrupt-parent = <&pio>;
+ interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>;
+ power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <800>;
+ touchscreen-inverted-x;
+ touchscreen-swapped-x-y;
+ silead,max-fingers = <5>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt
new file mode 100644
index 000000000000..d87ad14f1efe
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt
@@ -0,0 +1,33 @@
+* SiS I2C Multiple Touch Controller
+
+Required properties:
+- compatible: must be "sis,9200-ts"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+ (see interrupt binding [0])
+- interrupts: touch controller interrupt (see interrupt
+ binding [0])
+
+Optional properties:
+- pinctrl-names: should be "default" (see pinctrl binding [1]).
+- pinctrl-0: a phandle pointing to the pin settings for the
+ device (see pinctrl binding [1]).
+- attn-gpios: the gpio pin used as attention line
+- reset-gpios: the gpio pin used to reset the controller
+- wakeup-source: touchscreen can be used as a wakeup source
+
+[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+[1]: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+Example:
+
+ sis9255@5c {
+ compatible = "sis,9200-ts";
+ reg = <0x5c>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_sis>;
+ interrupt-parent = <&gpio3>;
+ interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
+ irq-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio2 30 GPIO_ACTIVE_LOW>;
+ };
diff --git a/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
new file mode 100644
index 000000000000..21f75bbd6dae
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
@@ -0,0 +1,21 @@
+Broadcom iProc PWM controller device tree bindings
+
+This controller has 4 channels.
+
+Required Properties :
+- compatible: must be "brcm,iproc-pwm"
+- reg: physical base address and length of the controller's registers
+- clocks: phandle + clock specifier pair for the external clock
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a
+ description of the cells format.
+
+Refer to clocks/clock-bindings.txt for generic clock consumer properties.
+
+Example:
+
+pwm: pwm@18031000 {
+ compatible = "brcm,iproc-pwm";
+ reg = <0x18031000 0x28>;
+ clocks = <&osc>;
+ #pwm-cells = <3>;
+};
diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
new file mode 100644
index 000000000000..472bd46ab5a4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
@@ -0,0 +1,23 @@
+* PWM controlled by ChromeOS EC
+
+Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller
+(EC) and controlled via a host-command interface.
+
+An EC PWM node should be only found as a sub-node of the EC node (see
+Documentation/devicetree/bindings/mfd/cros-ec.txt).
+
+Required properties:
+- compatible: Must contain "google,cros-ec-pwm"
+- #pwm-cells: Should be 1. The cell specifies the PWM index.
+
+Example:
+ cros-ec@0 {
+ compatible = "google,cros-ec-spi";
+
+ ...
+
+ cros_ec_pwm: ec-pwm {
+ compatible = "google,cros-ec-pwm";
+ #pwm-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
index c52f03b5032f..b4e73778dda3 100644
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
@@ -1,10 +1,14 @@
Tegra SoC PWFM controller
Required properties:
-- compatible: For Tegra20, must contain "nvidia,tegra20-pwm". For Tegra30,
- must contain "nvidia,tegra30-pwm". Otherwise, must contain
- "nvidia,<chip>-pwm", plus one of the above, where <chip> is tegra114,
- tegra124, tegra132, or tegra210.
+- compatible: Must be:
+ - "nvidia,tegra20-pwm": for Tegra20
+ - "nvidia,tegra30-pwm", "nvidia,tegra20-pwm": for Tegra30
+ - "nvidia,tegra114-pwm", "nvidia,tegra20-pwm": for Tegra114
+ - "nvidia,tegra124-pwm", "nvidia,tegra20-pwm": for Tegra124
+ - "nvidia,tegra132-pwm", "nvidia,tegra20-pwm": for Tegra132
+ - "nvidia,tegra210-pwm", "nvidia,tegra20-pwm": for Tegra210
+ - "nvidia,tegra186-pwm": for Tegra186
- reg: physical base address and length of the controller's registers
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
the cells format.
diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
index 0822a083fc57..d6de64335022 100644
--- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
+++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt
@@ -7,6 +7,7 @@ Required Properties:
- "renesas,pwm-r8a7790": for R-Car H2
- "renesas,pwm-r8a7791": for R-Car M2-W
- "renesas,pwm-r8a7794": for R-Car E2
+ - "renesas,pwm-r8a7795": for R-Car H3
- reg: base address and length of the registers block for the PWM.
- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
the cells format.
diff --git a/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt b/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
new file mode 100644
index 000000000000..cb209646bf13
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/st,stmpe-pwm.txt
@@ -0,0 +1,18 @@
+== ST STMPE PWM controller ==
+
+This is a PWM block embedded in the ST Microelectronics STMPE
+(ST Multi-Purpose Expander) chips. The PWM is registered as a
+subdevices of the STMPE MFD device.
+
+Required properties:
+- compatible: should be:
+ - "st,stmpe-pwm"
+- #pwm-cells: should be 2. See pwm.txt in this directory for a description of
+ the cells format.
+
+Example:
+
+pwm0: pwm {
+ compatible = "st,stmpe-pwm";
+ #pwm-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
index dd6f59cf1455..3aeba9f86ed8 100644
--- a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
@@ -34,6 +34,18 @@ Only required for Voltage Table Mode:
First cell is voltage in microvolts (uV)
Second cell is duty-cycle in percent (%)
+Optional properties for Continuous mode:
+- pwm-dutycycle-unit: Integer value encoding the duty cycle unit. If not
+ defined, <100> is assumed, meaning that
+ pwm-dutycycle-range contains values expressed in
+ percent.
+
+- pwm-dutycycle-range: Should contain 2 entries. The first entry is encoding
+ the dutycycle for regulator-min-microvolt and the
+ second one the dutycycle for regulator-max-microvolt.
+ Duty cycle values are expressed in pwm-dutycycle-unit.
+ If not defined, <0 100> is assumed.
+
NB: To be clear, if voltage-table is provided, then the device will be used
in Voltage Table Mode. If no voltage-table is provided, then the device will
be used in Continuous Voltage Mode.
@@ -53,6 +65,13 @@ Continuous Voltage With Enable GPIO Example:
regulator-min-microvolt = <1016000>;
regulator-max-microvolt = <1114000>;
regulator-name = "vdd_logic";
+ /* unit == per-mille */
+ pwm-dutycycle-unit = <1000>;
+ /*
+ * Inverted PWM logic, and the duty cycle range is limited
+ * to 30%-70%.
+ */
+ pwm-dutycycle-range <700 300>; /* */
};
Voltage Table Example:
diff --git a/Documentation/devicetree/bindings/misc/ramoops.txt b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
index cd02cec67d38..e81f821a2135 100644
--- a/Documentation/devicetree/bindings/misc/ramoops.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
@@ -2,8 +2,9 @@ Ramoops oops/panic logger
=========================
ramoops provides persistent RAM storage for oops and panics, so they can be
-recovered after a reboot. It is a backend to pstore, so this node is named
-"ramoops" after the backend, rather than "pstore" which is the subsystem.
+recovered after a reboot. This is a child-node of "/reserved-memory", and
+is named "ramoops" after the backend, rather than "pstore" which is the
+subsystem.
Parts of this storage may be set aside for other persistent log buffers, such
as kernel log messages, or for optional ECC error-correction data. The total
@@ -21,8 +22,7 @@ Required properties:
- compatible: must be "ramoops"
-- memory-region: phandle to a region of memory that is preserved between
- reboots
+- reg: region of memory that is preserved between reboots
Optional properties:
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 68391a462c0a..1992aa97d45a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -238,6 +238,7 @@ simtek
sii Seiko Instruments, Inc.
silergy Silergy Corp.
sirf SiRF Technology, Inc.
+sis Silicon Integrated Systems Corp.
sitronix Sitronix Technology Corporation
skyworks Skyworks Solutions, Inc.
smsc Standard Microsystems Corporation
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 1b3c39a7de62..d30fb2cb5066 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -12,7 +12,7 @@ prototypes:
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
- int (*d_compare)(const struct dentry *, const struct dentry *,
+ int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(struct dentry *);
int (*d_init)(struct dentry *);
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index a5fb89cac615..b1bd05ea66b2 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -585,3 +585,10 @@ in your dentry operations instead.
in the instances. Rationale: !@#!@# security_d_instantiate() needs to be
called before we attach dentry to inode and !@#!@##!@$!$#!@#$!@$!@$ smack
->d_instantiate() uses not just ->getxattr() but ->setxattr() as well.
+--
+[mandatory]
+ ->d_compare() doesn't get parent as a separate argument anymore. If you
+ used it for finding the struct super_block involved, dentry->d_sb will
+ work just as well; if it's something more complicated, use dentry->d_parent.
+ Just be careful not to assume that fetching it more than once will yield
+ the same value - in RCU mode it could change under you.
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index d9c11d25bf02..a85355cf85f4 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -98,7 +98,7 @@ A memory policy with a valid NodeList will be saved, as specified, for
use at file creation time. When a task allocates a file in the file
system, the mount option memory policy will be applied with a NodeList,
if any, modified by the calling task's cpuset constraints
-[See Documentation/cgroups/cpusets.txt] and any optional flags, listed
+[See Documentation/cgroup-v1/cpusets.txt] and any optional flags, listed
below. If the resulting NodeLists is the empty set, the effective memory
policy for the file will revert to "default" policy.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 8a196851f01d..9ace359d6cc5 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -931,7 +931,7 @@ struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
- int (*d_compare)(const struct dentry *, const struct dentry *,
+ int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const struct dentry *);
int (*d_init)(struct dentry *);
diff --git a/Documentation/gpu/kms-properties.csv b/Documentation/gpu/kms-properties.csv
index b6fcaf639c04..4c5ce3edcfd9 100644
--- a/Documentation/gpu/kms-properties.csv
+++ b/Documentation/gpu/kms-properties.csv
@@ -17,6 +17,7 @@ DRM,Generic,“rotation”,BITMASK,"{ 0, ""rotate-0"" }, { 1, ""rotate-90"" }, {
,,“CRTC_H”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout CRTC (destination) height (atomic)
,,“FB_ID”,OBJECT,DRM_MODE_OBJECT_FB,Plane,Scanout framebuffer (atomic)
,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Plane,CRTC that plane is attached to (atomic)
+,,“zpos”,RANGE,"Min=0, Max=UINT_MAX","Plane,Z-order of the plane.Planes with higher Z-order values are displayed on top, planes with identical Z-order values are display in an undefined order"
,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 00e4c2f615a8..46c030a49186 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2320,6 +2320,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Note that if CONFIG_MODULE_SIG_FORCE is set, that
is always true, so this option does nothing.
+ module_blacklist= [KNL] Do not load a comma-separated list of
+ modules. Useful for debugging problem modules.
+
mousedev.tap_time=
[MOUSE] Maximum time between finger touching and
leaving touchpad surface for touch to be considered
@@ -3586,7 +3589,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
relax_domain_level=
[KNL, SMP] Set scheduler's default relax_domain_level.
- See Documentation/cgroups/cpusets.txt.
+ See Documentation/cgroup-v1/cpusets.txt.
relative_sleep_states=
[SUSPEND] Use sleep state labeling where the deepest
@@ -3874,6 +3877,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
using these two parameters to set the minimum and
maximum port values.
+ sunrpc.svc_rpc_per_connection_limit=
+ [NFS,SUNRPC]
+ Limit the number of requests that the server will
+ process in parallel from a single connection.
+ The default value is 0 (no limit).
+
sunrpc.pool_mode=
[NFS]
Control how the NFS server code allocates CPUs to
@@ -3909,7 +3918,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
swapaccount=[0|1]
[KNL] Enable accounting of swap in memory resource
controller if no parameter or 1 is given or disable
- it if 0 is given (See Documentation/cgroups/memory.txt)
+ it if 0 is given (See Documentation/cgroup-v1/memory.txt)
swiotlb= [ARM,IA-64,PPC,MIPS,X86]
Format: { <int> | force }
diff --git a/Documentation/kernel-per-CPU-kthreads.txt b/Documentation/kernel-per-CPU-kthreads.txt
index edec3a3e648d..bbc3a8b8cff4 100644
--- a/Documentation/kernel-per-CPU-kthreads.txt
+++ b/Documentation/kernel-per-CPU-kthreads.txt
@@ -10,7 +10,7 @@ REFERENCES
o Documentation/IRQ-affinity.txt: Binding interrupts to sets of CPUs.
-o Documentation/cgroups: Using cgroups to bind tasks to sets of CPUs.
+o Documentation/cgroup-v1: Using cgroups to bind tasks to sets of CPUs.
o man taskset: Using the taskset command to bind tasks to sets
of CPUs.
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
index 696d5caf4fd8..f0e3361db20c 100644
--- a/Documentation/module-signing.txt
+++ b/Documentation/module-signing.txt
@@ -271,3 +271,9 @@ Since the private key is used to sign modules, viruses and malware could use
the private key to sign modules and compromise the operating system. The
private key must be either destroyed or moved to a secure location and not kept
in the root node of the kernel source tree.
+
+If you use the same private key to sign modules for multiple kernel
+configurations, you must ensure that the module version information is
+sufficient to prevent loading a module into a different kernel. Either
+set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
+kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 9264bcab4099..26b9f31cf65a 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -45,18 +45,34 @@ corrupt, but usually it is restorable.
2. Setting the parameters
-Setting the ramoops parameters can be done in 3 different manners:
- 1. Use the module parameters (which have the names of the variables described
- as before).
- For quick debugging, you can also reserve parts of memory during boot
- and then use the reserved memory for ramoops. For example, assuming a machine
- with > 128 MB of memory, the following kernel command line will tell the
- kernel to use only the first 128 MB of memory, and place ECC-protected ramoops
- region at 128 MB boundary:
+Setting the ramoops parameters can be done in several different manners:
+
+ A. Use the module parameters (which have the names of the variables described
+ as before). For quick debugging, you can also reserve parts of memory during
+ boot and then use the reserved memory for ramoops. For example, assuming a
+ machine with > 128 MB of memory, the following kernel command line will tell
+ the kernel to use only the first 128 MB of memory, and place ECC-protected
+ ramoops region at 128 MB boundary:
"mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
- 2. Use Device Tree bindings, as described in
- Documentation/device-tree/bindings/misc/ramoops.txt.
- 3. Use a platform device and set the platform data. The parameters can then
+
+ B. Use Device Tree bindings, as described in
+ Documentation/device-tree/bindings/reserved-memory/ramoops.txt.
+ For example:
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ramoops@8f000000 {
+ compatible = "ramoops";
+ reg = <0 0x8f000000 0 0x100000>;
+ record-size = <0x4000>;
+ console-size = <0x4000>;
+ };
+ };
+
+ C. Use a platform device and set the platform data. The parameters can then
be set through that platform data. An example of doing that is:
#include <linux/pstore_ram.h>
diff --git a/Documentation/scheduler/sched-deadline.txt b/Documentation/scheduler/sched-deadline.txt
index e114513a2731..53a2fe1ae8b8 100644
--- a/Documentation/scheduler/sched-deadline.txt
+++ b/Documentation/scheduler/sched-deadline.txt
@@ -431,7 +431,7 @@ CONTENTS
-deadline tasks cannot have an affinity mask smaller that the entire
root_domain they are created on. However, affinities can be specified
- through the cpuset facility (Documentation/cgroups/cpusets.txt).
+ through the cpuset facility (Documentation/cgroup-v1/cpusets.txt).
5.1 SCHED_DEADLINE and cpusets HOWTO
------------------------------------
diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt
index f14f49304222..edd861c94c1b 100644
--- a/Documentation/scheduler/sched-design-CFS.txt
+++ b/Documentation/scheduler/sched-design-CFS.txt
@@ -215,7 +215,7 @@ SCHED_BATCH) tasks.
These options need CONFIG_CGROUPS to be defined, and let the administrator
create arbitrary groups of tasks, using the "cgroup" pseudo filesystem. See
- Documentation/cgroups/cgroups.txt for more information about this filesystem.
+ Documentation/cgroup-v1/cgroups.txt for more information about this filesystem.
When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each
group created using the pseudo filesystem. See example steps below to create
diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt
index 71b54d549987..a03f0d944fe6 100644
--- a/Documentation/scheduler/sched-rt-group.txt
+++ b/Documentation/scheduler/sched-rt-group.txt
@@ -133,7 +133,7 @@ This uses the cgroup virtual file system and "<cgroup>/cpu.rt_runtime_us"
to control the CPU time reserved for each control group.
For more information on working with control groups, you should read
-Documentation/cgroups/cgroups.txt as well.
+Documentation/cgroup-v1/cgroups.txt as well.
Group settings are checked against the following limits in order to keep the
configuration schedulable:
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 5237e1b2fd66..739db9ab16b2 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1433,13 +1433,16 @@ KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
4.52 KVM_SET_GSI_ROUTING
Capability: KVM_CAP_IRQ_ROUTING
-Architectures: x86 s390
+Architectures: x86 s390 arm arm64
Type: vm ioctl
Parameters: struct kvm_irq_routing (in)
Returns: 0 on success, -1 on error
Sets the GSI routing table entries, overwriting any previously set entries.
+On arm/arm64, GSI routing has the following limitation:
+- GSI routing does not apply to KVM_IRQ_LINE but only to KVM_IRQFD.
+
struct kvm_irq_routing {
__u32 nr;
__u32 flags;
@@ -1468,7 +1471,13 @@ struct kvm_irq_routing_entry {
#define KVM_IRQ_ROUTING_S390_ADAPTER 3
#define KVM_IRQ_ROUTING_HV_SINT 4
-No flags are specified so far, the corresponding field must be set to zero.
+flags:
+- KVM_MSI_VALID_DEVID: used along with KVM_IRQ_ROUTING_MSI routing entry
+ type, specifies that the devid field contains a valid value. The per-VM
+ KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+ the device ID. If this capability is not available, userspace should
+ never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
+- zero otherwise
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1479,9 +1488,16 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
- __u32 pad;
+ union {
+ __u32 pad;
+ __u32 devid;
+ };
};
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message. For PCI, this is usually a
+BFD identifier in the lower 16 bits.
+
On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
feature of KVM_CAP_X2APIC_API capability is enabled. If it is enabled,
address_hi bits 31-8 provide bits 31-8 of the destination id. Bits 7-0 of
@@ -2199,18 +2215,19 @@ struct kvm_msi {
__u8 pad[12];
};
-flags: KVM_MSI_VALID_DEVID: devid contains a valid value
-devid: If KVM_MSI_VALID_DEVID is set, contains a unique device identifier
- for the device that wrote the MSI message.
- For PCI, this is usually a BFD identifier in the lower 16 bits.
+flags: KVM_MSI_VALID_DEVID: devid contains a valid value. The per-VM
+ KVM_CAP_MSI_DEVID capability advertises the requirement to provide
+ the device ID. If this capability is not available, userspace
+ should never set the KVM_MSI_VALID_DEVID flag as the ioctl might fail.
-The per-VM KVM_CAP_MSI_DEVID capability advertises the need to provide
-the device ID. If this capability is not set, userland cannot rely on
-the kernel to allow the KVM_MSI_VALID_DEVID flag being set.
+If KVM_MSI_VALID_DEVID is set, devid contains a unique device identifier
+for the device that wrote the MSI message. For PCI, this is usually a
+BFD identifier in the lower 16 bits.
-On x86, address_hi is ignored unless the KVM_CAP_X2APIC_API capability is
-enabled. If it is enabled, address_hi bits 31-8 provide bits 31-8 of the
-destination id. Bits 7-0 of address_hi must be zero.
+On x86, address_hi is ignored unless the KVM_X2APIC_API_USE_32BIT_IDS
+feature of KVM_CAP_X2APIC_API capability is enabled. If it is enabled,
+address_hi bits 31-8 provide bits 31-8 of the destination id. Bits 7-0 of
+address_hi must be zero.
4.71 KVM_CREATE_PIT2
@@ -2383,9 +2400,13 @@ Note that closing the resamplefd is not sufficient to disable the
irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment
and need not be specified with KVM_IRQFD_FLAG_DEASSIGN.
-On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared
-Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is
-given by gsi + 32.
+On arm/arm64, gsi routing being supported, the following can happen:
+- in case no routing entry is associated to this gsi, injection fails
+- in case the gsi is associated to an irqchip routing entry,
+ irqchip.pin + 32 corresponds to the injected SPI ID.
+- in case the gsi is associated to an MSI routing entry, the MSI
+ message and device ID are translated into an LPI (support restricted
+ to GICv3 ITS in-kernel emulation).
4.76 KVM_PPC_ALLOCATE_HTAB
diff --git a/Documentation/vm/numa b/Documentation/vm/numa
index ade01274212d..e0b58c0e6b49 100644
--- a/Documentation/vm/numa
+++ b/Documentation/vm/numa
@@ -63,7 +63,7 @@ nodes. Each emulated node will manage a fraction of the underlying cells'
physical memory. NUMA emluation is useful for testing NUMA kernel and
application features on non-NUMA platforms, and as a sort of memory resource
management mechanism when used together with cpusets.
-[see Documentation/cgroups/cpusets.txt]
+[see Documentation/cgroup-v1/cpusets.txt]
For each node with memory, Linux constructs an independent memory management
subsystem, complete with its own free page lists, in-use page lists, usage
@@ -113,7 +113,7 @@ allocation behavior using Linux NUMA memory policy.
System administrators can restrict the CPUs and nodes' memories that a non-
privileged user can specify in the scheduling or NUMA commands and functions
-using control groups and CPUsets. [see Documentation/cgroups/cpusets.txt]
+using control groups and CPUsets. [see Documentation/cgroup-v1/cpusets.txt]
On architectures that do not hide memoryless nodes, Linux will include only
zones [nodes] with memory in the zonelists. This means that for a memoryless
diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt
index badb0507608f..622b927816e7 100644
--- a/Documentation/vm/numa_memory_policy.txt
+++ b/Documentation/vm/numa_memory_policy.txt
@@ -9,7 +9,7 @@ document attempts to describe the concepts and APIs of the 2.6 memory policy
support.
Memory policies should not be confused with cpusets
-(Documentation/cgroups/cpusets.txt)
+(Documentation/cgroup-v1/cpusets.txt)
which is an administrative mechanism for restricting the nodes from which
memory may be allocated by a set of processes. Memory policies are a
programming interface that a NUMA-aware application can take advantage of. When
diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration
index 94bd9c11c4e0..0478ae2ad44a 100644
--- a/Documentation/vm/page_migration
+++ b/Documentation/vm/page_migration
@@ -38,7 +38,7 @@ locations.
Larger installations usually partition the system using cpusets into
sections of nodes. Paul Jackson has equipped cpusets with the ability to
move pages when a task is moved to another cpuset (See
-Documentation/cgroups/cpusets.txt).
+Documentation/cgroup-v1/cpusets.txt).
Cpusets allows the automation of process locality. If a task is moved to
a new cpuset then also all its pages are moved with it so that the
performance of the process does not sink dramatically. Also the pages
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
index 0026a8d33fc0..e14718572476 100644
--- a/Documentation/vm/unevictable-lru.txt
+++ b/Documentation/vm/unevictable-lru.txt
@@ -122,7 +122,7 @@ MEMORY CONTROL GROUP INTERACTION
--------------------------------
The unevictable LRU facility interacts with the memory control group [aka
-memory controller; see Documentation/cgroups/memory.txt] by extending the
+memory controller; see Documentation/cgroup-v1/memory.txt] by extending the
lru_list enum.
The memory controller data structure automatically gets a per-zone unevictable
diff --git a/Documentation/x86/x86_64/fake-numa-for-cpusets b/Documentation/x86/x86_64/fake-numa-for-cpusets
index 0f11d9becb0b..4b09f18831f8 100644
--- a/Documentation/x86/x86_64/fake-numa-for-cpusets
+++ b/Documentation/x86/x86_64/fake-numa-for-cpusets
@@ -8,7 +8,7 @@ assign them to cpusets and their attached tasks. This is a way of limiting the
amount of system memory that are available to a certain class of tasks.
For more information on the features of cpusets, see
-Documentation/cgroups/cpusets.txt.
+Documentation/cgroup-v1/cpusets.txt.
There are a number of different configurations you can use for your needs. For
more information on the numa=fake command line option and its various ways of
configuring fake nodes, see Documentation/x86/x86_64/boot-options.txt.
@@ -33,7 +33,7 @@ A machine may be split as follows with "numa=fake=4*512," as reported by dmesg:
On node 3 totalpages: 131072
Now following the instructions for mounting the cpusets filesystem from
-Documentation/cgroups/cpusets.txt, you can assign fake nodes (i.e. contiguous memory
+Documentation/cgroup-v1/cpusets.txt, you can assign fake nodes (i.e. contiguous memory
address spaces) to individual cpusets:
[root@xroads /]# mkdir exampleset
diff --git a/MAINTAINERS b/MAINTAINERS
index 429fc61bee81..a306795a7450 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1004,6 +1004,7 @@ N: meson
ARM/Annapurna Labs ALPINE ARCHITECTURE
M: Tsahee Zidenberg <tsahee@annapurnalabs.com>
M: Antoine Tenart <antoine.tenart@free-electrons.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-alpine/
F: arch/arm/boot/dts/alpine*
@@ -1648,7 +1649,8 @@ F: arch/arm/mach-s5pv210/
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com>
-M: Kamil Debski <k.debski@samsung.com>
+M: Kamil Debski <kamil@wypas.org>
+M: Andrzej Hajda <a.hajda@samsung.com>
L: linux-arm-kernel@lists.infradead.org
L: linux-media@vger.kernel.org
S: Maintained
@@ -1656,8 +1658,9 @@ F: drivers/media/platform/s5p-g2d/
ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com>
-M: Kamil Debski <k.debski@samsung.com>
+M: Kamil Debski <kamil@wypas.org>
M: Jeongtae Park <jtp.park@samsung.com>
+M: Andrzej Hajda <a.hajda@samsung.com>
L: linux-arm-kernel@lists.infradead.org
L: linux-media@vger.kernel.org
S: Maintained
@@ -3217,7 +3220,7 @@ M: Johannes Weiner <hannes@cmpxchg.org>
L: cgroups@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
S: Maintained
-F: Documentation/cgroups/
+F: Documentation/cgroup*
F: include/linux/cgroup*
F: kernel/cgroup*
@@ -3228,7 +3231,7 @@ W: http://www.bullopensource.org/cpuset/
W: http://oss.sgi.com/projects/cpusets/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
S: Maintained
-F: Documentation/cgroups/cpusets.txt
+F: Documentation/cgroup-v1/cpusets.txt
F: include/linux/cpuset.h
F: kernel/cpuset.c
@@ -3492,6 +3495,7 @@ F: Documentation/ABI/testing/sysfs-class-cxl
CXLFLASH (IBM Coherent Accelerator Processor Interface CAPI Flash) SCSI DRIVER
M: Manoj N. Kumar <manoj@linux.vnet.ibm.com>
M: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
+M: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/cxlflash/
@@ -5829,7 +5833,15 @@ M: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/ibmvscsi/ibmvscsi*
-F: drivers/scsi/ibmvscsi/viosrp.h
+F: include/scsi/viosrp.h
+
+IBM Power Virtual SCSI Device Target Driver
+M: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+M: Michael Cyr <mikecyr@linux.vnet.ibm.com>
+L: linux-scsi@vger.kernel.org
+L: target-devel@vger.kernel.org
+S: Supported
+F: drivers/scsi/ibmvscsi_tgt/
IBM Power Virtual FC Device Drivers
M: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
@@ -7637,6 +7649,15 @@ W: http://www.mellanox.com
Q: http://patchwork.ozlabs.org/project/netdev/list/
F: drivers/net/ethernet/mellanox/mlxsw/
+SOFT-ROCE DRIVER (rxe)
+M: Moni Shoua <monis@mellanox.com>
+L: linux-rdma@vger.kernel.org
+S: Supported
+W: https://github.com/SoftRoCE/rxe-dev/wiki/rxe-dev:-Home
+Q: http://patchwork.kernel.org/project/linux-rdma/list/
+F: drivers/infiniband/hw/rxe/
+F: include/uapi/rdma/rdma_user_rxe.h
+
MEMBARRIER SUPPORT
M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
M: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
@@ -8321,6 +8342,7 @@ F: drivers/ntb/
F: drivers/net/ntb_netdev.c
F: include/linux/ntb.h
F: include/linux/ntb_transport.h
+F: tools/testing/selftests/ntb/
NTB INTEL DRIVER
M: Jon Mason <jdmason@kudzu.us>
@@ -9231,6 +9253,16 @@ W: http://www.st.com/spear
S: Maintained
F: drivers/pinctrl/spear/
+PISTACHIO SOC SUPPORT
+M: James Hartley <james.hartley@imgtec.com>
+M: Ionela Voinescu <ionela.voinescu@imgtec.com>
+L: linux-mips@linux-mips.org
+S: Maintained
+F: arch/mips/pistachio/
+F: arch/mips/include/asm/mach-pistachio/
+F: arch/mips/boot/dts/pistachio/
+F: arch/mips/configs/pistachio*_defconfig
+
PKTCDVD DRIVER
M: Jiri Kosina <jikos@kernel.org>
S: Maintained
@@ -9470,7 +9502,8 @@ S: Odd Fixes
F: drivers/media/usb/pwc/*
PWM FAN DRIVER
-M: Kamil Debski <k.debski@samsung.com>
+M: Kamil Debski <kamil@wypas.org>
+M: Lukasz Majewski <l.majewski@samsung.com>
L: linux-hwmon@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
@@ -9808,10 +9841,14 @@ L: rtc-linux@googlegroups.com
Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git
S: Maintained
+F: Documentation/devicetree/bindings/rtc/
F: Documentation/rtc.txt
F: drivers/rtc/
F: include/linux/rtc.h
F: include/uapi/linux/rtc.h
+F: include/linux/rtc/
+F: include/linux/platform_data/rtc-*
+F: tools/testing/selftests/timers/rtctest.c
REALTEK AUDIO CODECS
M: Bard Liao <bardliao@realtek.com>
@@ -10218,7 +10255,8 @@ T: git https://github.com/lmajewski/linux-samsung-thermal.git
F: drivers/thermal/samsung/
SAMSUNG USB2 PHY DRIVER
-M: Kamil Debski <k.debski@samsung.com>
+M: Kamil Debski <kamil@wypas.org>
+M: Sylwester Nawrocki <s.nawrocki@samsung.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -12382,6 +12420,19 @@ S: Maintained
F: drivers/media/v4l2-core/videobuf2-*
F: include/media/videobuf2-*
+VIRTIO AND VHOST VSOCK DRIVER
+M: Stefan Hajnoczi <stefanha@redhat.com>
+L: kvm@vger.kernel.org
+L: virtualization@lists.linux-foundation.org
+L: netdev@vger.kernel.org
+S: Maintained
+F: include/linux/virtio_vsock.h
+F: include/uapi/linux/virtio_vsock.h
+F: net/vmw_vsock/virtio_transport_common.c
+F: net/vmw_vsock/virtio_transport.c
+F: drivers/vhost/vsock.c
+F: drivers/vhost/vsock.h
+
VIRTUAL SERIO DEVICE DRIVER
M: Stephen Chandler Paul <thatslyude@gmail.com>
S: Maintained
diff --git a/Makefile b/Makefile
index 182a84d0b8ea..5c18baad7218 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 4
-PATCHLEVEL = 7
+PATCHLEVEL = 8
SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc2
NAME = Psychotic Stoned Sheep
# *DOCUMENTATION*
@@ -635,13 +635,6 @@ endif
# Tell gcc to never replace conditional load with a non-conditional one
KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0)
-PHONY += gcc-plugins
-gcc-plugins: scripts_basic
-ifdef CONFIG_GCC_PLUGINS
- $(Q)$(MAKE) $(build)=scripts/gcc-plugins
-endif
- @:
-
include scripts/Makefile.gcc-plugins
ifdef CONFIG_READABLE_ASM
@@ -1432,7 +1425,7 @@ $(help-board-dirs): help-%:
# Documentation targets
# ---------------------------------------------------------------------------
-DOC_TARGETS := xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs cleanmediadocs
+DOC_TARGETS := xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs
PHONY += $(DOC_TARGETS)
$(DOC_TARGETS): scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype
diff --git a/arch/Kconfig b/arch/Kconfig
index bd8056b5b246..e9c9334507dd 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -461,6 +461,15 @@ config CC_STACKPROTECTOR_STRONG
endchoice
+config HAVE_ARCH_WITHIN_STACK_FRAMES
+ bool
+ help
+ An architecture should select this if it can walk the kernel stack
+ frames to determine if an object is part of either the arguments
+ or local variables (i.e. that it excludes saved return addresses,
+ and similar) by implementing an inline arch_within_stack_frames(),
+ which is used by CONFIG_HARDENED_USERCOPY.
+
config HAVE_CONTEXT_TRACKING
bool
help
diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h
index 3c3451f58ff4..c63b6ac19ee5 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -1,8 +1,6 @@
#ifndef _ALPHA_DMA_MAPPING_H
#define _ALPHA_DMA_MAPPING_H
-#include <linux/dma-attrs.h>
-
extern struct dma_map_ops *dma_ops;
static inline struct dma_map_ops *get_dma_ops(struct device *dev)
diff --git a/arch/alpha/include/asm/rtc.h b/arch/alpha/include/asm/rtc.h
deleted file mode 100644
index f71c3b0ed360..000000000000
--- a/arch/alpha/include/asm/rtc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/rtc.h>
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
index 53dd2f1a53aa..d5f0580746a5 100644
--- a/arch/alpha/kernel/core_marvel.c
+++ b/arch/alpha/kernel/core_marvel.c
@@ -24,7 +24,6 @@
#include <asm/gct.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
-#include <asm/rtc.h>
#include <asm/vga.h>
#include "proto.h"
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 8e735b5e56bd..bb152e21e5ae 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -109,7 +109,7 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 8969bf2dfe3a..451fc9cdd323 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -349,7 +349,7 @@ static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
int dac_allowed;
@@ -369,7 +369,7 @@ static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long flags;
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
@@ -433,7 +433,7 @@ static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
void *cpu_addr;
@@ -478,7 +478,7 @@ try_again:
static void alpha_pci_free_coherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
@@ -651,7 +651,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
struct scatterlist *start, *end, *out;
@@ -729,7 +729,7 @@ static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
unsigned long flags;
diff --git a/arch/alpha/kernel/rtc.c b/arch/alpha/kernel/rtc.c
index f535a3fd0f60..ceed68c7500b 100644
--- a/arch/alpha/kernel/rtc.c
+++ b/arch/alpha/kernel/rtc.c
@@ -15,8 +15,6 @@
#include <linux/rtc.h>
#include <linux/platform_device.h>
-#include <asm/rtc.h>
-
#include "proto.h"
@@ -81,7 +79,7 @@ init_rtc_epoch(void)
static int
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- __get_rtc_time(tm);
+ mc146818_get_time(tm);
/* Adjust for non-default epochs. It's easier to depend on the
generic __get_rtc_time and adjust the epoch here than create
@@ -112,7 +110,7 @@ alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
tm = &xtm;
}
- return __set_rtc_time(tm);
+ return mc146818_set_time(tm);
}
static int
diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c
index ab74b5d9186c..20afc65e22dc 100644
--- a/arch/arc/mm/dma.c
+++ b/arch/arc/mm/dma.c
@@ -22,7 +22,7 @@
static void *arc_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
unsigned long order = get_order(size);
struct page *page;
@@ -46,7 +46,7 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
* (vs. always going to memory - thus are faster)
*/
if ((is_isa_arcv2() && ioc_exists) ||
- dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
+ (attrs & DMA_ATTR_NON_CONSISTENT))
need_coh = 0;
/*
@@ -90,13 +90,13 @@ static void *arc_dma_alloc(struct device *dev, size_t size,
}
static void arc_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
phys_addr_t paddr = plat_dma_to_phys(dev, dma_handle);
struct page *page = virt_to_page(paddr);
int is_non_coh = 1;
- is_non_coh = dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs) ||
+ is_non_coh = (attrs & DMA_ATTR_NON_CONSISTENT) ||
(is_isa_arcv2() && ioc_exists);
if (PageHighMem(page) || !is_non_coh)
@@ -130,7 +130,7 @@ static void _dma_cache_sync(phys_addr_t paddr, size_t size,
static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
phys_addr_t paddr = page_to_phys(page) + offset;
_dma_cache_sync(paddr, size, dir);
@@ -138,7 +138,7 @@ static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page,
}
static int arc_dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *s;
int i;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2d601d769a1c..a9c4e48bb7ec 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -35,6 +35,7 @@ config ARM
select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT)
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
+ select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU
select HAVE_ARCH_MMAP_RND_BITS if MMU
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 56ea5c60b318..61f6ccc19cfa 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -260,12 +260,14 @@ machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
platdirs := $(patsubst %,arch/arm/plat-%/,$(sort $(plat-y)))
ifneq ($(CONFIG_ARCH_MULTIPLATFORM),y)
+ifneq ($(CONFIG_ARM_SINGLE_ARMV7M),y)
ifeq ($(KBUILD_SRC),)
KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs))
else
KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs) $(platdirs))
endif
endif
+endif
export TEXT_OFFSET GZFLAGS MMUEXT
diff --git a/arch/arm/boot/dts/arm-realview-pbx-a9.dts b/arch/arm/boot/dts/arm-realview-pbx-a9.dts
index db808f92dd79..90d00b407f85 100644
--- a/arch/arm/boot/dts/arm-realview-pbx-a9.dts
+++ b/arch/arm/boot/dts/arm-realview-pbx-a9.dts
@@ -70,13 +70,12 @@
* associativity as these may be erroneously set
* up by boot loader(s).
*/
- cache-size = <1048576>; // 1MB
- cache-sets = <4096>;
+ cache-size = <131072>; // 128KB
+ cache-sets = <512>;
cache-line-size = <32>;
arm,parity-disable;
- arm,tag-latency = <1>;
- arm,data-latency = <1 1>;
- arm,dirty-latency = <1>;
+ arm,tag-latency = <1 1 1>;
+ arm,data-latency = <1 1 1>;
};
scu: scu@1f000000 {
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index cf06e32ee108..4b34b54e09a1 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -42,7 +42,7 @@
};
syscon {
- compatible = "arm,integrator-ap-syscon";
+ compatible = "arm,integrator-ap-syscon", "syscon";
reg = <0x11000000 0x100>;
interrupt-parent = <&pic>;
/* These are the logical module IRQs */
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index d43f15b4f79a..79430fbfec3b 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -94,7 +94,7 @@
};
syscon {
- compatible = "arm,integrator-cp-syscon";
+ compatible = "arm,integrator-cp-syscon", "syscon";
reg = <0xcb000000 0x100>;
};
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index 00cb314d5e4d..e23f46d15c80 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -70,14 +70,6 @@
cpu_on = <0x84000003>;
};
- psci {
- compatible = "arm,psci";
- method = "smc";
- cpu_suspend = <0x84000001>;
- cpu_off = <0x84000002>;
- cpu_on = <0x84000003>;
- };
-
soc {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index e52b82449a79..6403e0de540e 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1382,7 +1382,7 @@
* Pin 41: BR_UART1_TXD
* Pin 44: BR_UART1_RXD
*/
- serial@70006000 {
+ serial@0,70006000 {
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
status = "okay";
};
@@ -1394,7 +1394,7 @@
* Pin 71: UART2_CTS_L
* Pin 74: UART2_RTS_L
*/
- serial@70006040 {
+ serial@0,70006040 {
compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
status = "okay";
};
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 1143c4d5c567..301281645d08 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -310,7 +310,7 @@ static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
*/
static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t dma_addr;
int ret;
@@ -344,7 +344,7 @@ static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
* should be)
*/
static void dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct safe_buffer *buf;
diff --git a/arch/arm/configs/aspeed_g4_defconfig b/arch/arm/configs/aspeed_g4_defconfig
index b6e54ee9bdbd..ca39c04fec6b 100644
--- a/arch/arm/configs/aspeed_g4_defconfig
+++ b/arch/arm/configs/aspeed_g4_defconfig
@@ -58,7 +58,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_FANOTIFY=y
-CONFIG_PRINTK_TIME=1
+CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_PAGE_POISONING=y
diff --git a/arch/arm/configs/aspeed_g5_defconfig b/arch/arm/configs/aspeed_g5_defconfig
index 892605167357..4f366b0370e9 100644
--- a/arch/arm/configs/aspeed_g5_defconfig
+++ b/arch/arm/configs/aspeed_g5_defconfig
@@ -59,7 +59,7 @@ CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_FIRMWARE_MEMMAP=y
CONFIG_FANOTIFY=y
-CONFIG_PRINTK_TIME=1
+CONFIG_PRINTK_TIME=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_STRIP_ASM_SYMS=y
CONFIG_PAGE_POISONING=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index a83570f10124..d009f7911ffc 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -5,7 +5,6 @@
#include <linux/mm_types.h>
#include <linux/scatterlist.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-debug.h>
#include <asm/memory.h>
@@ -174,7 +173,7 @@ static inline void dma_mark_clean(void *addr, size_t size) { }
* to be the device-viewed address.
*/
extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t gfp, struct dma_attrs *attrs);
+ gfp_t gfp, unsigned long attrs);
/**
* arm_dma_free - free memory allocated by arm_dma_alloc
@@ -191,7 +190,7 @@ extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
* during and after this call executing are illegal.
*/
extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs);
+ dma_addr_t handle, unsigned long attrs);
/**
* arm_dma_mmap - map a coherent DMA allocation into user space
@@ -208,7 +207,7 @@ extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
*/
extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs);
+ unsigned long attrs);
/*
* This can be called during early boot to increase the size of the atomic
@@ -262,16 +261,16 @@ extern void dmabounce_unregister_dev(struct device *);
* The scatter list versions of the above methods.
*/
extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
- enum dma_data_direction, struct dma_attrs *attrs);
+ enum dma_data_direction, unsigned long attrs);
extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
- enum dma_data_direction, struct dma_attrs *attrs);
+ enum dma_data_direction, unsigned long attrs);
extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
enum dma_data_direction);
extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
enum dma_data_direction);
extern int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs);
+ unsigned long attrs);
#endif /* __KERNEL__ */
#endif
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index 62a6f65029e6..a93c0f99acf7 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -480,7 +480,10 @@ arm_copy_from_user(void *to, const void __user *from, unsigned long n);
static inline unsigned long __must_check
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
- unsigned int __ua_flags = uaccess_save_and_enable();
+ unsigned int __ua_flags;
+
+ check_object_size(to, n, false);
+ __ua_flags = uaccess_save_and_enable();
n = arm_copy_from_user(to, from, n);
uaccess_restore(__ua_flags);
return n;
@@ -495,11 +498,15 @@ static inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
#ifndef CONFIG_UACCESS_WITH_MEMCPY
- unsigned int __ua_flags = uaccess_save_and_enable();
+ unsigned int __ua_flags;
+
+ check_object_size(from, n, true);
+ __ua_flags = uaccess_save_and_enable();
n = arm_copy_to_user(to, from, n);
uaccess_restore(__ua_flags);
return n;
#else
+ check_object_size(from, n, true);
return arm_copy_to_user(to, from, n);
#endif
}
diff --git a/arch/arm/include/asm/xen/page-coherent.h b/arch/arm/include/asm/xen/page-coherent.h
index 9408a994cc91..95ce6ac3a971 100644
--- a/arch/arm/include/asm/xen/page-coherent.h
+++ b/arch/arm/include/asm/xen/page-coherent.h
@@ -2,15 +2,14 @@
#define _ASM_ARM_XEN_PAGE_COHERENT_H
#include <asm/page.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-mapping.h>
void __xen_dma_map_page(struct device *hwdev, struct page *page,
dma_addr_t dev_addr, unsigned long offset, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs);
+ enum dma_data_direction dir, unsigned long attrs);
void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
void __xen_dma_sync_single_for_cpu(struct device *hwdev,
dma_addr_t handle, size_t size, enum dma_data_direction dir);
@@ -18,22 +17,20 @@ void __xen_dma_sync_single_for_device(struct device *hwdev,
dma_addr_t handle, size_t size, enum dma_data_direction dir);
static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
{
return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
}
static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
{
__generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
}
static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
dma_addr_t dev_addr, unsigned long offset, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
unsigned long page_pfn = page_to_xen_pfn(page);
unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
@@ -58,8 +55,7 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
}
static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
unsigned long pfn = PFN_DOWN(handle);
/*
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index 087acb569b63..5f221acd21ae 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -279,8 +279,12 @@ asmlinkage long sys_oabi_epoll_wait(int epfd,
mm_segment_t fs;
long ret, err, i;
- if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event)))
+ if (maxevents <= 0 ||
+ maxevents > (INT_MAX/sizeof(*kbuf)) ||
+ maxevents > (INT_MAX/sizeof(*events)))
return -EINVAL;
+ if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents))
+ return -EFAULT;
kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
@@ -317,6 +321,8 @@ asmlinkage long sys_oabi_semtimedop(int semid,
if (nsops < 1 || nsops > SEMOPM)
return -EINVAL;
+ if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops))
+ return -EFAULT;
sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
if (!sops)
return -ENOMEM;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 99420fc1f066..d24e5dd2aa7a 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -44,7 +44,7 @@
#endif
#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \
- defined(CONFIG_GENERIC_BUG)
+ defined(CONFIG_GENERIC_BUG) || defined(CONFIG_JUMP_LABEL)
#define ARM_EXIT_KEEP(x) x
#define ARM_EXIT_DISCARD(x)
#else
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 95a000515e43..3e1cd0452d67 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -32,6 +32,8 @@ config KVM
select KVM_VFIO
select HAVE_KVM_EVENTFD
select HAVE_KVM_IRQFD
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQ_ROUTING
depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
---help---
Support hosting virtualized guest machines.
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index 5e28df80dca7..10d77a66cad5 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -29,4 +29,5 @@ obj-y += $(KVM)/arm/vgic/vgic-v2.o
obj-y += $(KVM)/arm/vgic/vgic-mmio.o
obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+obj-y += $(KVM)/irqchip.o
obj-y += $(KVM)/arm/arch_timer.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index d94bb9093ead..75f130ef6504 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1009,9 +1009,13 @@ long kvm_arch_vm_ioctl(struct file *filp,
switch (ioctl) {
case KVM_CREATE_IRQCHIP: {
+ int ret;
if (!vgic_present)
return -ENXIO;
- return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
+ mutex_lock(&kvm->lock);
+ ret = kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
+ mutex_unlock(&kvm->lock);
+ return ret;
}
case KVM_ARM_SET_DEVICE_ADDR: {
struct kvm_arm_device_addr dev_addr;
diff --git a/arch/arm/kvm/irq.h b/arch/arm/kvm/irq.h
new file mode 100644
index 000000000000..b74099b905fd
--- /dev/null
+++ b/arch/arm/kvm/irq.h
@@ -0,0 +1,19 @@
+/*
+ * irq.h: in kernel interrupt controller related definitions
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * 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 header is included by irqchip.c. However, on ARM, interrupt
+ * controller declarations are located in include/kvm/arm_vgic.h since
+ * they are mostly shared between arm and arm64.
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+#include <kvm/arm_vgic.h>
+
+#endif
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index dc7c6edeab39..61284b9389cf 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -1,13 +1,13 @@
menuconfig ARCH_CLPS711X
bool "Cirrus Logic EP721x/EP731x-based"
depends on ARCH_MULTI_V4T
- select ARCH_REQUIRE_GPIOLIB
select AUTO_ZRELADDR
select CLKSRC_OF
select CLPS711X_TIMER
select COMMON_CLK
select CPU_ARM720T
select GENERIC_CLOCKEVENTS
+ select GPIOLIB
select MFD_SYSCON
select OF_IRQ
select USE_OF
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 45b81a2bcd4b..3b39ea353d30 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index e53c6cfcab51..6c6497e80a7b 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,5 +1,4 @@
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
- -I$(srctree)/arch/arm/plat-orion/include
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/arch/arm/plat-orion/include
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
CFLAGS_pmsu.o := -march=armv7-a
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 3a58a5d4a28a..8d597267d0c4 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/timeriomem-rng.h>
diff --git a/arch/arm/mach-oxnas/Kconfig b/arch/arm/mach-oxnas/Kconfig
index 567496bd250a..29100beb2e7f 100644
--- a/arch/arm/mach-oxnas/Kconfig
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -11,11 +11,13 @@ if ARCH_OXNAS
config MACH_OX810SE
bool "Support OX810SE Based Products"
+ select ARCH_HAS_RESET_CONTROLLER
select COMMON_CLK_OXNAS
select CPU_ARM926T
select MFD_SYSCON
select OXNAS_RPS_TIMER
select PINCTRL_OXNAS
+ select RESET_CONTROLLER
select RESET_OXNAS
select VERSATILE_FPGA_IRQ
help
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index fa5f51d633a3..be4a66166d61 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -14,7 +14,7 @@
#include <linux/gpio.h>
#include <linux/delay.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
#include <video/mbxfb.h>
#include <linux/spi/spi.h>
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 5f5ac7c8faf0..868448d2cd82 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -25,7 +25,7 @@
#include <linux/gpio.h>
#include <linux/dm9000.h>
#include <linux/leds.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index dc109dc3a622..10bfdb169366 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -13,6 +13,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h> /* symbol_get ; symbol_put */
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/major.h>
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 6e0268deec43..03354c21e1f2 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -14,7 +14,7 @@
#include <linux/delay.h>
#include <linux/dm9000.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 1080580b1343..2c150bfc0cd5 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -13,6 +13,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h> /* symbol_get ; symbol_put */
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio_keys.h>
diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
index dae8d86ef4cc..404882130956 100644
--- a/arch/arm/mach-realview/Makefile
+++ b/arch/arm/mach-realview/Makefile
@@ -1,8 +1,7 @@
#
# Makefile for the linux kernel.
#
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
- -I$(srctree)/arch/arm/plat-versatile/include
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/arch/arm/plat-versatile/include
obj-y := core.o
obj-$(CONFIG_REALVIEW_DT) += realview-dt.o
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index 72b9e9671507..fa7fb716e388 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -5,7 +5,7 @@
#
# Licensed under GPLv2
-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)/arch/arm/plat-samsung/include
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/arch/arm/plat-samsung/include
# Core
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index f3dba6f356e2..02e21bceb085 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -40,5 +40,8 @@ bool shmobile_smp_cpu_can_disable(unsigned int cpu)
bool __init shmobile_smp_init_fallback_ops(void)
{
/* fallback on PSCI/smp_ops if no other DT based method is detected */
+ if (!IS_ENABLED(CONFIG_SMP))
+ return false;
+
return platform_can_secondary_boot() ? true : false;
}
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index b7eed75960fe..c6834c0cfd1c 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -128,16 +128,16 @@ static void __dma_page_dev_to_cpu(struct page *, unsigned long,
*/
static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_cpu_to_dev(page, offset, size, dir);
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
}
static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
}
@@ -157,10 +157,9 @@ static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *pag
* whatever the device wrote there.
*/
static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
handle & ~PAGE_MASK, size, dir);
}
@@ -198,12 +197,12 @@ struct dma_map_ops arm_dma_ops = {
EXPORT_SYMBOL(arm_dma_ops);
static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs);
static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs);
+ dma_addr_t handle, unsigned long attrs);
static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs);
+ unsigned long attrs);
struct dma_map_ops arm_coherent_dma_ops = {
.alloc = arm_coherent_dma_alloc,
@@ -639,11 +638,11 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}
-static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
{
- prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
- pgprot_writecombine(prot) :
- pgprot_dmacoherent(prot);
+ prot = (attrs & DMA_ATTR_WRITE_COMBINE) ?
+ pgprot_writecombine(prot) :
+ pgprot_dmacoherent(prot);
return prot;
}
@@ -751,7 +750,7 @@ static struct arm_dma_allocator remap_allocator = {
static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
gfp_t gfp, pgprot_t prot, bool is_coherent,
- struct dma_attrs *attrs, const void *caller)
+ unsigned long attrs, const void *caller)
{
u64 mask = get_coherent_dma_mask(dev);
struct page *page = NULL;
@@ -764,7 +763,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
.gfp = gfp,
.prot = prot,
.caller = caller,
- .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+ .want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0),
.coherent_flag = is_coherent ? COHERENT : NORMAL,
};
@@ -834,7 +833,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
* virtual and bus address for that space.
*/
void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t gfp, struct dma_attrs *attrs)
+ gfp_t gfp, unsigned long attrs)
{
pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
@@ -843,7 +842,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
}
static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
{
return __dma_alloc(dev, size, handle, gfp, PAGE_KERNEL, true,
attrs, __builtin_return_address(0));
@@ -851,7 +850,7 @@ static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int ret = -ENXIO;
#ifdef CONFIG_MMU
@@ -879,14 +878,14 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
*/
static int arm_coherent_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return __arm_dma_mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
}
int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef CONFIG_MMU
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
@@ -898,7 +897,7 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
* Free a buffer as defined by the above mapping.
*/
static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs,
+ dma_addr_t handle, unsigned long attrs,
bool is_coherent)
{
struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
@@ -908,7 +907,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
.size = PAGE_ALIGN(size),
.cpu_addr = cpu_addr,
.page = page,
- .want_vaddr = !dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs),
+ .want_vaddr = ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0),
};
buf = arm_dma_buffer_find(cpu_addr);
@@ -920,20 +919,20 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
}
void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs)
+ dma_addr_t handle, unsigned long attrs)
{
__arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
}
static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs)
+ dma_addr_t handle, unsigned long attrs)
{
__arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
}
int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t handle, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
int ret;
@@ -1066,7 +1065,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
* here.
*/
int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
@@ -1100,7 +1099,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
* rules concerning calls here are the same as for dma_unmap_single().
*/
void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
@@ -1273,7 +1272,7 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
static const int iommu_order_array[] = { 9, 8, 4, 0 };
static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
- gfp_t gfp, struct dma_attrs *attrs,
+ gfp_t gfp, unsigned long attrs,
int coherent_flag)
{
struct page **pages;
@@ -1289,7 +1288,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
if (!pages)
return NULL;
- if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs))
+ if (attrs & DMA_ATTR_FORCE_CONTIGUOUS)
{
unsigned long order = get_order(size);
struct page *page;
@@ -1307,7 +1306,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
}
/* Go straight to 4K chunks if caller says it's OK. */
- if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs))
+ if (attrs & DMA_ATTR_ALLOC_SINGLE_PAGES)
order_idx = ARRAY_SIZE(iommu_order_array) - 1;
/*
@@ -1363,12 +1362,12 @@ error:
}
static int __iommu_free_buffer(struct device *dev, struct page **pages,
- size_t size, struct dma_attrs *attrs)
+ size_t size, unsigned long attrs)
{
int count = size >> PAGE_SHIFT;
int i;
- if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) {
+ if (attrs & DMA_ATTR_FORCE_CONTIGUOUS) {
dma_release_from_contiguous(dev, pages[0], count);
} else {
for (i = 0; i < count; i++)
@@ -1460,14 +1459,14 @@ static struct page **__atomic_get_pages(void *addr)
return (struct page **)page;
}
-static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
+static struct page **__iommu_get_pages(void *cpu_addr, unsigned long attrs)
{
struct vm_struct *area;
if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
return __atomic_get_pages(cpu_addr);
- if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+ if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
return cpu_addr;
area = find_vm_area(cpu_addr);
@@ -1511,7 +1510,7 @@ static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
}
static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs,
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs,
int coherent_flag)
{
pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL);
@@ -1542,7 +1541,7 @@ static void *__arm_iommu_alloc_attrs(struct device *dev, size_t size,
if (*handle == DMA_ERROR_CODE)
goto err_buffer;
- if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+ if (attrs & DMA_ATTR_NO_KERNEL_MAPPING)
return pages;
addr = __iommu_alloc_remap(pages, size, gfp, prot,
@@ -1560,20 +1559,20 @@ err_buffer:
}
static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
{
return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, NORMAL);
}
static void *arm_coherent_iommu_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
{
return __arm_iommu_alloc_attrs(dev, size, handle, gfp, attrs, COHERENT);
}
static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long uaddr = vma->vm_start;
unsigned long usize = vma->vm_end - vma->vm_start;
@@ -1603,7 +1602,7 @@ static int __arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma
}
static int arm_iommu_mmap_attrs(struct device *dev,
struct vm_area_struct *vma, void *cpu_addr,
- dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, size_t size, unsigned long attrs)
{
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
@@ -1612,7 +1611,7 @@ static int arm_iommu_mmap_attrs(struct device *dev,
static int arm_coherent_iommu_mmap_attrs(struct device *dev,
struct vm_area_struct *vma, void *cpu_addr,
- dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, size_t size, unsigned long attrs)
{
return __arm_iommu_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, attrs);
}
@@ -1622,7 +1621,7 @@ static int arm_coherent_iommu_mmap_attrs(struct device *dev,
* Must not be called with IRQs disabled.
*/
void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs, int coherent_flag)
+ dma_addr_t handle, unsigned long attrs, int coherent_flag)
{
struct page **pages;
size = PAGE_ALIGN(size);
@@ -1638,7 +1637,7 @@ void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
return;
}
- if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
+ if ((attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0) {
dma_common_free_remap(cpu_addr, size,
VM_ARM_DMA_CONSISTENT | VM_USERMAP);
}
@@ -1648,20 +1647,20 @@ void __arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
}
void arm_iommu_free_attrs(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs)
+ void *cpu_addr, dma_addr_t handle, unsigned long attrs)
{
__arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, NORMAL);
}
void arm_coherent_iommu_free_attrs(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs)
+ void *cpu_addr, dma_addr_t handle, unsigned long attrs)
{
__arm_iommu_free_attrs(dev, size, cpu_addr, handle, attrs, COHERENT);
}
static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr,
- size_t size, struct dma_attrs *attrs)
+ size_t size, unsigned long attrs)
{
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page **pages = __iommu_get_pages(cpu_addr, attrs);
@@ -1699,7 +1698,7 @@ static int __dma_direction_to_prot(enum dma_data_direction dir)
*/
static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
size_t size, dma_addr_t *handle,
- enum dma_data_direction dir, struct dma_attrs *attrs,
+ enum dma_data_direction dir, unsigned long attrs,
bool is_coherent)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
@@ -1720,8 +1719,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
phys_addr_t phys = page_to_phys(sg_page(s));
unsigned int len = PAGE_ALIGN(s->offset + s->length);
- if (!is_coherent &&
- !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if (!is_coherent && (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
prot = __dma_direction_to_prot(dir);
@@ -1742,7 +1740,7 @@ fail:
}
static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs,
+ enum dma_data_direction dir, unsigned long attrs,
bool is_coherent)
{
struct scatterlist *s = sg, *dma = sg, *start = sg;
@@ -1800,7 +1798,7 @@ bad_mapping:
* obtained via sg_dma_{address,length}.
*/
int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
}
@@ -1818,14 +1816,14 @@ int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
* sg_dma_{address,length}.
*/
int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
}
static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
- bool is_coherent)
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs, bool is_coherent)
{
struct scatterlist *s;
int i;
@@ -1834,8 +1832,7 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
if (sg_dma_len(s))
__iommu_remove_mapping(dev, sg_dma_address(s),
sg_dma_len(s));
- if (!is_coherent &&
- !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if (!is_coherent && (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_dev_to_cpu(sg_page(s), s->offset,
s->length, dir);
}
@@ -1852,7 +1849,8 @@ static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
* rules concerning calls here are the same as for dma_unmap_single().
*/
void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir,
+ unsigned long attrs)
{
__iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
}
@@ -1868,7 +1866,8 @@ void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
* rules concerning calls here are the same as for dma_unmap_single().
*/
void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir,
+ unsigned long attrs)
{
__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
}
@@ -1921,7 +1920,7 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
*/
static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t dma_addr;
@@ -1955,9 +1954,9 @@ fail:
*/
static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_cpu_to_dev(page, offset, size, dir);
return arm_coherent_iommu_map_page(dev, page, offset, size, dir, attrs);
@@ -1973,8 +1972,7 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
* Coherent IOMMU aware version of arm_dma_unmap_page()
*/
static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t iova = handle & PAGE_MASK;
@@ -1998,8 +1996,7 @@ static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
* IOMMU aware version of arm_dma_unmap_page()
*/
static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
dma_addr_t iova = handle & PAGE_MASK;
@@ -2010,7 +2007,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
if (!iova)
return;
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__dma_page_dev_to_cpu(page, offset, size, dir);
iommu_unmap(mapping->domain, iova, len);
diff --git a/arch/arm/xen/mm.c b/arch/arm/xen/mm.c
index c5f9a9e3d1f3..d062f08f5020 100644
--- a/arch/arm/xen/mm.c
+++ b/arch/arm/xen/mm.c
@@ -98,11 +98,11 @@ static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
void __xen_dma_map_page(struct device *hwdev, struct page *page,
dma_addr_t dev_addr, unsigned long offset, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
if (is_device_dma_coherent(hwdev))
return;
- if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
return;
__xen_dma_page_cpu_to_dev(hwdev, dev_addr, size, dir);
@@ -110,12 +110,12 @@ void __xen_dma_map_page(struct device *hwdev, struct page *page,
void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (is_device_dma_coherent(hwdev))
return;
- if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
return;
__xen_dma_page_dev_to_cpu(hwdev, handle, size, dir);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 69c8787bec7d..bc3f00f586f1 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -54,6 +54,7 @@ config ARM64
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
+ select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_HUGE_VMAP
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KASAN if SPARSEMEM_VMEMMAP && !(ARM64_16K_PAGES && ARM64_VA_BITS_48)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index bb2616b16157..be5d824ebdba 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -8,7 +8,7 @@ config ARCH_SUNXI
config ARCH_ALPINE
bool "Annapurna Labs Alpine platform"
- select ALPINE_MSI
+ select ALPINE_MSI if PCI
help
This enables support for the Annapurna Labs Alpine
Soc family.
@@ -66,7 +66,7 @@ config ARCH_LG1K
config ARCH_HISI
bool "Hisilicon SoC Family"
select ARM_TIMER_SP804
- select HISILICON_IRQ_MBIGEN
+ select HISILICON_IRQ_MBIGEN if PCI
help
This enables support for Hisilicon ARMv8 SoC family
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index d59b6908a21a..5b54f8c021d8 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -15,7 +15,7 @@ CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
GZFLAGS :=-9
ifneq ($(CONFIG_RELOCATABLE),)
-LDFLAGS_vmlinux += -pie
+LDFLAGS_vmlinux += -pie -Bsymbolic
endif
KBUILD_DEFCONFIG := defconfig
diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts
index 299f3ce969ab..c528dd52ba2d 100644
--- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts
+++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts
@@ -12,6 +12,7 @@
/dts-v1/;
#include "exynos7.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/samsung,s2mps11.h>
/ {
model = "Samsung Exynos7 Espresso board based on EXYNOS7";
@@ -43,6 +44,8 @@
&rtc {
status = "okay";
+ clocks = <&clock_ccore PCLK_RTC>, <&s2mps15_osc S2MPS11_CLK_AP>;
+ clock-names = "rtc", "rtc_src";
};
&watchdog {
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0555b7caaf2c..eadf4855ad2d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1,4 +1,3 @@
-# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_AUDIT=y
@@ -15,10 +14,14 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_HUGETLB=y
-# CONFIG_UTS_NS is not set
-# CONFIG_IPC_NS is not set
-# CONFIG_NET_NS is not set
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_USER_NS=y
CONFIG_SCHED_AUTOGROUP=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
@@ -71,6 +74,7 @@ CONFIG_PREEMPT=y
CONFIG_KSM=y
CONFIG_TRANSPARENT_HUGEPAGE=y
CONFIG_CMA=y
+CONFIG_SECCOMP=y
CONFIG_XEN=y
CONFIG_KEXEC=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -84,10 +88,37 @@ CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IPV6 is not set
+CONFIG_IPV6=m
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
CONFIG_BPF_JIT=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
@@ -103,6 +134,7 @@ CONFIG_MTD=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_SPI_NOR=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=m
CONFIG_VIRTIO_BLK=y
CONFIG_SRAM=y
# CONFIG_SCSI_PROC_FS is not set
@@ -120,7 +152,10 @@ CONFIG_SATA_SIL24=y
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_OF_PLATFORM=y
CONFIG_NETDEVICES=y
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
CONFIG_TUN=y
+CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
@@ -350,12 +385,16 @@ CONFIG_EXYNOS_ADC=y
CONFIG_PWM_SAMSUNG=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
CONFIG_FANOTIFY=y
CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_QUOTA=y
CONFIG_AUTOFS4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_CUSE=y
+CONFIG_FUSE_FS=m
+CONFIG_CUSE=m
+CONFIG_OVERLAY_FS=m
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_HUGETLBFS=y
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 579b6e654f2d..a55384f4a5d7 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -140,6 +140,7 @@ typedef struct user_fpsimd_state elf_fpregset_t;
#define SET_PERSONALITY(ex) clear_thread_flag(TIF_32BIT);
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \
do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 61b49150dfa3..1737aecfcc5e 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -22,7 +22,6 @@
#define __ARCH_WANT_KPROBES_INSN_SLOT
#define MAX_INSN_SIZE 1
-#define MAX_STACK_SIZE 128
#define flush_insn_slot(p) do { } while (0)
#define kretprobe_blacklist_size 0
@@ -47,7 +46,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
struct kprobe_step_ctx ss_ctx;
struct pt_regs jprobe_saved_regs;
- char jprobes_stack[MAX_STACK_SIZE];
};
void arch_remove_kprobe(struct kprobe *);
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 46472a91b6df..e20bd431184a 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -224,6 +224,23 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
set_pte(ptep, pte);
}
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+ pteval_t lhs, rhs;
+
+ lhs = pte_val(pte_a);
+ rhs = pte_val(pte_b);
+
+ if (pte_present(pte_a))
+ lhs &= ~PTE_RDONLY;
+
+ if (pte_present(pte_b))
+ rhs &= ~PTE_RDONLY;
+
+ return (lhs == rhs);
+}
+
/*
* Huge pte definitions.
*/
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index 5e834d10b291..c47257c91b77 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -265,22 +265,25 @@ extern unsigned long __must_check __clear_user(void __user *addr, unsigned long
static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
{
kasan_check_write(to, n);
- return __arch_copy_from_user(to, from, n);
+ check_object_size(to, n, false);
+ return __arch_copy_from_user(to, from, n);
}
static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
{
kasan_check_read(from, n);
- return __arch_copy_to_user(to, from, n);
+ check_object_size(from, n, true);
+ return __arch_copy_to_user(to, from, n);
}
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
{
kasan_check_write(to, n);
- if (access_ok(VERIFY_READ, from, n))
+ if (access_ok(VERIFY_READ, from, n)) {
+ check_object_size(to, n, false);
n = __arch_copy_from_user(to, from, n);
- else /* security hole - plug it */
+ } else /* security hole - plug it */
memset(to, 0, n);
return n;
}
@@ -289,8 +292,10 @@ static inline unsigned long __must_check copy_to_user(void __user *to, const voi
{
kasan_check_read(from, n);
- if (access_ok(VERIFY_WRITE, to, n))
+ if (access_ok(VERIFY_WRITE, to, n)) {
+ check_object_size(from, n, true);
n = __arch_copy_to_user(to, from, n);
+ }
return n;
}
diff --git a/arch/arm64/include/uapi/asm/auxvec.h b/arch/arm64/include/uapi/asm/auxvec.h
index 22d6d8885854..4cf0c17787a8 100644
--- a/arch/arm64/include/uapi/asm/auxvec.h
+++ b/arch/arm64/include/uapi/asm/auxvec.h
@@ -19,4 +19,6 @@
/* vDSO location */
#define AT_SYSINFO_EHDR 33
+#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
+
#endif
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 96e4a2b64cc1..441420ca7d08 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -353,6 +353,8 @@ el1_sync:
lsr x24, x1, #ESR_ELx_EC_SHIFT // exception class
cmp x24, #ESR_ELx_EC_DABT_CUR // data abort in EL1
b.eq el1_da
+ cmp x24, #ESR_ELx_EC_IABT_CUR // instruction abort in EL1
+ b.eq el1_ia
cmp x24, #ESR_ELx_EC_SYS64 // configurable trap
b.eq el1_undef
cmp x24, #ESR_ELx_EC_SP_ALIGN // stack alignment exception
@@ -364,6 +366,11 @@ el1_sync:
cmp x24, #ESR_ELx_EC_BREAKPT_CUR // debug exception in EL1
b.ge el1_dbg
b el1_inv
+
+el1_ia:
+ /*
+ * Fall through to the Data abort case
+ */
el1_da:
/*
* Data abort handling
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2c6e598a94dc..b77f58355da1 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -781,40 +781,25 @@ __primary_switch:
* Iterate over each entry in the relocation table, and apply the
* relocations in place.
*/
- ldr w8, =__dynsym_offset // offset to symbol table
ldr w9, =__rela_offset // offset to reloc table
ldr w10, =__rela_size // size of reloc table
mov_q x11, KIMAGE_VADDR // default virtual offset
add x11, x11, x23 // actual virtual offset
- add x8, x8, x11 // __va(.dynsym)
add x9, x9, x11 // __va(.rela)
add x10, x9, x10 // __va(.rela) + sizeof(.rela)
0: cmp x9, x10
- b.hs 2f
+ b.hs 1f
ldp x11, x12, [x9], #24
ldr x13, [x9, #-8]
cmp w12, #R_AARCH64_RELATIVE
- b.ne 1f
+ b.ne 0b
add x13, x13, x23 // relocate
str x13, [x11, x23]
b 0b
-1: cmp w12, #R_AARCH64_ABS64
- b.ne 0b
- add x12, x12, x12, lsl #1 // symtab offset: 24x top word
- add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word
- ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx
- ldr x15, [x12, #8] // Elf64_Sym::st_value
- cmp w14, #-0xf // SHN_ABS (0xfff1) ?
- add x14, x15, x23 // relocate
- csel x15, x14, x15, ne
- add x15, x13, x15
- str x15, [x11, x23]
- b 0b
-
-2:
+1:
#endif
ldr x8, =__primary_switched
br x8
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 21ab5df9fa76..65d81f965e74 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -35,6 +35,7 @@
#include <asm/sections.h>
#include <asm/smp.h>
#include <asm/suspend.h>
+#include <asm/sysreg.h>
#include <asm/virt.h>
/*
@@ -217,12 +218,22 @@ static int create_safe_exec_page(void *src_start, size_t length,
set_pte(pte, __pte(virt_to_phys((void *)dst) |
pgprot_val(PAGE_KERNEL_EXEC)));
- /* Load our new page tables */
- asm volatile("msr ttbr0_el1, %0;"
- "isb;"
- "tlbi vmalle1is;"
- "dsb ish;"
- "isb" : : "r"(virt_to_phys(pgd)));
+ /*
+ * Load our new page tables. A strict BBM approach requires that we
+ * ensure that TLBs are free of any entries that may overlap with the
+ * global mappings we are about to install.
+ *
+ * For a real hibernate/resume cycle TTBR0 currently points to a zero
+ * page, but TLBs may contain stale ASID-tagged entries (e.g. for EFI
+ * runtime services), while for a userspace-driven test_resume cycle it
+ * points to userspace page tables (and we must point it at a zero page
+ * ourselves). Elsewhere we only (un)install the idmap with preemption
+ * disabled, so T0SZ should be as required regardless.
+ */
+ cpu_set_reserved_ttbr0();
+ local_flush_tlb_all();
+ write_sysreg(virt_to_phys(pgd), ttbr0_el1);
+ isb();
*phys_dst_addr = virt_to_phys((void *)dst);
@@ -394,6 +405,38 @@ int swsusp_arch_resume(void)
void *, phys_addr_t, phys_addr_t);
/*
+ * Restoring the memory image will overwrite the ttbr1 page tables.
+ * Create a second copy of just the linear map, and use this when
+ * restoring.
+ */
+ tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
+ if (!tmp_pg_dir) {
+ pr_err("Failed to allocate memory for temporary page tables.");
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
+ if (rc)
+ goto out;
+
+ /*
+ * Since we only copied the linear map, we need to find restore_pblist's
+ * linear map address.
+ */
+ lm_restore_pblist = LMADDR(restore_pblist);
+
+ /*
+ * We need a zero page that is zero before & after resume in order to
+ * to break before make on the ttbr1 page tables.
+ */
+ zero_page = (void *)get_safe_page(GFP_ATOMIC);
+ if (!zero_page) {
+ pr_err("Failed to allocate zero page.");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /*
* Locate the exit code in the bottom-but-one page, so that *NULL
* still has disastrous affects.
*/
@@ -419,27 +462,6 @@ int swsusp_arch_resume(void)
__flush_dcache_area(hibernate_exit, exit_size);
/*
- * Restoring the memory image will overwrite the ttbr1 page tables.
- * Create a second copy of just the linear map, and use this when
- * restoring.
- */
- tmp_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
- if (!tmp_pg_dir) {
- pr_err("Failed to allocate memory for temporary page tables.");
- rc = -ENOMEM;
- goto out;
- }
- rc = copy_page_tables(tmp_pg_dir, PAGE_OFFSET, 0);
- if (rc)
- goto out;
-
- /*
- * Since we only copied the linear map, we need to find restore_pblist's
- * linear map address.
- */
- lm_restore_pblist = LMADDR(restore_pblist);
-
- /*
* KASLR will cause the el2 vectors to be in a different location in
* the resumed kernel. Load hibernate's temporary copy into el2.
*
@@ -453,12 +475,6 @@ int swsusp_arch_resume(void)
__hyp_set_vectors(el2_vectors);
}
- /*
- * We need a zero page that is zero before & after resume in order to
- * to break before make on the ttbr1 page tables.
- */
- zero_page = (void *)get_safe_page(GFP_ATOMIC);
-
hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1,
resume_hdr.reenter_kernel, lm_restore_pblist,
resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page));
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index bf9768588288..c6b0f40620d8 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -41,18 +41,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
static void __kprobes
post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
-static inline unsigned long min_stack_size(unsigned long addr)
-{
- unsigned long size;
-
- if (on_irq_stack(addr, raw_smp_processor_id()))
- size = IRQ_STACK_PTR(raw_smp_processor_id()) - addr;
- else
- size = (unsigned long)current_thread_info() + THREAD_START_SP - addr;
-
- return min(size, FIELD_SIZEOF(struct kprobe_ctlblk, jprobes_stack));
-}
-
static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
{
/* prepare insn slot */
@@ -489,20 +477,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
- long stack_ptr = kernel_stack_pointer(regs);
kcb->jprobe_saved_regs = *regs;
/*
- * As Linus pointed out, gcc assumes that the callee
- * owns the argument space and could overwrite it, e.g.
- * tailcall optimization. So, to be absolutely safe
- * we also save and restore enough stack bytes to cover
- * the argument area.
+ * Since we can't be sure where in the stack frame "stacked"
+ * pass-by-value arguments are stored we just don't try to
+ * duplicate any of the stack. Do not use jprobes on functions that
+ * use more than 64 bytes (after padding each to an 8 byte boundary)
+ * of arguments, or pass individual arguments larger than 16 bytes.
*/
- kasan_disable_current();
- memcpy(kcb->jprobes_stack, (void *)stack_ptr,
- min_stack_size(stack_ptr));
- kasan_enable_current();
instruction_pointer_set(regs, (unsigned long) jp->entry);
preempt_disable();
@@ -554,10 +537,6 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
}
unpause_graph_tracing();
*regs = kcb->jprobe_saved_regs;
- kasan_disable_current();
- memcpy((void *)stack_addr, kcb->jprobes_stack,
- min_stack_size(stack_addr));
- kasan_enable_current();
preempt_enable_no_resched();
return 1;
}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 76a6d9263908..d93d43352504 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -661,9 +661,9 @@ void __init smp_init_cpus(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
acpi_parse_gic_cpu_interface, 0);
- if (cpu_count > NR_CPUS)
- pr_warn("no. of cores (%d) greater than configured maximum of %d - clipping\n",
- cpu_count, NR_CPUS);
+ if (cpu_count > nr_cpu_ids)
+ pr_warn("Number of cores (%d) exceeds configured maximum of %d - clipping\n",
+ cpu_count, nr_cpu_ids);
if (!bootcpu_valid) {
pr_err("missing boot CPU MPIDR, not enabling secondaries\n");
@@ -677,7 +677,7 @@ void __init smp_init_cpus(void)
* with entries in cpu_logical_map while initializing the cpus.
* If the cpu set-up fails, invalidate the cpu_logical_map entry.
*/
- for (i = 1; i < NR_CPUS; i++) {
+ for (i = 1; i < nr_cpu_ids; i++) {
if (cpu_logical_map(i) != INVALID_HWID) {
if (smp_cpu_setup(i))
cpu_logical_map(i) = INVALID_HWID;
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 89d6e177ecbd..659963d40bb4 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -103,6 +103,7 @@ SECTIONS
*(.discard)
*(.discard.*)
*(.interp .dynamic)
+ *(.dynsym .dynstr .hash)
}
. = KIMAGE_VADDR + TEXT_OFFSET;
@@ -174,19 +175,9 @@ SECTIONS
.rela : ALIGN(8) {
*(.rela .rela*)
}
- .dynsym : ALIGN(8) {
- *(.dynsym)
- }
- .dynstr : {
- *(.dynstr)
- }
- .hash : {
- *(.hash)
- }
- __rela_offset = ADDR(.rela) - KIMAGE_VADDR;
+ __rela_offset = ABSOLUTE(ADDR(.rela) - KIMAGE_VADDR);
__rela_size = SIZEOF(.rela);
- __dynsym_offset = ADDR(.dynsym) - KIMAGE_VADDR;
. = ALIGN(SEGMENT_ALIGN);
__init_end = .;
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 9d2eff0b3ad3..9c9edc98d271 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -37,6 +37,8 @@ config KVM
select KVM_ARM_VGIC_V3
select KVM_ARM_PMU if HW_PERF_EVENTS
select HAVE_KVM_MSI
+ select HAVE_KVM_IRQCHIP
+ select HAVE_KVM_IRQ_ROUTING
---help---
Support hosting virtualized guest machines.
We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index a5b96642a9cb..695eb3c7ef41 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -30,5 +30,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index e9e0e6db73f6..898c0e6aedd4 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -132,16 +132,14 @@ static u64 get_except_vector(struct kvm_vcpu *vcpu, enum exception_type type)
static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
{
unsigned long cpsr = *vcpu_cpsr(vcpu);
- bool is_aarch32;
+ bool is_aarch32 = vcpu_mode_is_32bit(vcpu);
u32 esr = 0;
- is_aarch32 = vcpu_mode_is_32bit(vcpu);
-
- *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+ *vcpu_spsr(vcpu) = cpsr;
vcpu_sys_reg(vcpu, FAR_EL1) = addr;
@@ -172,11 +170,11 @@ static void inject_undef64(struct kvm_vcpu *vcpu)
unsigned long cpsr = *vcpu_cpsr(vcpu);
u32 esr = (ESR_ELx_EC_UNKNOWN << ESR_ELx_EC_SHIFT);
- *vcpu_spsr(vcpu) = cpsr;
*vcpu_elr_el1(vcpu) = *vcpu_pc(vcpu);
-
*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
+
*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+ *vcpu_spsr(vcpu) = cpsr;
/*
* Build an unknown exception, depending on the instruction
diff --git a/arch/arm64/kvm/irq.h b/arch/arm64/kvm/irq.h
new file mode 100644
index 000000000000..b74099b905fd
--- /dev/null
+++ b/arch/arm64/kvm/irq.h
@@ -0,0 +1,19 @@
+/*
+ * irq.h: in kernel interrupt controller related definitions
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * 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 header is included by irqchip.c. However, on ARM, interrupt
+ * controller declarations are located in include/kvm/arm_vgic.h since
+ * they are mostly shared between arm and arm64.
+ */
+
+#ifndef __IRQ_H
+#define __IRQ_H
+
+#include <kvm/arm_vgic.h>
+
+#endif
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index f6c55afab3e2..c4284c432ae8 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -32,10 +32,10 @@
static int swiotlb __read_mostly;
-static pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot,
+static pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot,
bool coherent)
{
- if (!coherent || dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+ if (!coherent || (attrs & DMA_ATTR_WRITE_COMBINE))
return pgprot_writecombine(prot);
return prot;
}
@@ -91,7 +91,7 @@ static int __free_from_pool(void *start, size_t size)
static void *__dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (dev == NULL) {
WARN_ONCE(1, "Use an actual device structure for DMA allocation\n");
@@ -121,7 +121,7 @@ static void *__dma_alloc_coherent(struct device *dev, size_t size,
static void __dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
bool freed;
phys_addr_t paddr = dma_to_phys(dev, dma_handle);
@@ -140,7 +140,7 @@ static void __dma_free_coherent(struct device *dev, size_t size,
static void *__dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct page *page;
void *ptr, *coherent_ptr;
@@ -188,7 +188,7 @@ no_mem:
static void __dma_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *swiotlb_addr = phys_to_virt(dma_to_phys(dev, dma_handle));
@@ -205,7 +205,7 @@ static void __dma_free(struct device *dev, size_t size,
static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t dev_addr;
@@ -219,7 +219,7 @@ static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (!is_device_dma_coherent(dev))
__dma_unmap_area(phys_to_virt(dma_to_phys(dev, dev_addr)), size, dir);
@@ -228,7 +228,7 @@ static void __swiotlb_unmap_page(struct device *dev, dma_addr_t dev_addr,
static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i, ret;
@@ -245,7 +245,7 @@ static int __swiotlb_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
static void __swiotlb_unmap_sg_attrs(struct device *dev,
struct scatterlist *sgl, int nelems,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -306,7 +306,7 @@ static void __swiotlb_sync_sg_for_device(struct device *dev,
static int __swiotlb_mmap(struct device *dev,
struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int ret = -ENXIO;
unsigned long nr_vma_pages = (vma->vm_end - vma->vm_start) >>
@@ -333,7 +333,7 @@ static int __swiotlb_mmap(struct device *dev,
static int __swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t handle, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
@@ -435,21 +435,21 @@ out:
static void *__dummy_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return NULL;
}
static void __dummy_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
}
static int __dummy_mmap(struct device *dev,
struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return -ENXIO;
}
@@ -457,20 +457,20 @@ static int __dummy_mmap(struct device *dev,
static dma_addr_t __dummy_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return DMA_ERROR_CODE;
}
static void __dummy_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
}
static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return 0;
}
@@ -478,7 +478,7 @@ static int __dummy_map_sg(struct device *dev, struct scatterlist *sgl,
static void __dummy_unmap_sg(struct device *dev,
struct scatterlist *sgl, int nelems,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
}
@@ -553,7 +553,7 @@ static void flush_page(struct device *dev, const void *virt, phys_addr_t phys)
static void *__iommu_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
bool coherent = is_device_dma_coherent(dev);
int ioprot = dma_direction_to_prot(DMA_BIDIRECTIONAL, coherent);
@@ -613,7 +613,7 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
}
static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t handle, struct dma_attrs *attrs)
+ dma_addr_t handle, unsigned long attrs)
{
size_t iosize = size;
@@ -629,7 +629,7 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
* Hence how dodgy the below logic looks...
*/
if (__in_atomic_pool(cpu_addr, size)) {
- iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
+ iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
__free_from_pool(cpu_addr, size);
} else if (is_vmalloc_addr(cpu_addr)){
struct vm_struct *area = find_vm_area(cpu_addr);
@@ -639,14 +639,14 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
iommu_dma_free(dev, area->pages, iosize, &handle);
dma_common_free_remap(cpu_addr, size, VM_USERMAP);
} else {
- iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
+ iommu_dma_unmap_page(dev, handle, iosize, 0, 0);
__free_pages(virt_to_page(cpu_addr), get_order(size));
}
}
static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vm_struct *area;
int ret;
@@ -666,7 +666,7 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr,
- size_t size, struct dma_attrs *attrs)
+ size_t size, unsigned long attrs)
{
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct vm_struct *area = find_vm_area(cpu_addr);
@@ -707,14 +707,14 @@ static void __iommu_sync_single_for_device(struct device *dev,
static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
bool coherent = is_device_dma_coherent(dev);
int prot = dma_direction_to_prot(dir, coherent);
dma_addr_t dev_addr = iommu_dma_map_page(dev, page, offset, size, prot);
if (!iommu_dma_mapping_error(dev, dev_addr) &&
- !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ (attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__iommu_sync_single_for_device(dev, dev_addr, size, dir);
return dev_addr;
@@ -722,9 +722,9 @@ static dma_addr_t __iommu_map_page(struct device *dev, struct page *page,
static void __iommu_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__iommu_sync_single_for_cpu(dev, dev_addr, size, dir);
iommu_dma_unmap_page(dev, dev_addr, size, dir, attrs);
@@ -760,11 +760,11 @@ static void __iommu_sync_sg_for_device(struct device *dev,
static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
bool coherent = is_device_dma_coherent(dev);
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__iommu_sync_sg_for_device(dev, sgl, nelems, dir);
return iommu_dma_map_sg(dev, sgl, nelems,
@@ -774,9 +774,9 @@ static int __iommu_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
static void __iommu_unmap_sg_attrs(struct device *dev,
struct scatterlist *sgl, int nelems,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+ if ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)
__iommu_sync_sg_for_cpu(dev, sgl, nelems, dir);
iommu_dma_unmap_sg(dev, sgl, nelems, dir, attrs);
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index c8beaa0da7df..05d2bd776c69 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -153,6 +153,11 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
}
#endif
+static bool is_el1_instruction_abort(unsigned int esr)
+{
+ return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR;
+}
+
/*
* The kernel tried to access some page that wasn't present.
*/
@@ -161,8 +166,9 @@ static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
{
/*
* Are we prepared to handle this kernel fault?
+ * We are almost certainly not prepared to handle instruction faults.
*/
- if (fixup_exception(regs))
+ if (!is_el1_instruction_abort(esr) && fixup_exception(regs))
return;
/*
@@ -267,7 +273,8 @@ static inline bool is_permission_fault(unsigned int esr)
unsigned int ec = ESR_ELx_EC(esr);
unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
- return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
+ return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) ||
+ (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
}
static bool is_el0_instruction_abort(unsigned int esr)
@@ -312,6 +319,9 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
if (regs->orig_addr_limit == KERNEL_DS)
die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
+ if (is_el1_instruction_abort(esr))
+ die("Attempting to execute userspace memory", regs, esr);
+
if (!search_exception_tables(regs->pc))
die("Accessing user space memory outside uaccess.h routines", regs, esr);
}
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 51a558195bb9..4989948d1feb 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -686,9 +686,9 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
/*
* Check whether the physical FDT address is set and meets the minimum
* alignment requirement. Since we are relying on MIN_FDT_ALIGN to be
- * at least 8 bytes so that we can always access the size field of the
- * FDT header after mapping the first chunk, double check here if that
- * is indeed the case.
+ * at least 8 bytes so that we can always access the magic and size
+ * fields of the FDT header after mapping the first chunk, double check
+ * here if that is indeed the case.
*/
BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
@@ -716,7 +716,7 @@ void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size, pgprot_t prot)
create_mapping_noalloc(round_down(dt_phys, SWAPPER_BLOCK_SIZE),
dt_virt_base, SWAPPER_BLOCK_SIZE, prot);
- if (fdt_check_header(dt_virt) != 0)
+ if (fdt_magic(dt_virt) != FDT_MAGIC)
return NULL;
*size = fdt_totalsize(dt_virt);
diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
index 92cf1fb2b3e6..58610d0df7ed 100644
--- a/arch/avr32/mm/dma-coherent.c
+++ b/arch/avr32/mm/dma-coherent.c
@@ -99,7 +99,7 @@ static void __dma_free(struct device *dev, size_t size,
}
static void *avr32_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
{
struct page *page;
dma_addr_t phys;
@@ -109,7 +109,7 @@ static void *avr32_dma_alloc(struct device *dev, size_t size,
return NULL;
phys = page_to_phys(page);
- if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) {
+ if (attrs & DMA_ATTR_WRITE_COMBINE) {
/* Now, map the page into P3 with write-combining turned on */
*handle = phys;
return __ioremap(phys, size, _PAGE_BUFFER);
@@ -119,11 +119,11 @@ static void *avr32_dma_alloc(struct device *dev, size_t size,
}
static void avr32_dma_free(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t handle, struct dma_attrs *attrs)
+ void *cpu_addr, dma_addr_t handle, unsigned long attrs)
{
struct page *page;
- if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs)) {
+ if (attrs & DMA_ATTR_WRITE_COMBINE) {
iounmap(cpu_addr);
page = phys_to_page(handle);
@@ -142,7 +142,7 @@ static void avr32_dma_free(struct device *dev, size_t size,
static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
void *cpu_addr = page_address(page) + offset;
@@ -152,7 +152,7 @@ static dma_addr_t avr32_dma_map_page(struct device *dev, struct page *page,
static int avr32_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c
index 771afe6e4264..53fbbb61aa86 100644
--- a/arch/blackfin/kernel/dma-mapping.c
+++ b/arch/blackfin/kernel/dma-mapping.c
@@ -79,7 +79,7 @@ static void __free_dma_pages(unsigned long addr, unsigned int pages)
}
static void *bfin_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -94,7 +94,7 @@ static void *bfin_dma_alloc(struct device *dev, size_t size,
}
static void bfin_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
__free_dma_pages((unsigned long)vaddr, get_pages(size));
}
@@ -111,7 +111,7 @@ EXPORT_SYMBOL(__dma_sync);
static int bfin_dma_map_sg(struct device *dev, struct scatterlist *sg_list,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -139,7 +139,7 @@ static void bfin_dma_sync_sg_for_device(struct device *dev,
static dma_addr_t bfin_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t handle = (dma_addr_t)(page_address(page) + offset);
diff --git a/arch/c6x/include/asm/dma-mapping.h b/arch/c6x/include/asm/dma-mapping.h
index 6b5cd7b0cf32..5717b1e52d96 100644
--- a/arch/c6x/include/asm/dma-mapping.h
+++ b/arch/c6x/include/asm/dma-mapping.h
@@ -26,8 +26,8 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
extern void coherent_mem_init(u32 start, u32 size);
void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t gfp, struct dma_attrs *attrs);
+ gfp_t gfp, unsigned long attrs);
void c6x_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs);
+ dma_addr_t dma_handle, unsigned long attrs);
#endif /* _ASM_C6X_DMA_MAPPING_H */
diff --git a/arch/c6x/kernel/dma.c b/arch/c6x/kernel/dma.c
index 8a80f3a250c0..db4a6a301f5e 100644
--- a/arch/c6x/kernel/dma.c
+++ b/arch/c6x/kernel/dma.c
@@ -38,7 +38,7 @@ static void c6x_dma_sync(dma_addr_t handle, size_t size,
static dma_addr_t c6x_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t handle = virt_to_phys(page_address(page) + offset);
@@ -47,13 +47,13 @@ static dma_addr_t c6x_dma_map_page(struct device *dev, struct page *page,
}
static void c6x_dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir, struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
{
c6x_dma_sync(handle, size, dir);
}
static int c6x_dma_map_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -67,8 +67,7 @@ static int c6x_dma_map_sg(struct device *dev, struct scatterlist *sglist,
}
static void c6x_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *sg;
int i;
diff --git a/arch/c6x/mm/dma-coherent.c b/arch/c6x/mm/dma-coherent.c
index f7ee63af2541..95e38ad27c69 100644
--- a/arch/c6x/mm/dma-coherent.c
+++ b/arch/c6x/mm/dma-coherent.c
@@ -74,7 +74,7 @@ static void __free_dma_pages(u32 addr, int order)
* virtual and DMA address for that space.
*/
void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t gfp, struct dma_attrs *attrs)
+ gfp_t gfp, unsigned long attrs)
{
u32 paddr;
int order;
@@ -99,7 +99,7 @@ void *c6x_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
* Free DMA coherent memory as defined by the above mapping.
*/
void c6x_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
int order;
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
index 8d5efa58cce1..1f0636793f0c 100644
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ b/arch/cris/arch-v32/drivers/pci/dma.c
@@ -17,7 +17,7 @@
#include <asm/io.h>
static void *v32_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -37,22 +37,21 @@ static void *v32_dma_alloc(struct device *dev, size_t size,
}
static void v32_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
free_pages((unsigned long)vaddr, get_order(size));
}
static inline dma_addr_t v32_dma_map_page(struct device *dev,
struct page *page, unsigned long offset, size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
return page_to_phys(page) + offset;
}
static inline int v32_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
printk("Map sg\n");
return nents;
diff --git a/arch/frv/include/asm/mc146818rtc.h b/arch/frv/include/asm/mc146818rtc.h
deleted file mode 100644
index 90dfb7a633d1..000000000000
--- a/arch/frv/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* mc146818rtc.h: RTC defs
- *
- * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@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; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-
-#endif /* _ASM_MC146818RTC_H */
diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c
index 082be49b5df0..90f2e4cb33d6 100644
--- a/arch/frv/mb93090-mb00/pci-dma-nommu.c
+++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c
@@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(dma_alloc_lock);
static LIST_HEAD(dma_alloc_list);
static void *frv_dma_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp, struct dma_attrs *attrs)
+ gfp_t gfp, unsigned long attrs)
{
struct dma_alloc_record *new;
struct list_head *this = &dma_alloc_list;
@@ -86,7 +86,7 @@ static void *frv_dma_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_ha
}
static void frv_dma_free(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
struct dma_alloc_record *rec;
unsigned long flags;
@@ -107,7 +107,7 @@ static void frv_dma_free(struct device *hwdev, size_t size, void *vaddr,
static int frv_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
@@ -124,7 +124,7 @@ static int frv_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static dma_addr_t frv_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
BUG_ON(direction == DMA_NONE);
flush_dcache_page(page);
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 316b7b65348d..f585745b1abc 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -19,8 +19,7 @@
#include <asm/io.h>
static void *frv_dma_alloc(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -32,14 +31,14 @@ static void *frv_dma_alloc(struct device *hwdev, size_t size,
}
static void frv_dma_free(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
consistent_free(vaddr);
}
static int frv_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long dampr2;
void *vaddr;
@@ -69,7 +68,7 @@ static int frv_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static dma_addr_t frv_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
flush_dcache_page(page);
return (dma_addr_t) page_to_phys(page) + offset;
diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h
index 2e221c5f0203..f86918aed9e1 100644
--- a/arch/h8300/include/asm/io.h
+++ b/arch/h8300/include/asm/io.h
@@ -3,6 +3,8 @@
#ifdef __KERNEL__
+#include <linux/types.h>
+
/* H8/300 internal I/O functions */
#define __raw_readb __raw_readb
diff --git a/arch/h8300/include/asm/mc146818rtc.h b/arch/h8300/include/asm/mc146818rtc.h
deleted file mode 100644
index ab9d9646d241..000000000000
--- a/arch/h8300/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _H8300_MC146818RTC_H
-#define _H8300_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c/ide-geometry.c */
-
-#endif /* _H8300_MC146818RTC_H */
diff --git a/arch/h8300/kernel/dma.c b/arch/h8300/kernel/dma.c
index eeb13d3f2424..3651da045806 100644
--- a/arch/h8300/kernel/dma.c
+++ b/arch/h8300/kernel/dma.c
@@ -12,7 +12,7 @@
static void *dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
@@ -32,7 +32,7 @@ static void *dma_alloc(struct device *dev, size_t size,
static void dma_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
free_pages((unsigned long)vaddr, get_order(size));
@@ -41,14 +41,14 @@ static void dma_free(struct device *dev, size_t size,
static dma_addr_t map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return page_to_phys(page) + offset;
}
static int map_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
index aa6203464520..7ef58df909fc 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -26,7 +26,6 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-debug.h>
-#include <linux/dma-attrs.h>
#include <asm/io.h>
struct device;
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index 9e3ddf792bd3..b9017785fb71 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -51,7 +51,7 @@ static struct gen_pool *coherent_pool;
static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
@@ -84,7 +84,7 @@ static void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
}
static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, unsigned long attrs)
{
gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
}
@@ -105,7 +105,7 @@ static int check_addr(const char *name, struct device *hwdev,
static int hexagon_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
@@ -172,7 +172,7 @@ static inline void dma_sync(void *addr, size_t size,
static dma_addr_t hexagon_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t bus = page_to_phys(page) + offset;
WARN_ON(size == 0);
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 6a15083cc366..18ca6a9ce566 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -52,6 +52,7 @@ config IA64
select MODULES_USE_ELF_RELA
select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_HARDENED_USERCOPY
default y
help
The Itanium Processor Family is Intel's 64-bit successor to
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index a6d6190c9d24..630ee8073899 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -919,7 +919,7 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
static dma_addr_t sba_map_page(struct device *dev, struct page *page,
unsigned long poff, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct ioc *ioc;
void *addr = page_address(page) + poff;
@@ -1005,7 +1005,7 @@ static dma_addr_t sba_map_page(struct device *dev, struct page *page,
static dma_addr_t sba_map_single_attrs(struct device *dev, void *addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return sba_map_page(dev, virt_to_page(addr),
(unsigned long)addr & ~PAGE_MASK, size, dir, attrs);
@@ -1046,7 +1046,7 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size)
* See Documentation/DMA-API-HOWTO.txt
*/
static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct ioc *ioc;
#if DELAYED_RESOURCE_CNT > 0
@@ -1115,7 +1115,7 @@ static void sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
}
void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
sba_unmap_page(dev, iova, size, dir, attrs);
}
@@ -1130,7 +1130,7 @@ void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size,
*/
static void *
sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t flags, struct dma_attrs *attrs)
+ gfp_t flags, unsigned long attrs)
{
struct ioc *ioc;
void *addr;
@@ -1175,7 +1175,7 @@ sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
* device to map single to get an iova mapping.
*/
*dma_handle = sba_map_single_attrs(&ioc->sac_only_dev->dev, addr,
- size, 0, NULL);
+ size, 0, 0);
return addr;
}
@@ -1191,9 +1191,9 @@ sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
* See Documentation/DMA-API-HOWTO.txt
*/
static void sba_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
- sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL);
+ sba_unmap_single_attrs(dev, dma_handle, size, 0, 0);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -1442,7 +1442,7 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
/**
* sba_map_sg - map Scatter/Gather list
* @dev: instance of PCI owned by the driver that's asking.
@@ -1455,7 +1455,7 @@ static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
*/
static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct ioc *ioc;
int coalesced, filled = 0;
@@ -1551,7 +1551,7 @@ static int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist,
*/
static void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef ASSERT_PDIR_SANITY
struct ioc *ioc;
diff --git a/arch/ia64/include/asm/machvec.h b/arch/ia64/include/asm/machvec.h
index 9c39bdfc2da8..ed7f09089f12 100644
--- a/arch/ia64/include/asm/machvec.h
+++ b/arch/ia64/include/asm/machvec.h
@@ -22,7 +22,6 @@ struct pci_bus;
struct task_struct;
struct pci_dev;
struct msi_desc;
-struct dma_attrs;
typedef void ia64_mv_setup_t (char **);
typedef void ia64_mv_cpu_init_t (void);
diff --git a/arch/ia64/include/asm/mc146818rtc.h b/arch/ia64/include/asm/mc146818rtc.h
deleted file mode 100644
index 407787a237ba..000000000000
--- a/arch/ia64/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_IA64_MC146818RTC_H
-#define _ASM_IA64_MC146818RTC_H
-
-/*
- * Machine dependent access functions for RTC registers.
- */
-
-/* empty include file to satisfy the include in genrtc.c */
-
-#endif /* _ASM_IA64_MC146818RTC_H */
diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h
index 2189d5ddc1ee..465c70982f40 100644
--- a/arch/ia64/include/asm/uaccess.h
+++ b/arch/ia64/include/asm/uaccess.h
@@ -241,12 +241,18 @@ extern unsigned long __must_check __copy_user (void __user *to, const void __use
static inline unsigned long
__copy_to_user (void __user *to, const void *from, unsigned long count)
{
+ if (!__builtin_constant_p(count))
+ check_object_size(from, count, true);
+
return __copy_user(to, (__force void __user *) from, count);
}
static inline unsigned long
__copy_from_user (void *to, const void __user *from, unsigned long count)
{
+ if (!__builtin_constant_p(count))
+ check_object_size(to, count, false);
+
return __copy_user((__force void __user *) to, from, count);
}
@@ -258,8 +264,11 @@ __copy_from_user (void *to, const void __user *from, unsigned long count)
const void *__cu_from = (from); \
long __cu_len = (n); \
\
- if (__access_ok(__cu_to, __cu_len, get_fs())) \
- __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \
+ if (__access_ok(__cu_to, __cu_len, get_fs())) { \
+ if (!__builtin_constant_p(n)) \
+ check_object_size(__cu_from, __cu_len, true); \
+ __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \
+ } \
__cu_len; \
})
@@ -270,8 +279,11 @@ __copy_from_user (void *to, const void __user *from, unsigned long count)
long __cu_len = (n); \
\
__chk_user_ptr(__cu_from); \
- if (__access_ok(__cu_from, __cu_len, get_fs())) \
+ if (__access_ok(__cu_from, __cu_len, get_fs())) { \
+ if (!__builtin_constant_p(n)) \
+ check_object_size(__cu_to, __cu_len, false); \
__cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \
+ } \
__cu_len; \
})
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index 939260aeac98..2933208c0285 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -16,7 +16,7 @@ EXPORT_SYMBOL(swiotlb);
static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
gfp |= GFP_DMA;
@@ -25,7 +25,7 @@ static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
static void ia64_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
}
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index 8f59907007cb..74c934a997bb 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -77,7 +77,7 @@ EXPORT_SYMBOL(sn_dma_set_mask);
*/
static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *cpuaddr;
unsigned long phys_addr;
@@ -138,7 +138,7 @@ static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
* any associated IOMMU mappings.
*/
static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -176,21 +176,18 @@ static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr
static dma_addr_t sn_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *cpu_addr = page_address(page) + offset;
dma_addr_t dma_addr;
unsigned long phys_addr;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
- int dmabarr;
-
- dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
BUG_ON(!dev_is_pci(dev));
phys_addr = __pa(cpu_addr);
- if (dmabarr)
+ if (attrs & DMA_ATTR_WRITE_BARRIER)
dma_addr = provider->dma_map_consistent(pdev, phys_addr,
size, SN_DMA_ADDR_PHYS);
else
@@ -218,7 +215,7 @@ static dma_addr_t sn_dma_map_page(struct device *dev, struct page *page,
*/
static void sn_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -240,7 +237,7 @@ static void sn_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
*/
static void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
int nhwentries, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct pci_dev *pdev = to_pci_dev(dev);
@@ -273,16 +270,13 @@ static void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl,
*/
static int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl,
int nhwentries, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long phys_addr;
struct scatterlist *saved_sg = sgl, *sg;
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
int i;
- int dmabarr;
-
- dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs);
BUG_ON(!dev_is_pci(dev));
@@ -292,7 +286,7 @@ static int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl,
for_each_sg(sgl, sg, nhwentries, i) {
dma_addr_t dma_addr;
phys_addr = SG_ENT_PHYS_ADDRESS(sg);
- if (dmabarr)
+ if (attrs & DMA_ATTR_WRITE_BARRIER)
dma_addr = provider->dma_map_consistent(pdev,
phys_addr,
sg->length,
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 01693df7f2f6..ec9cc1fdd237 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -35,7 +35,6 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/irq.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/io.h>
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 6e62d66c396e..432bc8bacfc2 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -15,7 +15,6 @@
#include <asm/pgtable.h>
#include <asm/apollohw.h>
#include <asm/irq.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
u_long sio01_physaddr;
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 478623dbb209..611d4d9ea2bd 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -34,7 +34,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/bvme6000hw.h>
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index a9befe65adc4..7cfab158fb61 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/console.h>
+#include <linux/rtc.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-hp300.h>
@@ -20,7 +21,6 @@
#include <asm/blinken.h>
#include <asm/io.h> /* readb() and writeb() */
#include <asm/hp300hw.h>
-#include <asm/rtc.h>
#include "time.h"
diff --git a/arch/m68k/include/asm/flat.h b/arch/m68k/include/asm/flat.h
index f9454b89a51b..00c392b0cabd 100644
--- a/arch/m68k/include/asm/flat.h
+++ b/arch/m68k/include/asm/flat.h
@@ -1,5 +1,5 @@
/*
- * include/asm-m68knommu/flat.h -- uClinux flat-format executables
+ * flat.h -- uClinux flat-format executables
*/
#ifndef __M68KNOMMU_FLAT_H__
@@ -8,8 +8,9 @@
#define flat_argvp_envp_on_stack() 1
#define flat_old_ram_flag(flags) (flags)
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp)
-#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp)
+#define flat_get_addr_from_rp(rp, relval, flags, p) \
+ ({ unsigned long __val; __get_user_unaligned(__val, rp); __val; })
+#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp)
#define flat_get_relocate_addr(rel) (rel)
static inline int flat_set_persistent(unsigned long relval,
@@ -18,4 +19,10 @@ static inline int flat_set_persistent(unsigned long relval,
return 0;
}
+#define FLAT_PLAT_INIT(regs) \
+ do { \
+ if (current->mm) \
+ (regs)->d5 = current->mm->start_data; \
+ } while (0)
+
#endif /* __M68KNOMMU_FLAT_H__ */
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index a6ce2ec8d693..c84a2183b3f0 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -110,7 +110,6 @@ struct thread_struct {
#define setframeformat(_regs) do { } while (0)
#endif
-#ifdef CONFIG_MMU
/*
* Do necessary setup to start up a newly executed thread.
*/
@@ -123,26 +122,14 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
wrusp(usp);
}
+#ifdef CONFIG_MMU
extern int handle_kernel_fault(struct pt_regs *regs);
-
#else
-
-#define start_thread(_regs, _pc, _usp) \
-do { \
- (_regs)->pc = (_pc); \
- setframeformat(_regs); \
- if (current->mm) \
- (_regs)->d5 = current->mm->start_data; \
- (_regs)->sr &= ~0x2000; \
- wrusp(_usp); \
-} while(0)
-
static inline int handle_kernel_fault(struct pt_regs *regs)
{
/* Any fault in kernel is fatal on non-mmu */
return 0;
}
-
#endif
/* Forward declaration, a strange C thing */
diff --git a/arch/m68k/include/asm/rtc.h b/arch/m68k/include/asm/rtc.h
deleted file mode 100644
index a4d08ea122ee..000000000000
--- a/arch/m68k/include/asm/rtc.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* include/asm-m68k/rtc.h
- *
- * Copyright Richard Zidlicky
- * implementation details for genrtc/q40rtc driver
- */
-/* permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-
-#ifndef _ASM_RTC_H
-#define _ASM_RTC_H
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-#include <asm/errno.h>
-#include <asm/machdep.h>
-
-#define RTC_PIE 0x40 /* periodic interrupt enable */
-#define RTC_AIE 0x20 /* alarm interrupt enable */
-#define RTC_UIE 0x10 /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100 /* battery bad */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
- /*
- * Only the values that we read from the RTC are set. We leave
- * tm_wday, tm_yday and tm_isdst untouched. Even though the
- * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
- * by the RTC when initially set to a non-zero value.
- */
- if (mach_hwclk)
- mach_hwclk(0, time);
- return RTC_24H;
-}
-
-static inline int set_rtc_time(struct rtc_time *time)
-{
- if (mach_hwclk)
- return mach_hwclk(1, time);
- return -EINVAL;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
- if (mach_get_ss)
- return mach_get_ss();
- else{
- struct rtc_time h;
-
- get_rtc_time(&h);
- return h.tm_sec;
- }
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
- if (mach_get_rtc_pll)
- return mach_get_rtc_pll(pll);
- else
- return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
- if (mach_set_rtc_pll)
- return mach_set_rtc_pll(pll);
- else
- return -EINVAL;
-}
-#endif /* __KERNEL__ */
-
-#endif /* _ASM__RTC_H */
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
index cbc78b4117b5..8cf97cbadc91 100644
--- a/arch/m68k/kernel/dma.c
+++ b/arch/m68k/kernel/dma.c
@@ -19,7 +19,7 @@
#if defined(CONFIG_MMU) && !defined(CONFIG_COLDFIRE)
static void *m68k_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t flag, struct dma_attrs *attrs)
+ gfp_t flag, unsigned long attrs)
{
struct page *page, **map;
pgprot_t pgprot;
@@ -62,7 +62,7 @@ static void *m68k_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
}
static void m68k_dma_free(struct device *dev, size_t size, void *addr,
- dma_addr_t handle, struct dma_attrs *attrs)
+ dma_addr_t handle, unsigned long attrs)
{
pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
vfree(addr);
@@ -73,7 +73,7 @@ static void m68k_dma_free(struct device *dev, size_t size, void *addr,
#include <asm/cacheflush.h>
static void *m68k_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
/* ignore region specifiers */
@@ -91,7 +91,7 @@ static void *m68k_dma_alloc(struct device *dev, size_t size,
}
static void m68k_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
free_pages((unsigned long)vaddr, get_order(size));
}
@@ -130,7 +130,7 @@ static void m68k_dma_sync_sg_for_device(struct device *dev,
static dma_addr_t m68k_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t handle = page_to_phys(page) + offset;
@@ -139,7 +139,7 @@ static dma_addr_t m68k_dma_map_page(struct device *dev, struct page *page,
}
static int m68k_dma_map_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction dir, unsigned long attrs)
{
int i;
struct scatterlist *sg;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 2dcee3a88867..9202f82dfce6 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -213,7 +213,6 @@ static inline int frame_extra_sizes(int f)
static inline void adjustformat(struct pt_regs *regs)
{
- ((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
/*
* set format byte to make stack appear modulo 4, which it will
* be when doing the rte
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 3857737e3958..4e5aa2f4f522 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -86,7 +86,49 @@ void read_persistent_clock(struct timespec *ts)
}
}
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+#if defined(CONFIG_ARCH_USES_GETTIMEOFFSET) && IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+ mach_hwclk(0, tm);
+ return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+ if (mach_hwclk(1, tm) < 0)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static int rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct rtc_pll_info pll;
+ struct rtc_pll_info __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case RTC_PLL_GET:
+ if (!mach_get_rtc_pll || mach_get_rtc_pll(&pll))
+ return -EINVAL;
+ return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
+
+ case RTC_PLL_SET:
+ if (!mach_set_rtc_pll)
+ return -EINVAL;
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+ if (copy_from_user(&pll, argp, sizeof(pll)))
+ return -EFAULT;
+ return mach_set_rtc_pll(&pll);
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static const struct rtc_class_ops generic_rtc_ops = {
+ .ioctl = rtc_ioctl,
+ .read_time = rtc_generic_get_time,
+ .set_time = rtc_generic_set_time,
+};
static int __init rtc_init(void)
{
@@ -95,7 +137,9 @@ static int __init rtc_init(void)
if (!mach_hwclk)
return -ENODEV;
- pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+ pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+ &generic_rtc_ops,
+ sizeof(generic_rtc_ops));
return PTR_ERR_OR_ZERO(pdev);
}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 689b47d292ac..2f33a33001e5 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -10,6 +10,7 @@
* Miscellaneous linux stuff
*/
+#include <linux/errno.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/mm.h>
@@ -25,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/adb.h>
#include <linux/cuda.h>
+#include <linux/rtc.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
@@ -34,7 +36,6 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/macintosh.h>
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index 707b61aea203..0fb54a90eac2 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -18,7 +18,6 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/rtc.h>
#include <asm/segment.h>
#include <asm/setup.h>
#include <asm/macintosh.h>
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index e6a3b56c6481..c11d38dfad08 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -32,7 +32,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/mvme147hw.h>
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index a53803cc66cd..58e240939d26 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -35,7 +35,6 @@
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/traps.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/mvme16xhw.h>
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index e90fe903613e..fcb7f05b60b6 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -12,6 +12,7 @@
* for more details.
*/
+#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -27,7 +28,6 @@
#include <linux/platform_device.h>
#include <asm/io.h>
-#include <asm/rtc.h>
#include <asm/bootinfo.h>
#include <asm/pgtable.h>
#include <asm/setup.h>
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 71884bf01d72..3af34fa3a344 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -26,7 +26,6 @@
#include <asm/pgalloc.h>
#include <asm/sun3-head.h>
#include <asm/sun3mmu.h>
-#include <asm/rtc.h>
#include <asm/machdep.h>
#include <asm/machines.h>
#include <asm/idprom.h>
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index 889829e11f1d..2cd0bcbe6f30 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -14,8 +14,8 @@
#include <linux/rtc.h>
#include <asm/errno.h>
-#include <asm/rtc.h>
#include <asm/intersil.h>
+#include <asm/machdep.h>
/* bits to set for start/run of the intersil */
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index c8eb08add6b0..431d3c4306dd 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -15,10 +15,10 @@
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/machdep.h>
#include <asm/traps.h>
#include <asm/sun3x.h>
#include <asm/sun3ints.h>
-#include <asm/rtc.h>
#include "time.h"
diff --git a/arch/metag/include/asm/cmpxchg_lnkget.h b/arch/metag/include/asm/cmpxchg_lnkget.h
index 0154e2807ebb..2369ad394876 100644
--- a/arch/metag/include/asm/cmpxchg_lnkget.h
+++ b/arch/metag/include/asm/cmpxchg_lnkget.h
@@ -73,7 +73,7 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
" DCACHE [%2], %0\n"
#endif
"2:\n"
- : "=&d" (temp), "=&da" (retval)
+ : "=&d" (temp), "=&d" (retval)
: "da" (m), "bd" (old), "da" (new)
: "cc"
);
diff --git a/arch/metag/include/asm/metag_mem.h b/arch/metag/include/asm/metag_mem.h
index aa5a076df439..7848bc6d3b61 100644
--- a/arch/metag/include/asm/metag_mem.h
+++ b/arch/metag/include/asm/metag_mem.h
@@ -881,7 +881,7 @@
#define PERFCTRL_DCSTALL 11 /* Dcache+TLB o/p delayed (per-thread) */
#define PERFCTRL_ICSTALL 12 /* Icache+TLB o/p delayed (per-thread) */
-#define PERFCTRL_INT 13 /* Internal core delailed events (see next) */
+#define PERFCTRL_INT 13 /* Internal core detailed events (see next) */
#define PERFCTRL_EXT 15 /* External source in core periphery */
#endif /* METAC_2_1 */
diff --git a/arch/metag/include/asm/metag_regs.h b/arch/metag/include/asm/metag_regs.h
index 40c3f679c5b8..60b750971d8a 100644
--- a/arch/metag/include/asm/metag_regs.h
+++ b/arch/metag/include/asm/metag_regs.h
@@ -179,7 +179,7 @@
; is best to dump these registers immediately at the start of a routine
; using a MSETL or SETL instruction-
;
-; MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2; Only dump argments expected
+; MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2; Only dump arguments expected
;or SETL [A0StP+#8++],D0Ar2 ; Up to two 32-bit args expected
;
; For non-leaf routines it is always necessary to save and restore at least
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c
index 04b7d4f8429a..db944c2e7d88 100644
--- a/arch/metag/kernel/cachepart.c
+++ b/arch/metag/kernel/cachepart.c
@@ -15,7 +15,7 @@
#define SYSC_DCPART(n) (SYSC_DCPART0 + SYSC_xCPARTn_STRIDE * (n))
#define SYSC_ICPART(n) (SYSC_ICPART0 + SYSC_xCPARTn_STRIDE * (n))
-#define CACHE_ASSOCIATIVITY 4 /* 4 way set-assosiative */
+#define CACHE_ASSOCIATIVITY 4 /* 4 way set-associative */
#define ICACHE 0
#define DCACHE 1
diff --git a/arch/metag/kernel/dma.c b/arch/metag/kernel/dma.c
index e12368d02155..0db31e24c541 100644
--- a/arch/metag/kernel/dma.c
+++ b/arch/metag/kernel/dma.c
@@ -172,7 +172,7 @@ out:
* virtual and bus address for that space.
*/
static void *metag_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *handle, gfp_t gfp, unsigned long attrs)
{
struct page *page;
struct metag_vm_region *c;
@@ -268,7 +268,7 @@ no_page:
* free a page as defined by the above mapping.
*/
static void metag_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
struct metag_vm_region *c;
unsigned long flags, addr;
@@ -331,13 +331,13 @@ no_area:
static int metag_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long flags, user_size, kern_size;
struct metag_vm_region *c;
int ret = -ENXIO;
- if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+ if (attrs & DMA_ATTR_WRITE_COMBINE)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
else
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -482,7 +482,7 @@ static void dma_sync_for_cpu(void *vaddr, size_t size, int dma_direction)
static dma_addr_t metag_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
dma_sync_for_device((void *)(page_to_phys(page) + offset), size,
direction);
@@ -491,14 +491,14 @@ static dma_addr_t metag_dma_map_page(struct device *dev, struct page *page,
static void metag_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
}
static int metag_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -516,7 +516,7 @@ static int metag_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static void metag_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nhwentries, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
diff --git a/arch/metag/lib/divsi3.S b/arch/metag/lib/divsi3.S
index 7c8a8ae9a0a1..11124cc93dee 100644
--- a/arch/metag/lib/divsi3.S
+++ b/arch/metag/lib/divsi3.S
@@ -50,7 +50,7 @@ $LIDMCQuick:
ADDCC D0Re0,D0Re0,#1 ! If yes result += 1
SUBCC D1Ar1,D1Ar1,D1Re0 ! and A -= Bu
ORS D0Ar4,D0Ar4,D0Ar4 ! Return neg result?
- NEG D0Ar2,D0Re0 ! Calulate neg result
+ NEG D0Ar2,D0Re0 ! Calculate neg result
MOVMI D0Re0,D0Ar2 ! Yes: Take neg result
$LIDMCRet:
MOV PC,D1RtP
@@ -94,7 +94,7 @@ $LIDMCLoop:
LSR D1Re0, D1Re0, #1 ! Shift down B
BNZ $LIDMCLoop ! Was single bit in curbit lost?
ORS D0Ar4,D0Ar4,D0Ar4 ! Return neg result?
- NEG D0Ar2,D0Re0 ! Calulate neg result
+ NEG D0Ar2,D0Re0 ! Calculate neg result
MOVMI D0Re0,D0Ar2 ! Yes: Take neg result
MOV PC,D1RtP
.size ___divsi3,.-___divsi3
diff --git a/arch/metag/mm/fault.c b/arch/metag/mm/fault.c
index 372783a67dda..c765b3621b9b 100644
--- a/arch/metag/mm/fault.c
+++ b/arch/metag/mm/fault.c
@@ -187,7 +187,7 @@ bad_area_nosemaphore:
if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
printk_ratelimit()) {
- pr_info("%s%s[%d]: segfault at %lx pc %08x sp %08x write %d trap %#x (%s)",
+ printk("%s%s[%d]: segfault at %lx pc %08x sp %08x write %d trap %#x (%s)",
task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
tsk->comm, task_pid_nr(tsk), address,
regs->ctx.CurrPC, regs->ctx.AX[0].U0,
diff --git a/arch/metag/mm/init.c b/arch/metag/mm/init.c
index 11fa51c89617..c0ec116b3993 100644
--- a/arch/metag/mm/init.c
+++ b/arch/metag/mm/init.c
@@ -390,7 +390,6 @@ void __init mem_init(void)
free_all_bootmem();
mem_init_print_info(NULL);
- show_mem(0);
}
void free_initmem(void)
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
index 1884783d15c0..1768d4bdc8d3 100644
--- a/arch/microblaze/include/asm/dma-mapping.h
+++ b/arch/microblaze/include/asm/dma-mapping.h
@@ -25,7 +25,6 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-debug.h>
-#include <linux/dma-attrs.h>
#include <asm/io.h>
#include <asm/cacheflush.h>
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index bf4dec229437..ec04dc1e2527 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -17,7 +17,7 @@
static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef NOT_COHERENT_CACHE
return consistent_alloc(flag, size, dma_handle);
@@ -42,7 +42,7 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
static void dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef NOT_COHERENT_CACHE
consistent_free(size, vaddr);
@@ -53,7 +53,7 @@ static void dma_direct_free_coherent(struct device *dev, size_t size,
static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -78,7 +78,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
unsigned long offset,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
__dma_sync(page_to_phys(page) + offset, size, direction);
return page_to_phys(page) + offset;
@@ -88,7 +88,7 @@ static inline void dma_direct_unmap_page(struct device *dev,
dma_addr_t dma_address,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
/* There is not necessary to do cache cleanup
*
@@ -157,7 +157,7 @@ dma_direct_sync_sg_for_device(struct device *dev,
static
int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t handle, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef CONFIG_MMU
unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 29867139851e..26388562e300 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -64,6 +64,7 @@ config MIPS
select GENERIC_TIME_VSYSCALL
select ARCH_CLOCKSOURCE_DATA
select HANDLE_DOMAIN_IRQ
+ select HAVE_EXIT_THREAD
menu "Machine selection"
@@ -384,7 +385,7 @@ config MACH_PISTACHIO
select CLKSRC_MIPS_GIC
select COMMON_CLK
select CSRC_R4K
- select DMA_MAYBE_COHERENT
+ select DMA_NONCOHERENT
select GPIOLIB
select IRQ_MIPS_CPU
select LIBFDT
@@ -880,7 +881,6 @@ config CAVIUM_OCTEON_SOC
select SYS_SUPPORTS_HOTPLUG_CPU if CPU_BIG_ENDIAN
select SYS_HAS_EARLY_PRINTK
select SYS_HAS_CPU_CAVIUM_OCTEON
- select SWAP_IO_SPACE
select HW_HAS_PCI
select ZONE_DMA32
select HOLES_IN_ZONE
@@ -1111,16 +1111,6 @@ config NEED_DMA_MAP_STATE
config SYS_HAS_EARLY_PRINTK
bool
-config HOTPLUG_CPU
- bool "Support for hot-pluggable CPUs"
- depends on SMP && SYS_SUPPORTS_HOTPLUG_CPU
- help
- Say Y here to allow turning CPUs off and on. CPUs can be
- controlled through /sys/devices/system/cpu.
- (Note: power management support will enable this option
- automatically on SMP systems. )
- Say N if you want to disable CPU hotplug.
-
config SYS_SUPPORTS_HOTPLUG_CPU
bool
@@ -1406,7 +1396,6 @@ config CPU_LOONGSON1B
bool "Loongson 1B"
depends on SYS_HAS_CPU_LOONGSON1B
select CPU_LOONGSON1
- select ARCH_WANT_OPTIONAL_GPIOLIB
select LEDS_GPIO_REGISTER
help
The Loongson 1B is a 32-bit SoC, which implements the MIPS32
@@ -2636,6 +2625,16 @@ config SMP
If you don't know what to do here, say N.
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs"
+ depends on SMP && SYS_SUPPORTS_HOTPLUG_CPU
+ help
+ Say Y here to allow turning CPUs off and on. CPUs can be
+ controlled through /sys/devices/system/cpu.
+ (Note: power management support will enable this option
+ automatically on SMP systems. )
+ Say N if you want to disable CPU hotplug.
+
config SMP_UP
bool
@@ -2887,10 +2886,10 @@ choice
the documented boot protocol using a device tree.
config MIPS_RAW_APPENDED_DTB
- bool "vmlinux.bin"
+ bool "vmlinux.bin or vmlinuz.bin"
help
With this option, the boot code will look for a device tree binary
- DTB) appended to raw vmlinux.bin (without decompressor).
+ DTB) appended to raw vmlinux.bin or vmlinuz.bin.
(e.g. cat vmlinux.bin <filename>.dtb > vmlinux_w_dtb).
This is meant as a backward compatibility convenience for those
@@ -2902,24 +2901,6 @@ choice
look like a DTB header after a reboot if no actual DTB is appended
to vmlinux.bin. Do not leave this option active in a production kernel
if you don't intend to always append a DTB.
-
- config MIPS_ZBOOT_APPENDED_DTB
- bool "vmlinuz.bin"
- depends on SYS_SUPPORTS_ZBOOT
- help
- With this option, the boot code will look for a device tree binary
- DTB) appended to raw vmlinuz.bin (with decompressor).
- (e.g. cat vmlinuz.bin <filename>.dtb > vmlinuz_w_dtb).
-
- This is meant as a backward compatibility convenience for those
- systems with a bootloader that can't be upgraded to accommodate
- the documented boot protocol using a device tree.
-
- Beware that there is very little in terms of protection against
- this option being confused by leftover garbage in memory that might
- look like a DTB header after a reboot if no actual DTB is appended
- to vmlinuz.bin. Do not leave this option active in a production kernel
- if you don't intend to always append a DTB.
endchoice
choice
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 3a0019deb7f7..f206dafbb0a3 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -203,8 +203,8 @@ void __init plat_mem_setup(void)
fdt_start = fw_getenvl("fdt_start");
if (fdt_start)
__dt_setup_arch((void *)KSEG0ADDR(fdt_start));
- else if (fw_arg0 == -2)
- __dt_setup_arch((void *)KSEG0ADDR(fw_arg1));
+ else if (fw_passed_dtb)
+ __dt_setup_arch((void *)KSEG0ADDR(fw_passed_dtb));
if (mips_machtype != ATH79_MACH_GENERIC_OF) {
ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
diff --git a/arch/mips/bmips/setup.c b/arch/mips/bmips/setup.c
index f146d1219bde..6776042679dd 100644
--- a/arch/mips/bmips/setup.c
+++ b/arch/mips/bmips/setup.c
@@ -162,8 +162,8 @@ void __init plat_mem_setup(void)
/* intended to somewhat resemble ARM; see Documentation/arm/Booting */
if (fw_arg0 == 0 && fw_arg1 == 0xffffffff)
dtb = phys_to_virt(fw_arg2);
- else if (fw_arg0 == -2) /* UHI interface */
- dtb = (void *)fw_arg1;
+ else if (fw_passed_dtb) /* UHI interface */
+ dtb = (void *)fw_passed_dtb;
else if (__dtb_start != __dtb_end)
dtb = (void *)__dtb_start;
else
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index 080cd53bac36..fdf99e9dd4c3 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/libfdt.h>
#include <asm/addrspace.h>
@@ -36,6 +37,8 @@ extern void puthex(unsigned long long val);
#define puthex(val) do {} while (0)
#endif
+extern char __appended_dtb[];
+
void error(char *x)
{
puts("\n\n");
@@ -114,6 +117,20 @@ void decompress_kernel(unsigned long boot_heap_start)
__decompress((char *)zimage_start, zimage_size, 0, 0,
(void *)VMLINUX_LOAD_ADDRESS_ULL, 0, 0, error);
+ if (IS_ENABLED(CONFIG_MIPS_RAW_APPENDED_DTB) &&
+ fdt_magic((void *)&__appended_dtb) == FDT_MAGIC) {
+ unsigned int image_size, dtb_size;
+
+ dtb_size = fdt_totalsize((void *)&__appended_dtb);
+
+ /* last four bytes is always image size in little endian */
+ image_size = le32_to_cpup((void *)&__image_end - 4);
+
+ /* copy dtb to where the booted kernel will expect it */
+ memcpy((void *)VMLINUX_LOAD_ADDRESS_ULL + image_size,
+ __appended_dtb, dtb_size);
+ }
+
/* FIXME: should we flush cache here? */
puts("Now, booting the kernel...\n");
}
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
index c580e853b9fb..409cb483a9ff 100644
--- a/arch/mips/boot/compressed/head.S
+++ b/arch/mips/boot/compressed/head.S
@@ -25,22 +25,6 @@ start:
move s2, a2
move s3, a3
-#ifdef CONFIG_MIPS_ZBOOT_APPENDED_DTB
- PTR_LA t0, __appended_dtb
-#ifdef CONFIG_CPU_BIG_ENDIAN
- li t1, 0xd00dfeed
-#else
- li t1, 0xedfe0dd0
-#endif
- lw t2, (t0)
- bne t1, t2, not_found
- nop
-
- move s1, t0
- PTR_LI s0, -2
-not_found:
-#endif
-
/* Clear BSS */
PTR_LA a0, _edata
PTR_LA a2, _end
diff --git a/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts b/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts
index d6bc994f736f..b134798a0fd7 100644
--- a/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts
+++ b/arch/mips/boot/dts/cavium-octeon/dlink_dsr-1000n.dts
@@ -9,6 +9,7 @@
*/
/include/ "octeon_3xxx.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "dlink,dsr-1000n";
@@ -63,12 +64,27 @@
usb1 {
label = "usb1";
- gpios = <&gpio 9 1>; /* Active low */
+ gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
};
usb2 {
label = "usb2";
- gpios = <&gpio 10 1>; /* Active low */
+ gpios = <&gpio 10 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+ };
+
+ wireless1 {
+ label = "5g";
+ gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
+ };
+
+ wireless2 {
+ label = "2.4g";
+ gpios = <&gpio 18 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts
index de61f02d3ef6..ca6b4467bcd3 100644
--- a/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts
+++ b/arch/mips/boot/dts/cavium-octeon/octeon_3xxx.dts
@@ -388,16 +388,4 @@
usbn = &usbn;
led0 = &led0;
};
-
- dsr1000n-leds {
- compatible = "gpio-leds";
- usb1 {
- label = "usb1";
- gpios = <&gpio 9 1>; /* Active low */
- };
- usb2 {
- label = "usb2";
- gpios = <&gpio 10 1>; /* Active low */
- };
- };
};
diff --git a/arch/mips/boot/tools/relocs_64.c b/arch/mips/boot/tools/relocs_64.c
index b671b5e2dcd8..06066e6ac2f9 100644
--- a/arch/mips/boot/tools/relocs_64.c
+++ b/arch/mips/boot/tools/relocs_64.c
@@ -9,17 +9,20 @@
typedef uint8_t Elf64_Byte;
-typedef struct {
- Elf64_Word r_sym; /* Symbol index. */
- Elf64_Byte r_ssym; /* Special symbol. */
- Elf64_Byte r_type3; /* Third relocation. */
- Elf64_Byte r_type2; /* Second relocation. */
- Elf64_Byte r_type; /* First relocation. */
+typedef union {
+ struct {
+ Elf64_Word r_sym; /* Symbol index. */
+ Elf64_Byte r_ssym; /* Special symbol. */
+ Elf64_Byte r_type3; /* Third relocation. */
+ Elf64_Byte r_type2; /* Second relocation. */
+ Elf64_Byte r_type; /* First relocation. */
+ } fields;
+ Elf64_Xword unused;
} Elf64_Mips_Rela;
#define ELF_CLASS ELFCLASS64
-#define ELF_R_SYM(val) (((Elf64_Mips_Rela *)(&val))->r_sym)
-#define ELF_R_TYPE(val) (((Elf64_Mips_Rela *)(&val))->r_type)
+#define ELF_R_SYM(val) (((Elf64_Mips_Rela *)(&val))->fields.r_sym)
+#define ELF_R_TYPE(val) (((Elf64_Mips_Rela *)(&val))->fields.r_type)
#define ELF_ST_TYPE(o) ELF64_ST_TYPE(o)
#define ELF_ST_BIND(o) ELF64_ST_BIND(o)
#define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o)
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index 2cd45f5f9481..fd69528b24fb 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -125,7 +125,7 @@ static phys_addr_t octeon_small_dma_to_phys(struct device *dev,
static dma_addr_t octeon_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
direction, attrs);
@@ -135,7 +135,7 @@ static dma_addr_t octeon_dma_map_page(struct device *dev, struct page *page,
}
static int octeon_dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction direction, unsigned long attrs)
{
int r = swiotlb_map_sg_attrs(dev, sg, nents, direction, attrs);
mb();
@@ -157,7 +157,7 @@ static void octeon_dma_sync_sg_for_device(struct device *dev,
}
static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -189,7 +189,7 @@ static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
}
static void octeon_dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
+ void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
index 504ed61a47cd..b65a6c1ac016 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -668,7 +668,7 @@ int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
/*
* Round size up to mult of minimum alignment bytes We need
* the actual size allocated to allow for blocks to be
- * coallesced when they are freed. The alloc routine does the
+ * coalesced when they are freed. The alloc routine does the
* same rounding up on all allocations.
*/
size = ALIGN(size, CVMX_BOOTMEM_ALIGNMENT_SIZE);
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index 36e30d65ba05..ff49fc04500c 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -186,15 +186,6 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return 7 - ipd_port;
else
return -1;
- case CVMX_BOARD_TYPE_CUST_DSR1000N:
- /*
- * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1)
- * connect to a switch (BCM53115).
- */
- if (ipd_port == 2)
- return 8;
- else
- return -1;
case CVMX_BOARD_TYPE_KONTRON_S1901:
if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT)
return 1;
@@ -289,18 +280,6 @@ cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port)
return result;
}
break;
- case CVMX_BOARD_TYPE_CUST_DSR1000N:
- if (ipd_port == 0 || ipd_port == 1) {
- /* Ports 0 and 1 connect to a switch (BCM53115). */
- result.s.link_up = 1;
- result.s.full_duplex = 1;
- result.s.speed = 1000;
- return result;
- } else {
- /* Port 2 uses a Broadcom PHY (B5081). */
- is_broadcom_phy = 1;
- }
- break;
}
phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
@@ -765,7 +744,6 @@ enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(vo
case CVMX_BOARD_TYPE_LANAI2_G:
case CVMX_BOARD_TYPE_NIC10E_66:
case CVMX_BOARD_TYPE_UBNT_E100:
- case CVMX_BOARD_TYPE_CUST_DSR1000N:
return USB_CLOCK_TYPE_CRYSTAL_12;
case CVMX_BOARD_TYPE_NIC10E:
return USB_CLOCK_TYPE_REF_12;
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 368eb490354c..5a9b87b7993e 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -1260,7 +1260,7 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
line = (hw + gpiod->base_hwirq) >> 6;
bit = (hw + gpiod->base_hwirq) & 63;
- if (line > ARRAY_SIZE(octeon_irq_ciu_to_irq) ||
+ if (line >= ARRAY_SIZE(octeon_irq_ciu_to_irq) ||
octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
@@ -1542,10 +1542,6 @@ static int __init octeon_irq_init_ciu(
goto err;
}
- r = octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
- if (r)
- goto err;
-
r = octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_TWSI2, 0, 59);
if (r)
goto err;
@@ -1559,10 +1555,6 @@ static int __init octeon_irq_init_ciu(
goto err;
}
- r = octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
- if (r)
- goto err;
-
/* Enable the CIU lines */
set_c0_status(STATUSF_IP3 | STATUSF_IP2);
if (octeon_irq_use_ip4)
@@ -2077,10 +2069,6 @@ static int __init octeon_irq_init_ciu2(
goto err;
}
- r = octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 3, 44);
- if (r)
- goto err;
-
for (i = 0; i < 4; i++) {
r = octeon_irq_force_ciu_mapping(
ciu_domain, i + OCTEON_IRQ_PCI_INT0, 4, i);
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 7aeafedff94e..b31fbc9d6eae 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -3,33 +3,27 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2004-2011 Cavium Networks
+ * Copyright (C) 2004-2016 Cavium Networks
* Copyright (C) 2008 Wind River Systems
*/
-#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/i2c.h>
-#include <linux/usb.h>
-#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include <linux/etherdevice.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
+#include <linux/usb/ehci_def.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
#include <asm/octeon/octeon.h>
-#include <asm/octeon/cvmx-rnm-defs.h>
-#include <asm/octeon/cvmx-helper.h>
#include <asm/octeon/cvmx-helper-board.h>
#include <asm/octeon/cvmx-uctlx-defs.h>
+#define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull))
+#define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull))
+
/* Octeon Random Number Generator. */
static int __init octeon_rng_device_init(void)
{
@@ -78,12 +72,36 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
static int octeon2_usb_clock_start_cnt;
+static int __init octeon2_usb_reset(void)
+{
+ union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
+ u32 ucmd;
+
+ if (!OCTEON_IS_OCTEON2())
+ return 0;
+
+ clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
+ if (clk_rst_ctl.s.hrst) {
+ ucmd = cvmx_read64_uint32(CVMX_UAHCX_EHCI_USBCMD);
+ ucmd &= ~CMD_RUN;
+ cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
+ mdelay(2);
+ ucmd |= CMD_RESET;
+ cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
+ ucmd = cvmx_read64_uint32(CVMX_UAHCX_OHCI_USBCMD);
+ ucmd |= CMD_RUN;
+ cvmx_write64_uint32(CVMX_UAHCX_OHCI_USBCMD, ucmd);
+ }
+
+ return 0;
+}
+arch_initcall(octeon2_usb_reset);
+
static void octeon2_usb_clocks_start(struct device *dev)
{
u64 div;
union cvmx_uctlx_if_ena if_ena;
union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
- union cvmx_uctlx_uphy_ctl_status uphy_ctl_status;
union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
int i;
unsigned long io_clk_64_to_ns;
@@ -131,6 +149,17 @@ static void octeon2_usb_clocks_start(struct device *dev)
if_ena.s.en = 1;
cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
+ for (i = 0; i <= 1; i++) {
+ port_ctl_status.u64 =
+ cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
+ /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
+ port_ctl_status.s.txvreftune = 15;
+ port_ctl_status.s.txrisetune = 1;
+ port_ctl_status.s.txpreemphasistune = 1;
+ cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
+ port_ctl_status.u64);
+ }
+
/* Step 3: Configure the reference clock, PHY, and HCLK */
clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
@@ -218,29 +247,10 @@ static void octeon2_usb_clocks_start(struct device *dev)
clk_rst_ctl.s.p_por = 0;
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
- /* Step 5: Wait 1 ms for the PHY clock to start. */
- mdelay(1);
+ /* Step 5: Wait 3 ms for the PHY clock to start. */
+ mdelay(3);
- /*
- * Step 6: Program the reset input from automatic test
- * equipment field in the UPHY CSR
- */
- uphy_ctl_status.u64 = cvmx_read_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0));
- uphy_ctl_status.s.ate_reset = 1;
- cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
-
- /* Step 7: Wait for at least 10ns. */
- ndelay(10);
-
- /* Step 8: Clear the ATE_RESET field in the UPHY CSR. */
- uphy_ctl_status.s.ate_reset = 0;
- cvmx_write_csr(CVMX_UCTLX_UPHY_CTL_STATUS(0), uphy_ctl_status.u64);
-
- /*
- * Step 9: Wait for at least 20ns for UPHY to output PHY clock
- * signals and OHCI_CLK48
- */
- ndelay(20);
+ /* Steps 6..9 for ATE only, are skipped. */
/* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
/* 10a */
@@ -261,6 +271,20 @@ static void octeon2_usb_clocks_start(struct device *dev)
clk_rst_ctl.s.p_prst = 1;
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+ /* Step 11b */
+ udelay(1);
+
+ /* Step 11c */
+ clk_rst_ctl.s.p_prst = 0;
+ cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+
+ /* Step 11d */
+ mdelay(1);
+
+ /* Step 11e */
+ clk_rst_ctl.s.p_prst = 1;
+ cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
+
/* Step 12: Wait 1 uS. */
udelay(1);
@@ -269,21 +293,9 @@ static void octeon2_usb_clocks_start(struct device *dev)
cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
end_clock:
- /* Now we can set some other registers. */
-
- for (i = 0; i <= 1; i++) {
- port_ctl_status.u64 =
- cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
- /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
- port_ctl_status.s.txvreftune = 15;
- port_ctl_status.s.txrisetune = 1;
- port_ctl_status.s.txpreemphasistune = 1;
- cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
- port_ctl_status.u64);
- }
-
/* Set uSOF cycle period to 60,000 bits. */
cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
+
exit:
mutex_unlock(&octeon2_usb_clocks_mutex);
}
@@ -311,7 +323,11 @@ static struct usb_ehci_pdata octeon_ehci_pdata = {
#ifdef __BIG_ENDIAN
.big_endian_mmio = 1,
#endif
- .dma_mask_64 = 1,
+ /*
+ * We can DMA from anywhere. But the descriptors must be in
+ * the lower 4GB.
+ */
+ .dma_mask_64 = 0,
.power_on = octeon_ehci_power_on,
.power_off = octeon_ehci_power_off,
};
@@ -689,6 +705,10 @@ int __init octeon_prune_device_tree(void)
if (fdt_check_header(initial_boot_params))
panic("Corrupt Device Tree.");
+ WARN(octeon_bootinfo->board_type == CVMX_BOARD_TYPE_CUST_DSR1000N,
+ "Built-in DTB booting is deprecated on %s. Please switch to use appended DTB.",
+ cvmx_board_type_to_string(octeon_bootinfo->board_type));
+
aliases = fdt_path_offset(initial_boot_params, "/aliases");
if (aliases < 0) {
pr_err("Error: No /aliases node in device tree.");
@@ -1032,13 +1052,6 @@ end_led:
}
}
- if (octeon_bootinfo->board_type != CVMX_BOARD_TYPE_CUST_DSR1000N) {
- int dsr1000n_leds = fdt_path_offset(initial_boot_params,
- "/dsr1000n-leds");
- if (dsr1000n_leds >= 0)
- fdt_nop_node(initial_boot_params, dsr1000n_leds);
- }
-
return 0;
}
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 64f852b063a8..cb16fcc5f8f0 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -40,9 +40,27 @@
#include <asm/octeon/octeon.h>
#include <asm/octeon/pci-octeon.h>
-#include <asm/octeon/cvmx-mio-defs.h>
#include <asm/octeon/cvmx-rst-defs.h>
+/*
+ * TRUE for devices having registers with little-endian byte
+ * order, FALSE for registers with native-endian byte order.
+ * PCI mandates little-endian, USB and SATA are configuraable,
+ * but we chose little-endian for these.
+ */
+const bool octeon_should_swizzle_table[256] = {
+ [0x00] = true, /* bootbus/CF */
+ [0x1b] = true, /* PCI mmio window */
+ [0x1c] = true, /* PCI mmio window */
+ [0x1d] = true, /* PCI mmio window */
+ [0x1e] = true, /* PCI mmio window */
+ [0x68] = true, /* OCTEON III USB */
+ [0x69] = true, /* OCTEON III USB */
+ [0x6c] = true, /* OCTEON III SATA */
+ [0x6f] = true, /* OCTEON II USB */
+};
+EXPORT_SYMBOL(octeon_should_swizzle_table);
+
#ifdef CONFIG_PCI
extern void pci_console_init(const char *arg);
#endif
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 33aab89259f3..4d457d602d3b 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -271,6 +271,7 @@ static int octeon_cpu_disable(void)
return -ENOTSUPP;
set_cpu_online(cpu, false);
+ calculate_cpu_foreign_map();
cpumask_clear_cpu(cpu, &cpu_callin_map);
octeon_fixup_irqs();
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index 9a8c2fe8d334..c136a18c7221 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -42,8 +42,8 @@ const char *get_system_type(void)
/*
* Cobalt doesn't have PS/2 keyboard/mouse interfaces,
- * keyboard conntroller is never used.
- * Also PCI-ISA bridge DMA contoroller is never used.
+ * keyboard controller is never used.
+ * Also PCI-ISA bridge DMA controller is never used.
*/
static struct resource cobalt_reserved_resources[] = {
{ /* dma1 */
diff --git a/arch/mips/configs/ath25_defconfig b/arch/mips/configs/ath25_defconfig
new file mode 100644
index 000000000000..2c829950be17
--- /dev/null
+++ b/arch/mips/configs/ath25_defconfig
@@ -0,0 +1,119 @@
+CONFIG_ATH25=y
+# CONFIG_COMPACTION is not set
+CONFIG_HZ_100=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_FHANDLE is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_AIO is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_IPV6 is not set
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_DEBUGFS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_MTD=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_NETDEVICES=y
+# CONFIG_ETHERNET is not set
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+CONFIG_ATH5K=m
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+CONFIG_INPUT=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_PCI is not set
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_VGA_ARB is not set
+CONFIG_USB=m
+CONFIG_USB_EHCI_HCD=m
+CONFIG_LEDS_CLASS=y
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+# CONFIG_JFFS2_FS_POSIX_ACL is not set
+# CONFIG_JFFS2_FS_SECURITY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+# CONFIG_JFFS2_ZLIB is not set
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
diff --git a/arch/mips/configs/cavium_octeon_defconfig b/arch/mips/configs/cavium_octeon_defconfig
index dcac308cec39..d470d08362c0 100644
--- a/arch/mips/configs/cavium_octeon_defconfig
+++ b/arch/mips/configs/cavium_octeon_defconfig
@@ -59,6 +59,8 @@ CONFIG_EEPROM_AT25=y
CONFIG_BLK_DEV_SD=y
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_OCTEON=y
CONFIG_PATA_OCTEON_CF=y
CONFIG_SATA_SIL=y
CONFIG_NETDEVICES=y
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 9f67033961a6..ee9f5f2d18fc 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -127,6 +127,10 @@ extern char arcs_cmdline[COMMAND_LINE_SIZE];
*/
extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+#ifdef CONFIG_USE_OF
+extern unsigned long fw_passed_dtb;
+#endif
+
/*
* Platform memory detection hook called by setup_arch
*/
diff --git a/arch/mips/include/asm/dsemul.h b/arch/mips/include/asm/dsemul.h
new file mode 100644
index 000000000000..a6e067801f23
--- /dev/null
+++ b/arch/mips/include/asm/dsemul.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.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 __MIPS_ASM_DSEMUL_H__
+#define __MIPS_ASM_DSEMUL_H__
+
+#include <asm/break.h>
+#include <asm/inst.h>
+
+/* Break instruction with special math emu break code set */
+#define BREAK_MATH(micromips) (((micromips) ? 0x7 : 0xd) | (BRK_MEMU << 16))
+
+/* When used as a frame index, indicates the lack of a frame */
+#define BD_EMUFRAME_NONE ((int)BIT(31))
+
+struct mm_struct;
+struct pt_regs;
+struct task_struct;
+
+/**
+ * mips_dsemul() - 'Emulate' an instruction from a branch delay slot
+ * @regs: User thread register context.
+ * @ir: The instruction to be 'emulated'.
+ * @branch_pc: The PC of the branch instruction.
+ * @cont_pc: The PC to continue at following 'emulation'.
+ *
+ * Emulate or execute an arbitrary MIPS instruction within the context of
+ * the current user thread. This is used primarily to handle instructions
+ * in the delay slots of emulated branch instructions, for example FP
+ * branch instructions on systems without an FPU.
+ *
+ * Return: Zero on success, negative if ir is a NOP, signal number on failure.
+ */
+extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
+ unsigned long branch_pc, unsigned long cont_pc);
+
+/**
+ * do_dsemulret() - Return from a delay slot 'emulation' frame
+ * @xcp: User thread register context.
+ *
+ * Call in response to the BRK_MEMU break instruction used to return to
+ * the kernel from branch delay slot 'emulation' frames following a call
+ * to mips_dsemul(). Restores the user thread PC to the value that was
+ * passed as the cpc parameter to mips_dsemul().
+ *
+ * Return: True if an emulation frame was returned from, else false.
+ */
+extern bool do_dsemulret(struct pt_regs *xcp);
+
+/**
+ * dsemul_thread_cleanup() - Cleanup thread 'emulation' frame
+ * @tsk: The task structure associated with the thread
+ *
+ * If the thread @tsk has a branch delay slot 'emulation' frame
+ * allocated to it then free that frame.
+ *
+ * Return: True if a frame was freed, else false.
+ */
+extern bool dsemul_thread_cleanup(struct task_struct *tsk);
+
+/**
+ * dsemul_thread_rollback() - Rollback from an 'emulation' frame
+ * @regs: User thread register context.
+ *
+ * If the current thread, whose register context is represented by @regs,
+ * is executing within a delay slot 'emulation' frame then exit that
+ * frame. The PC will be rolled back to the branch if the instruction
+ * that was being 'emulated' has not yet executed, or advanced to the
+ * continuation PC if it has.
+ *
+ * Return: True if a frame was exited, else false.
+ */
+extern bool dsemul_thread_rollback(struct pt_regs *regs);
+
+/**
+ * dsemul_mm_cleanup() - Cleanup per-mm delay slot 'emulation' state
+ * @mm: The struct mm_struct to cleanup state for.
+ *
+ * Cleanup state for the given @mm, ensuring that any memory allocated
+ * for delay slot 'emulation' book-keeping is freed. This is to be called
+ * before @mm is freed in order to avoid memory leaks.
+ */
+extern void dsemul_mm_cleanup(struct mm_struct *mm);
+
+#endif /* __MIPS_ASM_DSEMUL_H__ */
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index f5f45717968e..2b3dc2973670 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -458,6 +458,7 @@ extern const char *__elf_platform;
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif
+/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
#define ARCH_DLINFO \
do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, \
@@ -498,4 +499,7 @@ extern int arch_check_elf(void *ehdr, bool has_interpreter, void *interp_ehdr,
extern void mips_set_personality_nan(struct arch_elf_state *state);
extern void mips_set_personality_fp(struct arch_elf_state *state);
+#define elf_read_implies_exec(ex, stk) mips_elf_read_implies_exec(&(ex), stk)
+extern int mips_elf_read_implies_exec(void *elf_ex, int exstack);
+
#endif /* _ASM_ELF_H */
diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h
index 3225c3c0724b..355dc25172e7 100644
--- a/arch/mips/include/asm/fpu_emulator.h
+++ b/arch/mips/include/asm/fpu_emulator.h
@@ -24,7 +24,7 @@
#define _ASM_FPU_EMULATOR_H
#include <linux/sched.h>
-#include <asm/break.h>
+#include <asm/dsemul.h>
#include <asm/thread_info.h>
#include <asm/inst.h>
#include <asm/local.h>
@@ -60,27 +60,16 @@ do { \
#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)
#endif /* CONFIG_DEBUG_FS */
-extern int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
- unsigned long cpc);
-extern int do_dsemulret(struct pt_regs *xcp);
extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
struct mips_fpu_struct *ctx, int has_fpu,
void *__user *fault_addr);
int process_fpemu_return(int sig, void __user *fault_addr,
unsigned long fcr31);
+int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
+ unsigned long *contpc);
int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
unsigned long *contpc);
-/*
- * Instruction inserted following the badinst to further tag the sequence
- */
-#define BD_COOKIE 0x0000bd36 /* tne $0, $0 with baggage */
-
-/*
- * Break instruction with special math emu break code set
- */
-#define BREAK_MATH(micromips) (((micromips) ? 0x7 : 0xd) | (BRK_MEMU << 16))
-
#define SIGNALLING_NAN 0x7ff800007ff80000LL
static inline void fpu_emulator_init_fpu(void)
diff --git a/arch/mips/include/asm/mach-cavium-octeon/irq.h b/arch/mips/include/asm/mach-cavium-octeon/irq.h
index cceae32a0732..64b86b9d30fe 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/irq.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/irq.h
@@ -42,8 +42,6 @@ enum octeon_irq {
OCTEON_IRQ_TIMER1,
OCTEON_IRQ_TIMER2,
OCTEON_IRQ_TIMER3,
- OCTEON_IRQ_USB0,
- OCTEON_IRQ_USB1,
#ifndef CONFIG_PCI_MSI
OCTEON_IRQ_LAST = 127
#endif
diff --git a/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h b/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h
index 374eefafb320..0cf5ac1f7245 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/mangle-port.h
@@ -12,6 +12,14 @@
#ifdef __BIG_ENDIAN
+static inline bool __should_swizzle_bits(volatile void *a)
+{
+ extern const bool octeon_should_swizzle_table[];
+
+ unsigned long did = ((unsigned long)a >> 40) & 0xff;
+ return octeon_should_swizzle_table[did];
+}
+
# define __swizzle_addr_b(port) (port)
# define __swizzle_addr_w(port) (port)
# define __swizzle_addr_l(port) (port)
@@ -19,6 +27,8 @@
#else /* __LITTLE_ENDIAN */
+#define __should_swizzle_bits(a) false
+
static inline bool __should_swizzle_addr(unsigned long p)
{
/* boot bus? */
@@ -35,40 +45,14 @@ static inline bool __should_swizzle_addr(unsigned long p)
#endif /* __BIG_ENDIAN */
-/*
- * Sane hardware offers swapping of PCI/ISA I/O space accesses in hardware;
- * less sane hardware forces software to fiddle with this...
- *
- * Regardless, if the host bus endianness mismatches that of PCI/ISA, then
- * you can't have the numerical value of data and byte addresses within
- * multibyte quantities both preserved at the same time. Hence two
- * variations of functions: non-prefixed ones that preserve the value
- * and prefixed ones that preserve byte addresses. The latters are
- * typically used for moving raw data between a peripheral and memory (cf.
- * string I/O functions), hence the "__mem_" prefix.
- */
-#if defined(CONFIG_SWAP_IO_SPACE)
# define ioswabb(a, x) (x)
# define __mem_ioswabb(a, x) (x)
-# define ioswabw(a, x) le16_to_cpu(x)
+# define ioswabw(a, x) (__should_swizzle_bits(a) ? le16_to_cpu(x) : x)
# define __mem_ioswabw(a, x) (x)
-# define ioswabl(a, x) le32_to_cpu(x)
+# define ioswabl(a, x) (__should_swizzle_bits(a) ? le32_to_cpu(x) : x)
# define __mem_ioswabl(a, x) (x)
-# define ioswabq(a, x) le64_to_cpu(x)
+# define ioswabq(a, x) (__should_swizzle_bits(a) ? le64_to_cpu(x) : x)
# define __mem_ioswabq(a, x) (x)
-#else
-
-# define ioswabb(a, x) (x)
-# define __mem_ioswabb(a, x) (x)
-# define ioswabw(a, x) (x)
-# define __mem_ioswabw(a, x) cpu_to_le16(x)
-# define ioswabl(a, x) (x)
-# define __mem_ioswabl(a, x) cpu_to_le32(x)
-# define ioswabq(a, x) (x)
-# define __mem_ioswabq(a, x) cpu_to_le32(x)
-
-#endif
-
#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */
diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
index 9411a4c0bdad..58e7874e9347 100644
--- a/arch/mips/include/asm/mips-cm.h
+++ b/arch/mips/include/asm/mips-cm.h
@@ -462,7 +462,7 @@ static inline unsigned int mips_cm_max_vp_width(void)
if (mips_cm_revision() >= CM_REV_CM3)
return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK;
- if (config_enabled(CONFIG_SMP))
+ if (IS_ENABLED(CONFIG_SMP))
return smp_num_siblings;
return 1;
diff --git a/arch/mips/include/asm/mmu.h b/arch/mips/include/asm/mmu.h
index 1afa1f986df8..f6ba08d77931 100644
--- a/arch/mips/include/asm/mmu.h
+++ b/arch/mips/include/asm/mmu.h
@@ -2,11 +2,20 @@
#define __ASM_MMU_H
#include <linux/atomic.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
typedef struct {
unsigned long asid[NR_CPUS];
void *vdso;
atomic_t fp_mode_switching;
+
+ /* lock to be held whilst modifying fp_bd_emupage_allocmap */
+ spinlock_t bd_emupage_lock;
+ /* bitmap tracking allocation of fp_bd_emupage */
+ unsigned long *bd_emupage_allocmap;
+ /* wait queue for threads requiring an emuframe */
+ wait_queue_head_t bd_emupage_queue;
} mm_context_t;
#endif /* __ASM_MMU_H */
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index fc57e135cb0a..ddd57ade1aa8 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -16,6 +16,7 @@
#include <linux/smp.h>
#include <linux/slab.h>
#include <asm/cacheflush.h>
+#include <asm/dsemul.h>
#include <asm/hazards.h>
#include <asm/tlbflush.h>
#include <asm-generic/mm_hooks.h>
@@ -128,6 +129,10 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
atomic_set(&mm->context.fp_mode_switching, 0);
+ mm->context.bd_emupage_allocmap = NULL;
+ spin_lock_init(&mm->context.bd_emupage_lock);
+ init_waitqueue_head(&mm->context.bd_emupage_queue);
+
return 0;
}
@@ -162,6 +167,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
*/
static inline void destroy_context(struct mm_struct *mm)
{
+ dsemul_mm_cleanup(mm);
}
#define deactivate_mm(tsk, mm) do { } while (0)
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index ddf496cb2a2a..8967b475ab10 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -168,6 +168,7 @@ static inline unsigned int read_msa_##name(void) \
unsigned int reg; \
__asm__ __volatile__( \
" .set push\n" \
+ " .set fp=64\n" \
" .set msa\n" \
" cfcmsa %0, $" #cs "\n" \
" .set pop\n" \
@@ -179,6 +180,7 @@ static inline void write_msa_##name(unsigned int val) \
{ \
__asm__ __volatile__( \
" .set push\n" \
+ " .set fp=64\n" \
" .set msa\n" \
" ctcmsa $" #cs ", %0\n" \
" .set pop\n" \
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 21ed7150fec3..ea0cd9773914 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -162,16 +162,34 @@ typedef struct { unsigned long pgprot; } pgprot_t;
/*
* __pa()/__va() should be used only during mem init.
*/
-#ifdef CONFIG_64BIT
-#define __pa(x) \
-({ \
- unsigned long __x = (unsigned long)(x); \
- __x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \
-})
-#else
-#define __pa(x) \
- ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
-#endif
+static inline unsigned long ___pa(unsigned long x)
+{
+ if (config_enabled(CONFIG_64BIT)) {
+ /*
+ * For MIPS64 the virtual address may either be in one of
+ * the compatibility segements ckseg0 or ckseg1, or it may
+ * be in xkphys.
+ */
+ return x < CKSEG0 ? XPHYSADDR(x) : CPHYSADDR(x);
+ }
+
+ if (!config_enabled(CONFIG_EVA)) {
+ /*
+ * We're using the standard MIPS32 legacy memory map, ie.
+ * the address x is going to be in kseg0 or kseg1. We can
+ * handle either case by masking out the desired bits using
+ * CPHYSADDR.
+ */
+ return CPHYSADDR(x);
+ }
+
+ /*
+ * EVA is in use so the memory map could be anything, making it not
+ * safe to just mask out bits.
+ */
+ return x - PAGE_OFFSET + PHYS_OFFSET;
+}
+#define __pa(x) ___pa((unsigned long)(x))
#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
#include <asm/io.h>
@@ -229,8 +247,10 @@ extern int __virt_addr_valid(const volatile void *kaddr);
#define virt_addr_valid(kaddr) \
__virt_addr_valid((const volatile void *) (kaddr))
-#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+#define VM_DATA_DEFAULT_FLAGS \
+ (VM_READ | VM_WRITE | \
+ ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 7d44e888134f..70128d3f770a 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -159,7 +159,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
* it better already be global)
*/
if (pte_none(*buddy)) {
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
buddy->pte_low |= _PAGE_GLOBAL;
buddy->pte_high |= _PAGE_GLOBAL;
}
@@ -172,7 +172,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
htw_stop();
/* Preserve global status for the pair */
- if (config_enabled(CONFIG_XPA)) {
+ if (IS_ENABLED(CONFIG_XPA)) {
if (ptep_buddy(ptep)->pte_high & _PAGE_GLOBAL)
null.pte_high = _PAGE_GLOBAL;
} else {
@@ -319,7 +319,7 @@ static inline int pte_young(pte_t pte) { return pte.pte_low & _PAGE_ACCESSED; }
static inline pte_t pte_wrprotect(pte_t pte)
{
pte.pte_low &= ~_PAGE_WRITE;
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low &= ~_PAGE_SILENT_WRITE;
pte.pte_high &= ~_PAGE_SILENT_WRITE;
return pte;
@@ -328,7 +328,7 @@ static inline pte_t pte_wrprotect(pte_t pte)
static inline pte_t pte_mkclean(pte_t pte)
{
pte.pte_low &= ~_PAGE_MODIFIED;
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low &= ~_PAGE_SILENT_WRITE;
pte.pte_high &= ~_PAGE_SILENT_WRITE;
return pte;
@@ -337,7 +337,7 @@ static inline pte_t pte_mkclean(pte_t pte)
static inline pte_t pte_mkold(pte_t pte)
{
pte.pte_low &= ~_PAGE_ACCESSED;
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low &= ~_PAGE_SILENT_READ;
pte.pte_high &= ~_PAGE_SILENT_READ;
return pte;
@@ -347,7 +347,7 @@ static inline pte_t pte_mkwrite(pte_t pte)
{
pte.pte_low |= _PAGE_WRITE;
if (pte.pte_low & _PAGE_MODIFIED) {
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low |= _PAGE_SILENT_WRITE;
pte.pte_high |= _PAGE_SILENT_WRITE;
}
@@ -358,7 +358,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
{
pte.pte_low |= _PAGE_MODIFIED;
if (pte.pte_low & _PAGE_WRITE) {
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low |= _PAGE_SILENT_WRITE;
pte.pte_high |= _PAGE_SILENT_WRITE;
}
@@ -369,7 +369,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
{
pte.pte_low |= _PAGE_ACCESSED;
if (!(pte.pte_low & _PAGE_NO_READ)) {
- if (!config_enabled(CONFIG_XPA))
+ if (!IS_ENABLED(CONFIG_XPA))
pte.pte_low |= _PAGE_SILENT_READ;
pte.pte_high |= _PAGE_SILENT_READ;
}
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 7e78b6208d7d..0d36c87acbe2 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -11,12 +11,14 @@
#ifndef _ASM_PROCESSOR_H
#define _ASM_PROCESSOR_H
+#include <linux/atomic.h>
#include <linux/cpumask.h>
#include <linux/threads.h>
#include <asm/cachectl.h>
#include <asm/cpu.h>
#include <asm/cpu-info.h>
+#include <asm/dsemul.h>
#include <asm/mipsregs.h>
#include <asm/prefetch.h>
@@ -78,7 +80,11 @@ extern unsigned int vced_count, vcei_count;
#endif
-#define STACK_TOP (TASK_SIZE & PAGE_MASK)
+/*
+ * One page above the stack is used for branch delay slot "emulation".
+ * See dsemul.c for details.
+ */
+#define STACK_TOP ((TASK_SIZE & PAGE_MASK) - PAGE_SIZE)
/*
* This decides where the kernel will search for a free chunk of vm
@@ -256,6 +262,12 @@ struct thread_struct {
/* Saved fpu/fpu emulator stuff. */
struct mips_fpu_struct fpu FPU_ALIGN;
+ /* Assigned branch delay slot 'emulation' frame */
+ atomic_t bd_emu_frame;
+ /* PC of the branch from a branch delay slot 'emulation' */
+ unsigned long bd_emu_branch_pc;
+ /* PC to continue from following a branch delay slot 'emulation' */
+ unsigned long bd_emu_cont_pc;
#ifdef CONFIG_MIPS_MT_FPAFF
/* Emulated instruction count */
unsigned long emulated_fp;
@@ -323,6 +335,10 @@ struct thread_struct {
* FPU affinity state (null if not FPAFF) \
*/ \
FPAFF_INIT \
+ /* Delay slot emulation */ \
+ .bd_emu_frame = ATOMIC_INIT(BD_EMUFRAME_NONE), \
+ .bd_emu_branch_pc = 0, \
+ .bd_emu_cont_pc = 0, \
/* \
* Saved DSP stuff \
*/ \
diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
index 38902bf97adc..667ca3c467b7 100644
--- a/arch/mips/include/asm/r4kcache.h
+++ b/arch/mips/include/asm/r4kcache.h
@@ -210,7 +210,11 @@ static inline void protected_writeback_dcache_line(unsigned long addr)
static inline void protected_writeback_scache_line(unsigned long addr)
{
+#ifdef CONFIG_EVA
+ protected_cachee_op(Hit_Writeback_Inv_SD, addr);
+#else
protected_cache_op(Hit_Writeback_Inv_SD, addr);
+#endif
}
/*
diff --git a/arch/mips/include/asm/seccomp.h b/arch/mips/include/asm/seccomp.h
index 684fb3a12ed3..d886d6f7687a 100644
--- a/arch/mips/include/asm/seccomp.h
+++ b/arch/mips/include/asm/seccomp.h
@@ -16,10 +16,10 @@ static inline const int *get_compat_mode1_syscalls(void)
0, /* null terminated */
};
- if (config_enabled(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))
+ if (IS_ENABLED(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))
return syscalls_O32;
- if (config_enabled(CONFIG_MIPS32_N32))
+ if (IS_ENABLED(CONFIG_MIPS32_N32))
return syscalls_N32;
BUG();
diff --git a/arch/mips/include/asm/signal.h b/arch/mips/include/asm/signal.h
index 2292373ff11a..23d6b8015c79 100644
--- a/arch/mips/include/asm/signal.h
+++ b/arch/mips/include/asm/signal.h
@@ -11,7 +11,7 @@
#include <uapi/asm/signal.h>
-#ifdef CONFIG_MIPS32_COMPAT
+#ifdef CONFIG_MIPS32_O32
extern struct mips_abi mips_abi_32;
#define sig_uses_siginfo(ka, abi) \
@@ -19,8 +19,8 @@ extern struct mips_abi mips_abi_32;
((ka)->sa.sa_flags & SA_SIGINFO))
#else
#define sig_uses_siginfo(ka, abi) \
- (config_enabled(CONFIG_64BIT) ? 1 : \
- (config_enabled(CONFIG_TRAD_SIGNALS) ? \
+ (IS_ENABLED(CONFIG_64BIT) ? 1 : \
+ (IS_ENABLED(CONFIG_TRAD_SIGNALS) ? \
((ka)->sa.sa_flags & SA_SIGINFO) : 1) )
#endif
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 03722d4326a1..8bc6c70a4030 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -23,7 +23,7 @@
extern int smp_num_siblings;
extern cpumask_t cpu_sibling_map[];
extern cpumask_t cpu_core_map[];
-extern cpumask_t cpu_foreign_map;
+extern cpumask_t cpu_foreign_map[];
#define raw_smp_processor_id() (current_thread_info()->cpu)
@@ -53,6 +53,8 @@ extern cpumask_t cpu_coherent_mask;
extern void asmlinkage smp_bootstrap(void);
+extern void calculate_cpu_foreign_map(void);
+
/*
* this function sends a 'reschedule' IPI to another CPU.
* it goes straight through and wastes no time serializing
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
index 47bc45a67e9b..d87882513ee3 100644
--- a/arch/mips/include/asm/syscall.h
+++ b/arch/mips/include/asm/syscall.h
@@ -99,7 +99,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
{
int ret;
/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
- if ((config_enabled(CONFIG_32BIT) ||
+ if ((IS_ENABLED(CONFIG_32BIT) ||
test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
(regs->regs[2] == __NR_syscall))
i++;
diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h
index 7f109d4f64a4..11b965f98d95 100644
--- a/arch/mips/include/asm/uaccess.h
+++ b/arch/mips/include/asm/uaccess.h
@@ -88,7 +88,7 @@ extern u64 __ua_limit;
*/
static inline bool eva_kernel_access(void)
{
- if (!config_enabled(CONFIG_EVA))
+ if (!IS_ENABLED(CONFIG_EVA))
return false;
return segment_eq(get_fs(), get_ds());
diff --git a/arch/mips/include/uapi/asm/auxvec.h b/arch/mips/include/uapi/asm/auxvec.h
index c9c7195272c4..45ba259a3618 100644
--- a/arch/mips/include/uapi/asm/auxvec.h
+++ b/arch/mips/include/uapi/asm/auxvec.h
@@ -14,4 +14,6 @@
/* Location of VDSO image. */
#define AT_SYSINFO_EHDR 33
+#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */
+
#endif /* __ASM_AUXVEC_H */
diff --git a/arch/mips/jz4740/setup.c b/arch/mips/jz4740/setup.c
index 0914ef775b5f..6d0152321819 100644
--- a/arch/mips/jz4740/setup.c
+++ b/arch/mips/jz4740/setup.c
@@ -75,7 +75,7 @@ void __init device_tree_init(void)
const char *get_system_type(void)
{
- if (config_enabled(CONFIG_MACH_JZ4780))
+ if (IS_ENABLED(CONFIG_MACH_JZ4780))
return "JZ4780";
return "JZ4740";
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index e6053d07072f..4a603a3ea657 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -71,7 +71,7 @@ obj-$(CONFIG_32BIT) += scall32-o32.o
obj-$(CONFIG_64BIT) += scall64-64.o
obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o
obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o
-obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o
+obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o signal_o32.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index e4c21bbf9422..804d2a2a19fe 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -276,12 +276,7 @@ int r4k_clockevent_init(void)
CLOCK_EVT_FEAT_C3STOP |
CLOCK_EVT_FEAT_PERCPU;
- clockevent_set_clock(cd, mips_hpt_frequency);
-
- /* Calculate the min / max delta */
- cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
min_delta = calculate_min_delta();
- cd->min_delta_ns = clockevent_delta2ns(min_delta, cd);
cd->rating = 300;
cd->irq = irq;
@@ -289,7 +284,7 @@ int r4k_clockevent_init(void)
cd->set_next_event = mips_next_event;
cd->event_handler = mips_event_handler;
- clockevents_register_device(cd);
+ clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff);
if (cp0_timer_irq_installed)
return 0;
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
index 6392dbe504fb..a378e44688f5 100644
--- a/arch/mips/kernel/cpu-bugs64.c
+++ b/arch/mips/kernel/cpu-bugs64.c
@@ -244,7 +244,7 @@ static inline void check_daddi(void)
panic(bug64hit, !DADDI_WAR ? daddiwar : nowar);
}
-int daddiu_bug = config_enabled(CONFIG_CPU_MIPSR6) ? 0 : -1;
+int daddiu_bug = IS_ENABLED(CONFIG_CPU_MIPSR6) ? 0 : -1;
static inline void check_daddiu(void)
{
@@ -314,7 +314,7 @@ static inline void check_daddiu(void)
void __init check_bugs64_early(void)
{
- if (!config_enabled(CONFIG_CPU_MIPSR6)) {
+ if (!IS_ENABLED(CONFIG_CPU_MIPSR6)) {
check_mult_sh();
check_daddiu();
}
@@ -322,6 +322,6 @@ void __init check_bugs64_early(void)
void __init check_bugs64(void)
{
- if (!config_enabled(CONFIG_CPU_MIPSR6))
+ if (!IS_ENABLED(CONFIG_CPU_MIPSR6))
check_daddi();
}
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index 1f910563fdf6..d76275da54cb 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -23,7 +23,7 @@ static struct clocksource clocksource_mips = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
-static u64 notrace r4k_read_sched_clock(void)
+static u64 __maybe_unused notrace r4k_read_sched_clock(void)
{
return read_c0_count();
}
@@ -82,7 +82,9 @@ int __init init_r4k_clocksource(void)
clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
+#ifndef CONFIG_CPU_FREQ
sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
+#endif
return 0;
}
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 891f5ee63983..6430bff21fff 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -8,9 +8,12 @@
* option) any later version.
*/
+#include <linux/binfmts.h>
#include <linux/elf.h>
+#include <linux/export.h>
#include <linux/sched.h>
+#include <asm/cpu-features.h>
#include <asm/cpu-info.h>
/* Whether to accept legacy-NaN and 2008-NaN user binaries. */
@@ -179,7 +182,7 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
return -ELIBBAD;
}
- if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+ if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
return 0;
fp_abi = state->fp_abi;
@@ -285,7 +288,7 @@ void mips_set_personality_fp(struct arch_elf_state *state)
* not be worried about N32/N64 binaries.
*/
- if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+ if (!IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
return;
switch (state->overall_fp_mode) {
@@ -326,3 +329,19 @@ void mips_set_personality_nan(struct arch_elf_state *state)
BUG();
}
}
+
+int mips_elf_read_implies_exec(void *elf_ex, int exstack)
+{
+ if (exstack != EXSTACK_DISABLE_X) {
+ /* The binary doesn't request a non-executable stack */
+ return 1;
+ }
+
+ if (!cpu_has_rixi) {
+ /* The CPU doesn't support non-executable memory */
+ return 1;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mips_elf_read_implies_exec);
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index 56e8fede3fd8..cf052204eb0a 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -93,21 +93,24 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
jr t0
0:
+#ifdef CONFIG_USE_OF
#ifdef CONFIG_MIPS_RAW_APPENDED_DTB
- PTR_LA t0, __appended_dtb
+ PTR_LA t2, __appended_dtb
#ifdef CONFIG_CPU_BIG_ENDIAN
li t1, 0xd00dfeed
#else
li t1, 0xedfe0dd0
#endif
- lw t2, (t0)
- bne t1, t2, not_found
- nop
+ lw t0, (t2)
+ beq t0, t1, dtb_found
+#endif
+ li t1, -2
+ beq a0, t1, dtb_found
+ move t2, a1
- move a1, t0
- PTR_LI a0, -2
-not_found:
+ li t2, 0
+dtb_found:
#endif
PTR_LA t0, __bss_start # clear .bss
LONG_S zero, (t0)
@@ -122,6 +125,10 @@ not_found:
LONG_S a2, fw_arg2
LONG_S a3, fw_arg3
+#ifdef CONFIG_USE_OF
+ LONG_S t2, fw_passed_dtb
+#endif
+
MTC0 zero, CP0_CONTEXT # clear context register
PTR_LA $28, init_thread_union
/* Set the SP after an empty pt_regs. */
diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
index 760217bbb2fa..659e6d3ae335 100644
--- a/arch/mips/kernel/mips-cm.c
+++ b/arch/mips/kernel/mips-cm.c
@@ -251,7 +251,7 @@ int mips_cm_probe(void)
mips_cm_probe_l2sync();
/* determine register width for this CM */
- mips_cm_is64 = config_enabled(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
+ mips_cm_is64 = IS_ENABLED(CONFIG_64BIT) && (mips_cm_revision() >= CM_REV_CM3);
for_each_possible_cpu(cpu)
spin_lock_init(&per_cpu(cm_core_lock, cpu));
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
index 7ff2a557f4aa..c3372cac6db2 100644
--- a/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -84,7 +84,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
(s32)MIPSInst_SIMM(ir);
return 0;
case daddiu_op:
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
break;
if (MIPSInst_RT(ir))
@@ -143,7 +143,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
(u32)regs->regs[MIPSInst_RT(ir)]);
return 0;
case dsll_op:
- if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+ if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_RS(ir))
break;
if (MIPSInst_RD(ir))
@@ -152,7 +152,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
MIPSInst_FD(ir));
return 0;
case dsrl_op:
- if (config_enabled(CONFIG_32BIT) || MIPSInst_RS(ir))
+ if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_RS(ir))
break;
if (MIPSInst_RD(ir))
@@ -161,7 +161,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
MIPSInst_FD(ir));
return 0;
case daddu_op:
- if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+ if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_FD(ir))
break;
if (MIPSInst_RD(ir))
@@ -170,7 +170,7 @@ static inline int mipsr6_emul(struct pt_regs *regs, u32 ir)
(u64)regs->regs[MIPSInst_RT(ir)];
return 0;
case dsubu_op:
- if (config_enabled(CONFIG_32BIT) || MIPSInst_FD(ir))
+ if (IS_ENABLED(CONFIG_32BIT) || MIPSInst_FD(ir))
break;
if (MIPSInst_RD(ir))
@@ -283,7 +283,7 @@ static int jr_func(struct pt_regs *regs, u32 ir)
err = mipsr6_emul(regs, nir);
if (err > 0) {
regs->cp0_epc = nepc;
- err = mips_dsemul(regs, nir, cepc);
+ err = mips_dsemul(regs, nir, epc, cepc);
if (err == SIGILL)
err = SIGEMT;
MIPS_R2_STATS(dsemul);
@@ -498,7 +498,7 @@ static int dmult_func(struct pt_regs *regs, u32 ir)
s64 res;
s64 rt, rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
rt = regs->regs[MIPSInst_RT(ir)];
@@ -530,7 +530,7 @@ static int dmultu_func(struct pt_regs *regs, u32 ir)
u64 res;
u64 rt, rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
rt = regs->regs[MIPSInst_RT(ir)];
@@ -561,7 +561,7 @@ static int ddiv_func(struct pt_regs *regs, u32 ir)
{
s64 rt, rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
rt = regs->regs[MIPSInst_RT(ir)];
@@ -586,7 +586,7 @@ static int ddivu_func(struct pt_regs *regs, u32 ir)
{
u64 rt, rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
rt = regs->regs[MIPSInst_RT(ir)];
@@ -825,7 +825,7 @@ static int dclz_func(struct pt_regs *regs, u32 ir)
u64 res;
u64 rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
if (!MIPSInst_RD(ir))
@@ -852,7 +852,7 @@ static int dclo_func(struct pt_regs *regs, u32 ir)
u64 res;
u64 rs;
- if (config_enabled(CONFIG_32BIT))
+ if (IS_ENABLED(CONFIG_32BIT))
return SIGILL;
if (!MIPSInst_RD(ir))
@@ -1033,7 +1033,7 @@ repeat:
if (nir) {
err = mipsr6_emul(regs, nir);
if (err > 0) {
- err = mips_dsemul(regs, nir, cpc);
+ err = mips_dsemul(regs, nir, epc, cpc);
if (err == SIGILL)
err = SIGEMT;
MIPS_R2_STATS(dsemul);
@@ -1082,7 +1082,7 @@ repeat:
if (nir) {
err = mipsr6_emul(regs, nir);
if (err > 0) {
- err = mips_dsemul(regs, nir, cpc);
+ err = mips_dsemul(regs, nir, epc, cpc);
if (err == SIGILL)
err = SIGEMT;
MIPS_R2_STATS(dsemul);
@@ -1149,7 +1149,7 @@ repeat:
if (nir) {
err = mipsr6_emul(regs, nir);
if (err > 0) {
- err = mips_dsemul(regs, nir, cpc);
+ err = mips_dsemul(regs, nir, epc, cpc);
if (err == SIGILL)
err = SIGEMT;
MIPS_R2_STATS(dsemul);
@@ -1484,7 +1484,7 @@ fpu_emul:
break;
case ldl_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
@@ -1603,7 +1603,7 @@ fpu_emul:
break;
case ldr_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
@@ -1722,7 +1722,7 @@ fpu_emul:
break;
case sdl_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
@@ -1840,7 +1840,7 @@ fpu_emul:
break;
case sdr_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
@@ -2072,7 +2072,7 @@ fpu_emul:
break;
case lld_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
@@ -2133,7 +2133,7 @@ fpu_emul:
break;
case scd_op:
- if (config_enabled(CONFIG_32BIT)) {
+ if (IS_ENABLED(CONFIG_32BIT)) {
err = SIGILL;
break;
}
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index adda3ffb9b78..5b31a9405ebc 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -148,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state)
}
/* Setup the VPE to run mips_cps_pm_restore when started again */
- if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ if (IS_ENABLED(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
/* Power gating relies upon CPS SMP */
if (!mips_cps_smp_in_use())
return -EINVAL;
@@ -387,7 +387,7 @@ static void * __init cps_gen_entry_code(unsigned cpu, enum cps_pm_state state)
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
- if (config_enabled(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
+ if (IS_ENABLED(CONFIG_CPU_PM) && state == CPS_PM_POWER_GATED) {
/* Power gating relies upon CPS SMP */
if (!mips_cps_smp_in_use())
goto out_err;
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 813ed7829c61..7429ad09fbe3 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -30,6 +30,7 @@
#include <asm/asm.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
+#include <asm/dsemul.h>
#include <asm/dsp.h>
#include <asm/fpu.h>
#include <asm/msa.h>
@@ -68,11 +69,22 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
lose_fpu(0);
clear_thread_flag(TIF_MSA_CTX_LIVE);
clear_used_math();
+ atomic_set(&current->thread.bd_emu_frame, BD_EMUFRAME_NONE);
init_dsp();
regs->cp0_epc = pc;
regs->regs[29] = sp;
}
+void exit_thread(struct task_struct *tsk)
+{
+ /*
+ * User threads may have allocated a delay slot emulation frame.
+ * If so, clean up that allocation.
+ */
+ if (!(current->flags & PF_KTHREAD))
+ dsemul_thread_cleanup(tsk);
+}
+
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{
/*
@@ -159,6 +171,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
clear_tsk_thread_flag(p, TIF_FPUBOUND);
#endif /* CONFIG_MIPS_MT_FPAFF */
+ atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE);
+
if (clone_flags & CLONE_SETTLS)
ti->tp_value = regs->regs[7];
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 9c0b387d6427..51d3988933f8 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -348,7 +348,7 @@ EXPORT(sysn32_call_table)
PTR sys_ni_syscall /* available, was setaltroot */
PTR sys_add_key
PTR sys_request_key
- PTR sys_keyctl /* 6245 */
+ PTR compat_sys_keyctl /* 6245 */
PTR sys_set_thread_area
PTR sys_inotify_init
PTR sys_inotify_add_watch
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index f4f28b1580de..6efa7136748f 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -504,7 +504,7 @@ EXPORT(sys32_call_table)
PTR sys_ni_syscall /* available, was setaltroot */
PTR sys_add_key /* 4280 */
PTR sys_request_key
- PTR sys_keyctl
+ PTR compat_sys_keyctl
PTR sys_set_thread_area
PTR sys_inotify_init
PTR sys_inotify_add_watch /* 4285 */
diff --git a/arch/mips/kernel/segment.c b/arch/mips/kernel/segment.c
index 87bc74a5a518..2703f218202e 100644
--- a/arch/mips/kernel/segment.c
+++ b/arch/mips/kernel/segment.c
@@ -26,17 +26,20 @@ static void build_segment_config(char *str, unsigned int cfg)
/*
* Access modes MK, MSK and MUSK are mapped segments. Therefore
- * there is no direct physical address mapping.
+ * there is no direct physical address mapping unless it becomes
+ * unmapped uncached at error level due to EU.
*/
- if ((am == 0) || (am > 3)) {
+ if ((am == 0) || (am > 3) || (cfg & MIPS_SEGCFG_EU))
str += sprintf(str, " %03lx",
((cfg & MIPS_SEGCFG_PA) >> MIPS_SEGCFG_PA_SHIFT));
+ else
+ str += sprintf(str, " UND");
+
+ if ((am == 0) || (am > 3))
str += sprintf(str, " %01ld",
((cfg & MIPS_SEGCFG_C) >> MIPS_SEGCFG_C_SHIFT));
- } else {
- str += sprintf(str, " UND");
+ else
str += sprintf(str, " U");
- }
/* Exception configuration. */
str += sprintf(str, " %01ld\n",
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index ef408a03e818..36cf8d65c47d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -875,6 +875,10 @@ void __init setup_arch(char **cmdline_p)
unsigned long kernelsp[NR_CPUS];
unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+#ifdef CONFIG_USE_OF
+unsigned long fw_passed_dtb;
+#endif
+
#ifdef CONFIG_DEBUG_FS
struct dentry *mips_debugfs_dir;
static int __init debugfs_mips(void)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index ae4231452115..9e224469c788 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -165,7 +165,7 @@ static int save_msa_extcontext(void __user *buf)
* should already have been done when handling scalar FP
* context.
*/
- BUG_ON(config_enabled(CONFIG_EVA));
+ BUG_ON(IS_ENABLED(CONFIG_EVA));
err = __put_user(read_msa_csr(), &msa->csr);
err |= _save_msa_all_upper(&msa->wr);
@@ -195,7 +195,7 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size)
unsigned int csr;
int i, err;
- if (!config_enabled(CONFIG_CPU_HAS_MSA))
+ if (!IS_ENABLED(CONFIG_CPU_HAS_MSA))
return SIGSYS;
if (size != sizeof(*msa))
@@ -215,7 +215,7 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size)
* scalar FP context, so FPU & MSA should have already been
* disabled whilst handling scalar FP context.
*/
- BUG_ON(config_enabled(CONFIG_EVA));
+ BUG_ON(IS_ENABLED(CONFIG_EVA));
write_msa_csr(csr);
err |= _restore_msa_all_upper(&msa->wr);
@@ -315,7 +315,7 @@ int protected_save_fp_context(void __user *sc)
* EVA does not have userland equivalents of ldc1 or sdc1, so
* save to the kernel FP context & copy that to userland below.
*/
- if (config_enabled(CONFIG_EVA))
+ if (IS_ENABLED(CONFIG_EVA))
lose_fpu(1);
while (1) {
@@ -378,7 +378,7 @@ int protected_restore_fp_context(void __user *sc)
* disable the FPU here such that the code below simply copies to
* the kernel FP context.
*/
- if (config_enabled(CONFIG_EVA))
+ if (IS_ENABLED(CONFIG_EVA))
lose_fpu(0);
while (1) {
@@ -772,6 +772,14 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct mips_abi *abi = current->thread.abi;
void *vdso = current->mm->context.vdso;
+ /*
+ * If we were emulating a delay slot instruction, exit that frame such
+ * that addresses in the sigframe are as expected for userland and we
+ * don't have a problem if we reuse the thread's frame for an
+ * instruction within the signal handler.
+ */
+ dsemul_thread_rollback(regs);
+
if (regs->regs[0]) {
switch(regs->regs[2]) {
case ERESTART_RESTARTBLOCK:
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 78c8349d151c..97b7c51b8251 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -6,129 +6,26 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994 - 2000, 2006 Ralf Baechle
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2016, Imagination Technologies Ltd.
*/
-#include <linux/cache.h>
-#include <linux/compat.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/suspend.h>
-#include <linux/compiler.h>
-#include <linux/uaccess.h>
-#include <asm/abi.h>
-#include <asm/asm.h>
+#include <asm/compat.h>
#include <asm/compat-signal.h>
-#include <linux/bitops.h>
-#include <asm/cacheflush.h>
-#include <asm/sim.h>
-#include <asm/ucontext.h>
-#include <asm/fpu.h>
-#include <asm/war.h>
-#include <asm/dsp.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
#include "signal-common.h"
-/*
- * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
- */
-#define __NR_O32_restart_syscall 4253
-
/* 32-bit compatibility types */
typedef unsigned int __sighandler32_t;
typedef void (*vfptr_t)(void);
-struct ucontext32 {
- u32 uc_flags;
- s32 uc_link;
- compat_stack_t uc_stack;
- struct sigcontext32 uc_mcontext;
- compat_sigset_t uc_sigmask; /* mask last for extensibility */
-};
-
-struct sigframe32 {
- u32 sf_ass[4]; /* argument save space for o32 */
- u32 sf_pad[2]; /* Was: signal trampoline */
- struct sigcontext32 sf_sc;
- compat_sigset_t sf_mask;
-};
-
-struct rt_sigframe32 {
- u32 rs_ass[4]; /* argument save space for o32 */
- u32 rs_pad[2]; /* Was: signal trampoline */
- compat_siginfo_t rs_info;
- struct ucontext32 rs_uc;
-};
-
-static int setup_sigcontext32(struct pt_regs *regs,
- struct sigcontext32 __user *sc)
-{
- int err = 0;
- int i;
-
- err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-
- err |= __put_user(0, &sc->sc_regs[0]);
- for (i = 1; i < 32; i++)
- err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
-
- err |= __put_user(regs->hi, &sc->sc_mdhi);
- err |= __put_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
- err |= __put_user(mfhi1(), &sc->sc_hi1);
- err |= __put_user(mflo1(), &sc->sc_lo1);
- err |= __put_user(mfhi2(), &sc->sc_hi2);
- err |= __put_user(mflo2(), &sc->sc_lo2);
- err |= __put_user(mfhi3(), &sc->sc_hi3);
- err |= __put_user(mflo3(), &sc->sc_lo3);
- }
-
- /*
- * Save FPU state to signal context. Signal handler
- * will "inherit" current FPU state.
- */
- err |= protected_save_fp_context(sc);
-
- return err;
-}
-
-static int restore_sigcontext32(struct pt_regs *regs,
- struct sigcontext32 __user *sc)
-{
- int err = 0;
- s32 treg;
- int i;
-
- /* Always make any pending restarted system calls return -EINTR */
- current->restart_block.fn = do_no_restart_syscall;
-
- err |= __get_user(regs->cp0_epc, &sc->sc_pc);
- err |= __get_user(regs->hi, &sc->sc_mdhi);
- err |= __get_user(regs->lo, &sc->sc_mdlo);
- if (cpu_has_dsp) {
- err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
- err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
- err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
- err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
- err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
- err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
- err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
- }
-
- for (i = 1; i < 32; i++)
- err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
-
- return err ?: protected_restore_fp_context(sc);
-}
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
@@ -247,176 +144,3 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
return 0;
}
-
-asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
-{
- struct sigframe32 __user *frame;
- sigset_t blocked;
- int sig;
-
- frame = (struct sigframe32 __user *) regs.regs[29];
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
- goto badframe;
-
- set_current_blocked(&blocked);
-
- sig = restore_sigcontext32(&regs, &frame->sf_sc);
- if (sig < 0)
- goto badframe;
- else if (sig)
- force_sig(sig, current);
-
- /*
- * Don't let your children do this ...
- */
- __asm__ __volatile__(
- "move\t$29, %0\n\t"
- "j\tsyscall_exit"
- :/* no outputs */
- :"r" (&regs));
- /* Unreached */
-
-badframe:
- force_sig(SIGSEGV, current);
-}
-
-asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
-{
- struct rt_sigframe32 __user *frame;
- sigset_t set;
- int sig;
-
- frame = (struct rt_sigframe32 __user *) regs.regs[29];
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
- goto badframe;
- if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
- goto badframe;
-
- set_current_blocked(&set);
-
- sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
- if (sig < 0)
- goto badframe;
- else if (sig)
- force_sig(sig, current);
-
- if (compat_restore_altstack(&frame->rs_uc.uc_stack))
- goto badframe;
-
- /*
- * Don't let your children do this ...
- */
- __asm__ __volatile__(
- "move\t$29, %0\n\t"
- "j\tsyscall_exit"
- :/* no outputs */
- :"r" (&regs));
- /* Unreached */
-
-badframe:
- force_sig(SIGSEGV, current);
-}
-
-static int setup_frame_32(void *sig_return, struct ksignal *ksig,
- struct pt_regs *regs, sigset_t *set)
-{
- struct sigframe32 __user *frame;
- int err = 0;
-
- frame = get_sigframe(ksig, regs, sizeof(*frame));
- if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- return -EFAULT;
-
- err |= setup_sigcontext32(regs, &frame->sf_sc);
- err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
-
- if (err)
- return -EFAULT;
-
- /*
- * Arguments to signal handler:
- *
- * a0 = signal number
- * a1 = 0 (should be cause)
- * a2 = pointer to struct sigcontext
- *
- * $25 and c0_epc point to the signal handler, $29 points to the
- * struct sigframe.
- */
- regs->regs[ 4] = ksig->sig;
- regs->regs[ 5] = 0;
- regs->regs[ 6] = (unsigned long) &frame->sf_sc;
- regs->regs[29] = (unsigned long) frame;
- regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
-
- DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
- current->comm, current->pid,
- frame, regs->cp0_epc, regs->regs[31]);
-
- return 0;
-}
-
-static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
- struct pt_regs *regs, sigset_t *set)
-{
- struct rt_sigframe32 __user *frame;
- int err = 0;
-
- frame = get_sigframe(ksig, regs, sizeof(*frame));
- if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
- return -EFAULT;
-
- /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
- err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
-
- /* Create the ucontext. */
- err |= __put_user(0, &frame->rs_uc.uc_flags);
- err |= __put_user(0, &frame->rs_uc.uc_link);
- err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
- err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
- err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
-
- if (err)
- return -EFAULT;
-
- /*
- * Arguments to signal handler:
- *
- * a0 = signal number
- * a1 = 0 (should be cause)
- * a2 = pointer to ucontext
- *
- * $25 and c0_epc point to the signal handler, $29 points to
- * the struct rt_sigframe32.
- */
- regs->regs[ 4] = ksig->sig;
- regs->regs[ 5] = (unsigned long) &frame->rs_info;
- regs->regs[ 6] = (unsigned long) &frame->rs_uc;
- regs->regs[29] = (unsigned long) frame;
- regs->regs[31] = (unsigned long) sig_return;
- regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
-
- DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
- current->comm, current->pid,
- frame, regs->cp0_epc, regs->regs[31]);
-
- return 0;
-}
-
-/*
- * o32 compatibility on 64-bit kernels, without DSP ASE
- */
-struct mips_abi mips_abi_32 = {
- .setup_frame = setup_frame_32,
- .setup_rt_frame = setup_rt_frame_32,
- .restart = __NR_O32_restart_syscall,
-
- .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
- .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
- .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
-
- .vdso = &vdso_image_o32,
-};
diff --git a/arch/mips/kernel/signal_o32.c b/arch/mips/kernel/signal_o32.c
new file mode 100644
index 000000000000..5e169fc5ca5c
--- /dev/null
+++ b/arch/mips/kernel/signal_o32.c
@@ -0,0 +1,285 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2016, Imagination Technologies Ltd.
+ */
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+
+#include <asm/abi.h>
+#include <asm/compat-signal.h>
+#include <asm/dsp.h>
+#include <asm/sim.h>
+#include <asm/unistd.h>
+
+#include "signal-common.h"
+
+/*
+ * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
+ */
+#define __NR_O32_restart_syscall 4253
+
+struct sigframe32 {
+ u32 sf_ass[4]; /* argument save space for o32 */
+ u32 sf_pad[2]; /* Was: signal trampoline */
+ struct sigcontext32 sf_sc;
+ compat_sigset_t sf_mask;
+};
+
+struct ucontext32 {
+ u32 uc_flags;
+ s32 uc_link;
+ compat_stack_t uc_stack;
+ struct sigcontext32 uc_mcontext;
+ compat_sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+struct rt_sigframe32 {
+ u32 rs_ass[4]; /* argument save space for o32 */
+ u32 rs_pad[2]; /* Was: signal trampoline */
+ compat_siginfo_t rs_info;
+ struct ucontext32 rs_uc;
+};
+
+static int setup_sigcontext32(struct pt_regs *regs,
+ struct sigcontext32 __user *sc)
+{
+ int err = 0;
+ int i;
+
+ err |= __put_user(regs->cp0_epc, &sc->sc_pc);
+
+ err |= __put_user(0, &sc->sc_regs[0]);
+ for (i = 1; i < 32; i++)
+ err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
+
+ err |= __put_user(regs->hi, &sc->sc_mdhi);
+ err |= __put_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
+ err |= __put_user(mfhi1(), &sc->sc_hi1);
+ err |= __put_user(mflo1(), &sc->sc_lo1);
+ err |= __put_user(mfhi2(), &sc->sc_hi2);
+ err |= __put_user(mflo2(), &sc->sc_lo2);
+ err |= __put_user(mfhi3(), &sc->sc_hi3);
+ err |= __put_user(mflo3(), &sc->sc_lo3);
+ }
+
+ /*
+ * Save FPU state to signal context. Signal handler
+ * will "inherit" current FPU state.
+ */
+ err |= protected_save_fp_context(sc);
+
+ return err;
+}
+
+static int restore_sigcontext32(struct pt_regs *regs,
+ struct sigcontext32 __user *sc)
+{
+ int err = 0;
+ s32 treg;
+ int i;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ err |= __get_user(regs->cp0_epc, &sc->sc_pc);
+ err |= __get_user(regs->hi, &sc->sc_mdhi);
+ err |= __get_user(regs->lo, &sc->sc_mdlo);
+ if (cpu_has_dsp) {
+ err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
+ err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
+ err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
+ err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
+ err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
+ err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
+ err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
+ }
+
+ for (i = 1; i < 32; i++)
+ err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
+
+ return err ?: protected_restore_fp_context(sc);
+}
+
+static int setup_frame_32(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
+{
+ struct sigframe32 __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ return -EFAULT;
+
+ err |= setup_sigcontext32(regs, &frame->sf_sc);
+ err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
+
+ if (err)
+ return -EFAULT;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to struct sigcontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to the
+ * struct sigframe.
+ */
+ regs->regs[ 4] = ksig->sig;
+ regs->regs[ 5] = 0;
+ regs->regs[ 6] = (unsigned long) &frame->sf_sc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) sig_return;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
+
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, regs->regs[31]);
+
+ return 0;
+}
+
+asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct rt_sigframe32 __user *frame;
+ sigset_t set;
+ int sig;
+
+ frame = (struct rt_sigframe32 __user *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
+ goto badframe;
+
+ set_current_blocked(&set);
+
+ sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
+ if (sig < 0)
+ goto badframe;
+ else if (sig)
+ force_sig(sig, current);
+
+ if (compat_restore_altstack(&frame->rs_uc.uc_stack))
+ goto badframe;
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (&regs));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
+
+static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
+ struct pt_regs *regs, sigset_t *set)
+{
+ struct rt_sigframe32 __user *frame;
+ int err = 0;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame));
+ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
+ return -EFAULT;
+
+ /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
+ err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->rs_uc.uc_flags);
+ err |= __put_user(0, &frame->rs_uc.uc_link);
+ err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
+ err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
+ err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
+
+ if (err)
+ return -EFAULT;
+
+ /*
+ * Arguments to signal handler:
+ *
+ * a0 = signal number
+ * a1 = 0 (should be cause)
+ * a2 = pointer to ucontext
+ *
+ * $25 and c0_epc point to the signal handler, $29 points to
+ * the struct rt_sigframe32.
+ */
+ regs->regs[ 4] = ksig->sig;
+ regs->regs[ 5] = (unsigned long) &frame->rs_info;
+ regs->regs[ 6] = (unsigned long) &frame->rs_uc;
+ regs->regs[29] = (unsigned long) frame;
+ regs->regs[31] = (unsigned long) sig_return;
+ regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
+
+ DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
+ current->comm, current->pid,
+ frame, regs->cp0_epc, regs->regs[31]);
+
+ return 0;
+}
+
+/*
+ * o32 compatibility on 64-bit kernels, without DSP ASE
+ */
+struct mips_abi mips_abi_32 = {
+ .setup_frame = setup_frame_32,
+ .setup_rt_frame = setup_rt_frame_32,
+ .restart = __NR_O32_restart_syscall,
+
+ .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
+ .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
+ .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
+
+ .vdso = &vdso_image_o32,
+};
+
+
+asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
+{
+ struct sigframe32 __user *frame;
+ sigset_t blocked;
+ int sig;
+
+ frame = (struct sigframe32 __user *) regs.regs[29];
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
+ goto badframe;
+
+ set_current_blocked(&blocked);
+
+ sig = restore_sigcontext32(&regs, &frame->sf_sc);
+ if (sig < 0)
+ goto badframe;
+ else if (sig)
+ force_sig(sig, current);
+
+ /*
+ * Don't let your children do this ...
+ */
+ __asm__ __volatile__(
+ "move\t$29, %0\n\t"
+ "j\tsyscall_exit"
+ :/* no outputs */
+ :"r" (&regs));
+ /* Unreached */
+
+badframe:
+ force_sig(SIGSEGV, current);
+}
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index e02addc0307f..6d0f1321e084 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -363,6 +363,7 @@ static int bmips_cpu_disable(void)
pr_info("SMP: CPU%d is offline\n", cpu);
set_cpu_online(cpu, false);
+ calculate_cpu_foreign_map();
cpumask_clear_cpu(cpu, &cpu_callin_map);
clear_c0_status(IE_IRQ5);
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 4ed36f288d64..e9d9fc6c754c 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -46,8 +46,8 @@ static unsigned core_vpe_count(unsigned core)
if (threads_disabled)
return 1;
- if ((!config_enabled(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
- && (!config_enabled(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
+ if ((!IS_ENABLED(CONFIG_MIPS_MT_SMP) || !cpu_has_mipsmt)
+ && (!IS_ENABLED(CONFIG_CPU_MIPSR6) || !cpu_has_vp))
return 1;
mips_cm_lock_other(core, 0);
@@ -206,7 +206,7 @@ err_out:
}
}
-static void boot_core(unsigned core)
+static void boot_core(unsigned int core, unsigned int vpe_id)
{
u32 access, stat, seq_state;
unsigned timeout;
@@ -233,8 +233,9 @@ static void boot_core(unsigned core)
mips_cpc_lock_other(core);
if (mips_cm_revision() >= CM_REV_CM3) {
- /* Run VP0 following the reset */
- write_cpc_co_vp_run(0x1);
+ /* Run only the requested VP following the reset */
+ write_cpc_co_vp_stop(0xf);
+ write_cpc_co_vp_run(1 << vpe_id);
/*
* Ensure that the VP_RUN register is written before the
@@ -306,7 +307,7 @@ static void cps_boot_secondary(int cpu, struct task_struct *idle)
if (!test_bit(core, core_power)) {
/* Boot a VPE on a powered down core */
- boot_core(core);
+ boot_core(core, vpe_id);
goto out;
}
@@ -397,6 +398,7 @@ static int cps_cpu_disable(void)
atomic_sub(1 << cpu_vpe_id(&current_cpu_data), &core_cfg->vpe_mask);
smp_mb__after_atomic();
set_cpu_online(cpu, false);
+ calculate_cpu_foreign_map();
cpumask_clear_cpu(cpu, &cpu_callin_map);
return 0;
@@ -411,14 +413,16 @@ static enum {
void play_dead(void)
{
- unsigned cpu, core;
+ unsigned int cpu, core, vpe_id;
local_irq_disable();
idle_task_exit();
cpu = smp_processor_id();
cpu_death = CPU_DEATH_POWER;
- if (cpu_has_mipsmt) {
+ pr_debug("CPU%d going offline\n", cpu);
+
+ if (cpu_has_mipsmt || cpu_has_vp) {
core = cpu_data[cpu].core;
/* Look for another online VPE within the core */
@@ -439,10 +443,21 @@ void play_dead(void)
complete(&cpu_death_chosen);
if (cpu_death == CPU_DEATH_HALT) {
- /* Halt this TC */
- write_c0_tchalt(TCHALT_H);
- instruction_hazard();
+ vpe_id = cpu_vpe_id(&cpu_data[cpu]);
+
+ pr_debug("Halting core %d VP%d\n", core, vpe_id);
+ if (cpu_has_mipsmt) {
+ /* Halt this TC */
+ write_c0_tchalt(TCHALT_H);
+ instruction_hazard();
+ } else if (cpu_has_vp) {
+ write_cpc_cl_vp_stop(1 << vpe_id);
+
+ /* Ensure that the VP_STOP register is written */
+ wmb();
+ }
} else {
+ pr_debug("Gating power to core %d\n", core);
/* Power down the core */
cps_pm_enter_state(CPS_PM_POWER_GATED);
}
@@ -469,6 +484,7 @@ static void wait_for_sibling_halt(void *ptr_cpu)
static void cps_cpu_die(unsigned int cpu)
{
unsigned core = cpu_data[cpu].core;
+ unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]);
unsigned stat;
int err;
@@ -497,10 +513,12 @@ static void cps_cpu_die(unsigned int cpu)
* in which case the CPC will refuse to power down the core.
*/
do {
+ mips_cm_lock_other(core, vpe_id);
mips_cpc_lock_other(core);
stat = read_cpc_co_stat_conf();
stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK;
mips_cpc_unlock_other();
+ mips_cm_unlock_other();
} while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 &&
stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 &&
stat != CPC_Cx_STAT_CONF_SEQSTATE_U2);
@@ -517,6 +535,12 @@ static void cps_cpu_die(unsigned int cpu)
(void *)(unsigned long)cpu, 1);
if (err)
panic("Failed to call remote sibling CPU\n");
+ } else if (cpu_has_vp) {
+ do {
+ mips_cm_lock_other(core, vpe_id);
+ stat = read_cpc_co_vp_running();
+ mips_cm_unlock_other();
+ } while (stat & (1 << vpe_id));
}
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index f9d01e953acb..f95f094f36e4 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(cpu_core_map);
* A logcal cpu mask containing only one VPE per core to
* reduce the number of IPIs on large MT systems.
*/
-cpumask_t cpu_foreign_map __read_mostly;
+cpumask_t cpu_foreign_map[NR_CPUS] __read_mostly;
EXPORT_SYMBOL(cpu_foreign_map);
/* representing cpus for which sibling maps can be computed */
@@ -124,7 +124,7 @@ static inline void set_cpu_core_map(int cpu)
* Calculate a new cpu_foreign_map mask whenever a
* new cpu appears or disappears.
*/
-static inline void calculate_cpu_foreign_map(void)
+void calculate_cpu_foreign_map(void)
{
int i, k, core_present;
cpumask_t temp_foreign_map;
@@ -141,7 +141,9 @@ static inline void calculate_cpu_foreign_map(void)
cpumask_set_cpu(i, &temp_foreign_map);
}
- cpumask_copy(&cpu_foreign_map, &temp_foreign_map);
+ for_each_online_cpu(i)
+ cpumask_andnot(&cpu_foreign_map[i],
+ &temp_foreign_map, &cpu_sibling_map[i]);
}
struct plat_smp_ops *mp_ops;
@@ -344,16 +346,9 @@ asmlinkage void start_secondary(void)
static void stop_this_cpu(void *dummy)
{
/*
- * Remove this CPU. Be a bit slow here and
- * set the bits for every online CPU so we don't miss
- * any IPI whilst taking this VPE down.
+ * Remove this CPU:
*/
- cpumask_copy(&cpu_foreign_map, cpu_online_mask);
-
- /* Make it visible to every other CPU */
- smp_mb();
-
set_cpu_online(smp_processor_id(), false);
calculate_cpu_foreign_map();
local_irq_disable();
@@ -512,10 +507,17 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned l
smp_on_other_tlbs(flush_tlb_range_ipi, &fd);
} else {
unsigned int cpu;
+ int exec = vma->vm_flags & VM_EXEC;
for_each_online_cpu(cpu) {
+ /*
+ * flush_cache_range() will only fully flush icache if
+ * the VMA is executable, otherwise we must invalidate
+ * ASID without it appearing to has_valid_asid() as if
+ * mm has been completely unused by that CPU.
+ */
if (cpu != smp_processor_id() && cpu_context(cpu, mm))
- cpu_context(cpu, mm) = 0;
+ cpu_context(cpu, mm) = !exec;
}
}
local_flush_tlb_range(vma, start, end);
@@ -560,8 +562,14 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
unsigned int cpu;
for_each_online_cpu(cpu) {
+ /*
+ * flush_cache_page() only does partial flushes, so
+ * invalidate ASID without it appearing to
+ * has_valid_asid() as if mm has been completely unused
+ * by that CPU.
+ */
if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm))
- cpu_context(cpu, vma->vm_mm) = 0;
+ cpu_context(cpu, vma->vm_mm) = 1;
}
}
local_flush_tlb_page(vma, page);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 6fb4704bd156..3de85be2486a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -704,6 +704,7 @@ asmlinkage void do_ov(struct pt_regs *regs)
int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
{
struct siginfo si = { 0 };
+ struct vm_area_struct *vma;
switch (sig) {
case 0:
@@ -744,7 +745,8 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
si.si_addr = fault_addr;
si.si_signo = sig;
down_read(&current->mm->mmap_sem);
- if (find_vma(current->mm, (unsigned long)fault_addr))
+ vma = find_vma(current->mm, (unsigned long)fault_addr);
+ if (vma && (vma->vm_start <= (unsigned long)fault_addr))
si.si_code = SEGV_ACCERR;
else
si.si_code = SEGV_MAPERR;
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index 28b3af73a17b..f1c308dbbc4a 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -1025,7 +1025,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
if (!access_ok(VERIFY_READ, addr, 2))
goto sigbus;
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
if (segment_eq(get_fs(), get_ds()))
LoadHW(addr, value, res);
else
@@ -1044,7 +1044,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
if (!access_ok(VERIFY_READ, addr, 4))
goto sigbus;
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
if (segment_eq(get_fs(), get_ds()))
LoadW(addr, value, res);
else
@@ -1063,7 +1063,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
if (!access_ok(VERIFY_READ, addr, 2))
goto sigbus;
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
if (segment_eq(get_fs(), get_ds()))
LoadHWU(addr, value, res);
else
@@ -1131,7 +1131,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
compute_return_epc(regs);
value = regs->regs[insn.i_format.rt];
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
if (segment_eq(get_fs(), get_ds()))
StoreHW(addr, value, res);
else
@@ -1151,7 +1151,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
compute_return_epc(regs);
value = regs->regs[insn.i_format.rt];
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
if (segment_eq(get_fs(), get_ds()))
StoreW(addr, value, res);
else
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 54e1663ce639..9abe447a4b48 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -107,6 +107,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
if (down_write_killable(&mm->mmap_sem))
return -EINTR;
+ /* Map delay slot emulation page */
+ base = mmap_region(NULL, STACK_TOP, PAGE_SIZE,
+ VM_READ|VM_WRITE|VM_EXEC|
+ VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+ 0);
+ if (IS_ERR_VALUE(base)) {
+ ret = base;
+ goto out;
+ }
+
/*
* Determine total area size. This includes the VDSO data itself, the
* data page, and the GIC user page if present. Always create a mapping
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 6eb52b9c9818..e788515f766b 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -1642,8 +1642,14 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst,
preempt_disable();
if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
- if (kvm_mips_host_tlb_lookup(vcpu, va) < 0)
- kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
+ if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 &&
+ kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) {
+ kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n",
+ __func__, va, vcpu, read_c0_entryhi());
+ er = EMULATE_FAIL;
+ preempt_enable();
+ goto done;
+ }
} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
int index;
@@ -1680,12 +1686,18 @@ enum emulation_result kvm_mips_emulate_cache(union mips_instruction inst,
run, vcpu);
preempt_enable();
goto dont_update_pc;
- } else {
- /*
- * We fault an entry from the guest tlb to the
- * shadow host TLB
- */
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb);
+ }
+ /*
+ * We fault an entry from the guest tlb to the
+ * shadow host TLB
+ */
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb)) {
+ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
+ __func__, va, index, vcpu,
+ read_c0_entryhi());
+ er = EMULATE_FAIL;
+ preempt_enable();
+ goto done;
}
}
} else {
@@ -2659,7 +2671,12 @@ enum emulation_result kvm_mips_handle_tlbmiss(u32 cause,
* OK we have a Guest TLB entry, now inject it into the
* shadow host TLB
*/
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb);
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb)) {
+ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
+ __func__, va, index, vcpu,
+ read_c0_entryhi());
+ er = EMULATE_FAIL;
+ }
}
}
diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c
index 57319ee57c4f..6cfdcf55572d 100644
--- a/arch/mips/kvm/mmu.c
+++ b/arch/mips/kvm/mmu.c
@@ -99,7 +99,7 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
}
gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
- if (gfn >= kvm->arch.guest_pmap_npages) {
+ if ((gfn | 1) >= kvm->arch.guest_pmap_npages) {
kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
gfn, badvaddr);
kvm_mips_dump_host_tlbs();
@@ -138,35 +138,49 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
struct kvm *kvm = vcpu->kvm;
kvm_pfn_t pfn0, pfn1;
+ gfn_t gfn0, gfn1;
+ long tlb_lo[2];
int ret;
- if ((tlb->tlb_hi & VPN2_MASK) == 0) {
- pfn0 = 0;
- pfn1 = 0;
- } else {
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo[0])
- >> PAGE_SHIFT) < 0)
- return -1;
-
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo[1])
- >> PAGE_SHIFT) < 0)
- return -1;
-
- pfn0 = kvm->arch.guest_pmap[
- mips3_tlbpfn_to_paddr(tlb->tlb_lo[0]) >> PAGE_SHIFT];
- pfn1 = kvm->arch.guest_pmap[
- mips3_tlbpfn_to_paddr(tlb->tlb_lo[1]) >> PAGE_SHIFT];
+ tlb_lo[0] = tlb->tlb_lo[0];
+ tlb_lo[1] = tlb->tlb_lo[1];
+
+ /*
+ * The commpage address must not be mapped to anything else if the guest
+ * TLB contains entries nearby, or commpage accesses will break.
+ */
+ if (!((tlb->tlb_hi ^ KVM_GUEST_COMMPAGE_ADDR) &
+ VPN2_MASK & (PAGE_MASK << 1)))
+ tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0;
+
+ gfn0 = mips3_tlbpfn_to_paddr(tlb_lo[0]) >> PAGE_SHIFT;
+ gfn1 = mips3_tlbpfn_to_paddr(tlb_lo[1]) >> PAGE_SHIFT;
+ if (gfn0 >= kvm->arch.guest_pmap_npages ||
+ gfn1 >= kvm->arch.guest_pmap_npages) {
+ kvm_err("%s: Invalid gfn: [%#llx, %#llx], EHi: %#lx\n",
+ __func__, gfn0, gfn1, tlb->tlb_hi);
+ kvm_mips_dump_guest_tlbs(vcpu);
+ return -1;
}
+ if (kvm_mips_map_page(kvm, gfn0) < 0)
+ return -1;
+
+ if (kvm_mips_map_page(kvm, gfn1) < 0)
+ return -1;
+
+ pfn0 = kvm->arch.guest_pmap[gfn0];
+ pfn1 = kvm->arch.guest_pmap[gfn1];
+
/* Get attributes from the Guest TLB */
entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) |
((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) |
- (tlb->tlb_lo[0] & ENTRYLO_D) |
- (tlb->tlb_lo[0] & ENTRYLO_V);
+ (tlb_lo[0] & ENTRYLO_D) |
+ (tlb_lo[0] & ENTRYLO_V);
entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) |
((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) |
- (tlb->tlb_lo[1] & ENTRYLO_D) |
- (tlb->tlb_lo[1] & ENTRYLO_V);
+ (tlb_lo[1] & ENTRYLO_D) |
+ (tlb_lo[1] & ENTRYLO_V);
kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
tlb->tlb_lo[0], tlb->tlb_lo[1]);
@@ -354,9 +368,15 @@ u32 kvm_get_inst(u32 *opc, struct kvm_vcpu *vcpu)
local_irq_restore(flags);
return KVM_INVALID_INST;
}
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
- &vcpu->arch.
- guest_tlb[index]);
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
+ &vcpu->arch.guest_tlb[index])) {
+ kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n",
+ __func__, opc, index, vcpu,
+ read_c0_entryhi());
+ kvm_mips_dump_guest_tlbs(vcpu);
+ local_irq_restore(flags);
+ return KVM_INVALID_INST;
+ }
inst = *(opc);
}
local_irq_restore(flags);
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index ff17669e30a3..8ac0e5994ed2 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -66,7 +66,7 @@ int gic_present;
#endif
static int exin_avail;
-static struct resource ltq_eiu_irq[MAX_EIU];
+static u32 ltq_eiu_irq[MAX_EIU];
static void __iomem *ltq_icu_membase[MAX_IM];
static void __iomem *ltq_eiu_membase;
static struct irq_domain *ltq_domain;
@@ -75,7 +75,7 @@ static int ltq_perfcount_irq;
int ltq_eiu_get_irq(int exin)
{
if (exin < exin_avail)
- return ltq_eiu_irq[exin].start;
+ return ltq_eiu_irq[exin];
return -1;
}
@@ -125,8 +125,8 @@ static int ltq_eiu_settype(struct irq_data *d, unsigned int type)
{
int i;
- for (i = 0; i < MAX_EIU; i++) {
- if (d->hwirq == ltq_eiu_irq[i].start) {
+ for (i = 0; i < exin_avail; i++) {
+ if (d->hwirq == ltq_eiu_irq[i]) {
int val = 0;
int edge = 0;
@@ -173,8 +173,8 @@ static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
int i;
ltq_enable_irq(d);
- for (i = 0; i < MAX_EIU; i++) {
- if (d->hwirq == ltq_eiu_irq[i].start) {
+ for (i = 0; i < exin_avail; i++) {
+ if (d->hwirq == ltq_eiu_irq[i]) {
/* by default we are low level triggered */
ltq_eiu_settype(d, IRQF_TRIGGER_LOW);
/* clear all pending */
@@ -195,8 +195,8 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)
int i;
ltq_disable_irq(d);
- for (i = 0; i < MAX_EIU; i++) {
- if (d->hwirq == ltq_eiu_irq[i].start) {
+ for (i = 0; i < exin_avail; i++) {
+ if (d->hwirq == ltq_eiu_irq[i]) {
/* disable */
ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~BIT(i),
LTQ_EIU_EXIN_INEN);
@@ -206,7 +206,7 @@ static void ltq_shutdown_eiu_irq(struct irq_data *d)
}
static struct irq_chip ltq_irq_type = {
- "icu",
+ .name = "icu",
.irq_enable = ltq_enable_irq,
.irq_disable = ltq_disable_irq,
.irq_unmask = ltq_enable_irq,
@@ -216,7 +216,7 @@ static struct irq_chip ltq_irq_type = {
};
static struct irq_chip ltq_eiu_type = {
- "eiu",
+ .name = "eiu",
.irq_startup = ltq_startup_eiu_irq,
.irq_shutdown = ltq_shutdown_eiu_irq,
.irq_enable = ltq_enable_irq,
@@ -341,10 +341,10 @@ static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
return 0;
for (i = 0; i < exin_avail; i++)
- if (hw == ltq_eiu_irq[i].start)
+ if (hw == ltq_eiu_irq[i])
chip = &ltq_eiu_type;
- irq_set_chip_and_handler(hw, chip, handle_level_irq);
+ irq_set_chip_and_handler(irq, chip, handle_level_irq);
return 0;
}
@@ -439,14 +439,15 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
/* find out how many external irq sources we have */
- exin_avail = of_irq_count(eiu_node);
+ exin_avail = of_property_count_u32_elems(eiu_node,
+ "lantiq,eiu-irqs");
if (exin_avail > MAX_EIU)
exin_avail = MAX_EIU;
- ret = of_irq_to_resource_table(eiu_node,
+ ret = of_property_read_u32_array(eiu_node, "lantiq,eiu-irqs",
ltq_eiu_irq, exin_avail);
- if (ret != exin_avail)
+ if (ret)
panic("failed to load external irq resources");
if (!request_mem_region(res.start, resource_size(&res),
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 5f693ac77a0d..4cbb000e778e 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -74,8 +74,8 @@ void __init plat_mem_setup(void)
set_io_port_base((unsigned long) KSEG1);
- if (fw_arg0 == -2) /* UHI interface */
- dtb = (void *)fw_arg1;
+ if (fw_passed_dtb) /* UHI interface */
+ dtb = (void *)fw_passed_dtb;
else if (__dtb_start != __dtb_end)
dtb = (void *)__dtb_start;
else
diff --git a/arch/mips/loongson64/common/dma-swiotlb.c b/arch/mips/loongson64/common/dma-swiotlb.c
index 4ffa6fc81c8f..1a80b6f73ab2 100644
--- a/arch/mips/loongson64/common/dma-swiotlb.c
+++ b/arch/mips/loongson64/common/dma-swiotlb.c
@@ -10,7 +10,7 @@
#include <dma-coherence.h>
static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -41,7 +41,7 @@ static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
}
static void loongson_dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
+ void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
@@ -49,7 +49,7 @@ static void loongson_dma_free_coherent(struct device *dev, size_t size,
static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t daddr = swiotlb_map_page(dev, page, offset, size,
dir, attrs);
@@ -59,9 +59,9 @@ static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
static int loongson_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, NULL);
+ int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, 0);
mb();
return r;
diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c
index 249039af66c4..4788bea62a6a 100644
--- a/arch/mips/loongson64/loongson-3/hpet.c
+++ b/arch/mips/loongson64/loongson-3/hpet.c
@@ -13,8 +13,8 @@
#define SMBUS_PCI_REG64 0x64
#define SMBUS_PCI_REGB4 0xb4
-#define HPET_MIN_CYCLES 64
-#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+#define HPET_MIN_CYCLES 16
+#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES * 12)
static DEFINE_SPINLOCK(hpet_lock);
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
@@ -157,14 +157,14 @@ static int hpet_tick_resume(struct clock_event_device *evt)
static int hpet_next_event(unsigned long delta,
struct clock_event_device *evt)
{
- unsigned int cnt;
- int res;
+ u32 cnt;
+ s32 res;
cnt = hpet_read(HPET_COUNTER);
- cnt += delta;
+ cnt += (u32) delta;
hpet_write(HPET_T0_CMP, cnt);
- res = (int)(cnt - hpet_read(HPET_COUNTER));
+ res = (s32)(cnt - hpet_read(HPET_COUNTER));
return res < HPET_MIN_CYCLES ? -ETIME : 0;
}
@@ -230,7 +230,7 @@ void __init setup_hpet_timer(void)
cd = &per_cpu(hpet_clockevent_device, cpu);
cd->name = "hpet";
- cd->rating = 320;
+ cd->rating = 100;
cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
cd->set_state_shutdown = hpet_set_state_shutdown;
cd->set_state_periodic = hpet_set_state_periodic;
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index e59759af63d9..2fec6f753a35 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -417,6 +417,7 @@ static int loongson3_cpu_disable(void)
return -EBUSY;
set_cpu_online(cpu, false);
+ calculate_cpu_foreign_map();
cpumask_clear_cpu(cpu, &cpu_callin_map);
local_irq_save(flags);
fixup_irqs();
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 6dc07fba187f..36775d20b0e7 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -434,8 +434,8 @@ static int microMIPS32_to_MIPS32(union mips_instruction *insn_ptr)
* a single subroutine should be used across both
* modules.
*/
-static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
- unsigned long *contpc)
+int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
+ unsigned long *contpc)
{
union mips_instruction insn = (union mips_instruction)dec_insn.insn;
unsigned int fcr31;
@@ -784,10 +784,10 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
*/
static inline int cop1_64bit(struct pt_regs *xcp)
{
- if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32))
+ if (IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_MIPS32_O32))
return 1;
- else if (config_enabled(CONFIG_32BIT) &&
- !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
+ else if (IS_ENABLED(CONFIG_32BIT) &&
+ !IS_ENABLED(CONFIG_MIPS_O32_FP64_SUPPORT))
return 0;
return !test_thread_flag(TIF_32BIT_FPREGS);
@@ -1268,7 +1268,7 @@ branch_common:
* instruction in the dslot.
*/
sig = mips_dsemul(xcp, ir,
- contpc);
+ bcpc, contpc);
if (sig < 0)
break;
if (sig)
@@ -1323,7 +1323,7 @@ branch_common:
* Single step the non-cp1
* instruction in the dslot
*/
- sig = mips_dsemul(xcp, ir, contpc);
+ sig = mips_dsemul(xcp, ir, bcpc, contpc);
if (sig < 0)
break;
if (sig)
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 47074887e64c..72a4642eee2c 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -1,3 +1,6 @@
+#include <linux/err.h>
+#include <linux/slab.h>
+
#include <asm/branch.h>
#include <asm/cacheflush.h>
#include <asm/fpu_emulator.h>
@@ -5,43 +8,211 @@
#include <asm/mipsregs.h>
#include <asm/uaccess.h>
-#include "ieee754.h"
-
-/*
- * Emulate the arbitrary instruction ir at xcp->cp0_epc. Required when
- * we have to emulate the instruction in a COP1 branch delay slot. Do
- * not change cp0_epc due to the instruction
+/**
+ * struct emuframe - The 'emulation' frame structure
+ * @emul: The instruction to 'emulate'.
+ * @badinst: A break instruction to cause a return to the kernel.
*
- * According to the spec:
- * 1) it shouldn't be a branch :-)
- * 2) it can be a COP instruction :-(
- * 3) if we are tring to run a protected memory space we must take
- * special care on memory access instructions :-(
- */
-
-/*
- * "Trampoline" return routine to catch exception following
- * execution of delay-slot instruction execution.
+ * This structure defines the frames placed within the delay slot emulation
+ * page in response to a call to mips_dsemul(). Each thread may be allocated
+ * only one frame at any given time. The kernel stores within it the
+ * instruction to be 'emulated' followed by a break instruction, then
+ * executes the frame in user mode. The break causes a trap to the kernel
+ * which leads to do_dsemulret() being called unless the instruction in
+ * @emul causes a trap itself, is a branch, or a signal is delivered to
+ * the thread. In these cases the allocated frame will either be reused by
+ * a subsequent delay slot 'emulation', or be freed during signal delivery or
+ * upon thread exit.
+ *
+ * This approach is used because:
+ *
+ * - Actually emulating all instructions isn't feasible. We would need to
+ * be able to handle instructions from all revisions of the MIPS ISA,
+ * all ASEs & all vendor instruction set extensions. This would be a
+ * whole lot of work & continual maintenance burden as new instructions
+ * are introduced, and in the case of some vendor extensions may not
+ * even be possible. Thus we need to take the approach of actually
+ * executing the instruction.
+ *
+ * - We must execute the instruction within user context. If we were to
+ * execute the instruction in kernel mode then it would have access to
+ * kernel resources without very careful checks, leaving us with a
+ * high potential for security or stability issues to arise.
+ *
+ * - We used to place the frame on the users stack, but this requires
+ * that the stack be executable. This is bad for security so the
+ * per-process page is now used instead.
+ *
+ * - The instruction in @emul may be something entirely invalid for a
+ * delay slot. The user may (intentionally or otherwise) place a branch
+ * in a delay slot, or a kernel mode instruction, or something else
+ * which generates an exception. Thus we can't rely upon the break in
+ * @badinst always being hit. For this reason we track the index of the
+ * frame allocated to each thread, allowing us to clean it up at later
+ * points such as signal delivery or thread exit.
+ *
+ * - The user may generate a fake struct emuframe if they wish, invoking
+ * the BRK_MEMU break instruction themselves. We must therefore not
+ * trust that BRK_MEMU means there's actually a valid frame allocated
+ * to the thread, and must not allow the user to do anything they
+ * couldn't already.
*/
-
struct emuframe {
mips_instruction emul;
mips_instruction badinst;
- mips_instruction cookie;
- unsigned long epc;
};
-/*
- * Set up an emulation frame for instruction IR, from a delay slot of
- * a branch jumping to CPC. Return 0 if successful, -1 if no emulation
- * required, otherwise a signal number causing a frame setup failure.
- */
-int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
+static const int emupage_frame_count = PAGE_SIZE / sizeof(struct emuframe);
+
+static inline __user struct emuframe *dsemul_page(void)
+{
+ return (__user struct emuframe *)STACK_TOP;
+}
+
+static int alloc_emuframe(void)
+{
+ mm_context_t *mm_ctx = &current->mm->context;
+ int idx;
+
+retry:
+ spin_lock(&mm_ctx->bd_emupage_lock);
+
+ /* Ensure we have an allocation bitmap */
+ if (!mm_ctx->bd_emupage_allocmap) {
+ mm_ctx->bd_emupage_allocmap =
+ kcalloc(BITS_TO_LONGS(emupage_frame_count),
+ sizeof(unsigned long),
+ GFP_ATOMIC);
+
+ if (!mm_ctx->bd_emupage_allocmap) {
+ idx = BD_EMUFRAME_NONE;
+ goto out_unlock;
+ }
+ }
+
+ /* Attempt to allocate a single bit/frame */
+ idx = bitmap_find_free_region(mm_ctx->bd_emupage_allocmap,
+ emupage_frame_count, 0);
+ if (idx < 0) {
+ /*
+ * Failed to allocate a frame. We'll wait until one becomes
+ * available. We unlock the page so that other threads actually
+ * get the opportunity to free their frames, which means
+ * technically the result of bitmap_full may be incorrect.
+ * However the worst case is that we repeat all this and end up
+ * back here again.
+ */
+ spin_unlock(&mm_ctx->bd_emupage_lock);
+ if (!wait_event_killable(mm_ctx->bd_emupage_queue,
+ !bitmap_full(mm_ctx->bd_emupage_allocmap,
+ emupage_frame_count)))
+ goto retry;
+
+ /* Received a fatal signal - just give in */
+ return BD_EMUFRAME_NONE;
+ }
+
+ /* Success! */
+ pr_debug("allocate emuframe %d to %d\n", idx, current->pid);
+out_unlock:
+ spin_unlock(&mm_ctx->bd_emupage_lock);
+ return idx;
+}
+
+static void free_emuframe(int idx, struct mm_struct *mm)
+{
+ mm_context_t *mm_ctx = &mm->context;
+
+ spin_lock(&mm_ctx->bd_emupage_lock);
+
+ pr_debug("free emuframe %d from %d\n", idx, current->pid);
+ bitmap_clear(mm_ctx->bd_emupage_allocmap, idx, 1);
+
+ /* If some thread is waiting for a frame, now's its chance */
+ wake_up(&mm_ctx->bd_emupage_queue);
+
+ spin_unlock(&mm_ctx->bd_emupage_lock);
+}
+
+static bool within_emuframe(struct pt_regs *regs)
+{
+ unsigned long base = (unsigned long)dsemul_page();
+
+ if (regs->cp0_epc < base)
+ return false;
+ if (regs->cp0_epc >= (base + PAGE_SIZE))
+ return false;
+
+ return true;
+}
+
+bool dsemul_thread_cleanup(struct task_struct *tsk)
+{
+ int fr_idx;
+
+ /* Clear any allocated frame, retrieving its index */
+ fr_idx = atomic_xchg(&tsk->thread.bd_emu_frame, BD_EMUFRAME_NONE);
+
+ /* If no frame was allocated, we're done */
+ if (fr_idx == BD_EMUFRAME_NONE)
+ return false;
+
+ task_lock(tsk);
+
+ /* Free the frame that this thread had allocated */
+ if (tsk->mm)
+ free_emuframe(fr_idx, tsk->mm);
+
+ task_unlock(tsk);
+ return true;
+}
+
+bool dsemul_thread_rollback(struct pt_regs *regs)
+{
+ struct emuframe __user *fr;
+ int fr_idx;
+
+ /* Do nothing if we're not executing from a frame */
+ if (!within_emuframe(regs))
+ return false;
+
+ /* Find the frame being executed */
+ fr_idx = atomic_read(&current->thread.bd_emu_frame);
+ if (fr_idx == BD_EMUFRAME_NONE)
+ return false;
+ fr = &dsemul_page()[fr_idx];
+
+ /*
+ * If the PC is at the emul instruction, roll back to the branch. If
+ * PC is at the badinst (break) instruction, we've already emulated the
+ * instruction so progress to the continue PC. If it's anything else
+ * then something is amiss & the user has branched into some other area
+ * of the emupage - we'll free the allocated frame anyway.
+ */
+ if (msk_isa16_mode(regs->cp0_epc) == (unsigned long)&fr->emul)
+ regs->cp0_epc = current->thread.bd_emu_branch_pc;
+ else if (msk_isa16_mode(regs->cp0_epc) == (unsigned long)&fr->badinst)
+ regs->cp0_epc = current->thread.bd_emu_cont_pc;
+
+ atomic_set(&current->thread.bd_emu_frame, BD_EMUFRAME_NONE);
+ free_emuframe(fr_idx, current->mm);
+ return true;
+}
+
+void dsemul_mm_cleanup(struct mm_struct *mm)
+{
+ mm_context_t *mm_ctx = &mm->context;
+
+ kfree(mm_ctx->bd_emupage_allocmap);
+}
+
+int mips_dsemul(struct pt_regs *regs, mips_instruction ir,
+ unsigned long branch_pc, unsigned long cont_pc)
{
int isa16 = get_isa16_mode(regs->cp0_epc);
mips_instruction break_math;
struct emuframe __user *fr;
- int err;
+ int err, fr_idx;
/* NOP is easy */
if (ir == 0)
@@ -68,30 +239,20 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
}
}
- pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
+ pr_debug("dsemul 0x%08lx cont at 0x%08lx\n", regs->cp0_epc, cont_pc);
- /*
- * The strategy is to push the instruction onto the user stack
- * and put a trap after it which we can catch and jump to
- * the required address any alternative apart from full
- * instruction emulation!!.
- *
- * Algorithmics used a system call instruction, and
- * borrowed that vector. MIPS/Linux version is a bit
- * more heavyweight in the interests of portability and
- * multiprocessor support. For Linux we use a BREAK 514
- * instruction causing a breakpoint exception.
- */
- break_math = BREAK_MATH(isa16);
-
- /* Ensure that the two instructions are in the same cache line */
- fr = (struct emuframe __user *)
- ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7);
-
- /* Verify that the stack pointer is not completely insane */
- if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
+ /* Allocate a frame if we don't already have one */
+ fr_idx = atomic_read(&current->thread.bd_emu_frame);
+ if (fr_idx == BD_EMUFRAME_NONE)
+ fr_idx = alloc_emuframe();
+ if (fr_idx == BD_EMUFRAME_NONE)
return SIGBUS;
+ fr = &dsemul_page()[fr_idx];
+
+ /* Retrieve the appropriately encoded break instruction */
+ break_math = BREAK_MATH(isa16);
+ /* Write the instructions to the frame */
if (isa16) {
err = __put_user(ir >> 16,
(u16 __user *)(&fr->emul));
@@ -106,84 +267,36 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
err |= __put_user(break_math, &fr->badinst);
}
- err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);
- err |= __put_user(cpc, &fr->epc);
-
if (unlikely(err)) {
MIPS_FPU_EMU_INC_STATS(errors);
+ free_emuframe(fr_idx, current->mm);
return SIGBUS;
}
+ /* Record the PC of the branch, PC to continue from & frame index */
+ current->thread.bd_emu_branch_pc = branch_pc;
+ current->thread.bd_emu_cont_pc = cont_pc;
+ atomic_set(&current->thread.bd_emu_frame, fr_idx);
+
+ /* Change user register context to execute the frame */
regs->cp0_epc = (unsigned long)&fr->emul | isa16;
+ /* Ensure the icache observes our newly written frame */
flush_cache_sigtramp((unsigned long)&fr->emul);
return 0;
}
-int do_dsemulret(struct pt_regs *xcp)
+bool do_dsemulret(struct pt_regs *xcp)
{
- int isa16 = get_isa16_mode(xcp->cp0_epc);
- struct emuframe __user *fr;
- unsigned long epc;
- u32 insn, cookie;
- int err = 0;
- u16 instr[2];
-
- fr = (struct emuframe __user *)
- (msk_isa16_mode(xcp->cp0_epc) - sizeof(mips_instruction));
-
- /*
- * If we can't even access the area, something is very wrong, but we'll
- * leave that to the default handling
- */
- if (!access_ok(VERIFY_READ, fr, sizeof(struct emuframe)))
- return 0;
-
- /*
- * Do some sanity checking on the stackframe:
- *
- * - Is the instruction pointed to by the EPC an BREAK_MATH?
- * - Is the following memory word the BD_COOKIE?
- */
- if (isa16) {
- err = __get_user(instr[0],
- (u16 __user *)(&fr->badinst));
- err |= __get_user(instr[1],
- (u16 __user *)((long)(&fr->badinst) + 2));
- insn = (instr[0] << 16) | instr[1];
- } else {
- err = __get_user(insn, &fr->badinst);
- }
- err |= __get_user(cookie, &fr->cookie);
-
- if (unlikely(err ||
- insn != BREAK_MATH(isa16) || cookie != BD_COOKIE)) {
+ /* Cleanup the allocated frame, returning if there wasn't one */
+ if (!dsemul_thread_cleanup(current)) {
MIPS_FPU_EMU_INC_STATS(errors);
- return 0;
- }
-
- /*
- * At this point, we are satisfied that it's a BD emulation trap. Yes,
- * a user might have deliberately put two malformed and useless
- * instructions in a row in his program, in which case he's in for a
- * nasty surprise - the next instruction will be treated as a
- * continuation address! Alas, this seems to be the only way that we
- * can handle signals, recursion, and longjmps() in the context of
- * emulating the branch delay instruction.
- */
-
- pr_debug("dsemulret\n");
-
- if (__get_user(epc, &fr->epc)) { /* Saved EPC */
- /* This is not a good situation to be in */
- force_sig(SIGBUS, current);
-
- return 0;
+ return false;
}
/* Set EPC to return to post-branch instruction */
- xcp->cp0_epc = epc;
- MIPS_FPU_EMU_INC_STATS(ds_emul);
- return 1;
+ xcp->cp0_epc = current->thread.bd_emu_cont_pc;
+ pr_debug("dsemulret to 0x%08lx\n", xcp->cp0_epc);
+ return true;
}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 7a9c345e87e5..cd72805b64a7 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -40,6 +40,51 @@
#include <asm/mips-cm.h>
/*
+ * Bits describing what cache ops an SMP callback function may perform.
+ *
+ * R4K_HIT - Virtual user or kernel address based cache operations. The
+ * active_mm must be checked before using user addresses, falling
+ * back to kmap.
+ * R4K_INDEX - Index based cache operations.
+ */
+
+#define R4K_HIT BIT(0)
+#define R4K_INDEX BIT(1)
+
+/**
+ * r4k_op_needs_ipi() - Decide if a cache op needs to be done on every core.
+ * @type: Type of cache operations (R4K_HIT or R4K_INDEX).
+ *
+ * Decides whether a cache op needs to be performed on every core in the system.
+ * This may change depending on the @type of cache operation, as well as the set
+ * of online CPUs, so preemption should be disabled by the caller to prevent CPU
+ * hotplug from changing the result.
+ *
+ * Returns: 1 if the cache operation @type should be done on every core in
+ * the system.
+ * 0 if the cache operation @type is globalized and only needs to
+ * be performed on a simple CPU.
+ */
+static inline bool r4k_op_needs_ipi(unsigned int type)
+{
+ /* The MIPS Coherence Manager (CM) globalizes address-based cache ops */
+ if (type == R4K_HIT && mips_cm_present())
+ return false;
+
+ /*
+ * Hardware doesn't globalize the required cache ops, so SMP calls may
+ * be needed, but only if there are foreign CPUs (non-siblings with
+ * separate caches).
+ */
+ /* cpu_foreign_map[] undeclared when !CONFIG_SMP */
+#ifdef CONFIG_SMP
+ return !cpumask_empty(&cpu_foreign_map[0]);
+#else
+ return false;
+#endif
+}
+
+/*
* Special Variant of smp_call_function for use by cache functions:
*
* o No return value
@@ -48,30 +93,17 @@
* primary cache.
* o doesn't disable interrupts on the local CPU
*/
-static inline void r4k_on_each_cpu(void (*func) (void *info), void *info)
+static inline void r4k_on_each_cpu(unsigned int type,
+ void (*func)(void *info), void *info)
{
preempt_disable();
-
- /*
- * The Coherent Manager propagates address-based cache ops to other
- * cores but not index-based ops. However, r4k_on_each_cpu is used
- * in both cases so there is no easy way to tell what kind of op is
- * executed to the other cores. The best we can probably do is
- * to restrict that call when a CM is not present because both
- * CM-based SMP protocols (CMP & CPS) restrict index-based cache ops.
- */
- if (!mips_cm_present())
- smp_call_function_many(&cpu_foreign_map, func, info, 1);
+ if (r4k_op_needs_ipi(type))
+ smp_call_function_many(&cpu_foreign_map[smp_processor_id()],
+ func, info, 1);
func(info);
preempt_enable();
}
-#if defined(CONFIG_MIPS_CMP) || defined(CONFIG_MIPS_CPS)
-#define cpu_has_safe_index_cacheops 0
-#else
-#define cpu_has_safe_index_cacheops 1
-#endif
-
/*
* Must die.
*/
@@ -462,22 +494,44 @@ static inline void local_r4k___flush_cache_all(void * args)
static void r4k___flush_cache_all(void)
{
- r4k_on_each_cpu(local_r4k___flush_cache_all, NULL);
+ r4k_on_each_cpu(R4K_INDEX, local_r4k___flush_cache_all, NULL);
}
-static inline int has_valid_asid(const struct mm_struct *mm)
+/**
+ * has_valid_asid() - Determine if an mm already has an ASID.
+ * @mm: Memory map.
+ * @type: R4K_HIT or R4K_INDEX, type of cache op.
+ *
+ * Determines whether @mm already has an ASID on any of the CPUs which cache ops
+ * of type @type within an r4k_on_each_cpu() call will affect. If
+ * r4k_on_each_cpu() does an SMP call to a single VPE in each core, then the
+ * scope of the operation is confined to sibling CPUs, otherwise all online CPUs
+ * will need to be checked.
+ *
+ * Must be called in non-preemptive context.
+ *
+ * Returns: 1 if the CPUs affected by @type cache ops have an ASID for @mm.
+ * 0 otherwise.
+ */
+static inline int has_valid_asid(const struct mm_struct *mm, unsigned int type)
{
-#ifdef CONFIG_MIPS_MT_SMP
- int i;
+ unsigned int i;
+ const cpumask_t *mask = cpu_present_mask;
- for_each_online_cpu(i)
+ /* cpu_sibling_map[] undeclared when !CONFIG_SMP */
+#ifdef CONFIG_SMP
+ /*
+ * If r4k_on_each_cpu does SMP calls, it does them to a single VPE in
+ * each foreign core, so we only need to worry about siblings.
+ * Otherwise we need to worry about all present CPUs.
+ */
+ if (r4k_op_needs_ipi(type))
+ mask = &cpu_sibling_map[smp_processor_id()];
+#endif
+ for_each_cpu(i, mask)
if (cpu_context(i, mm))
return 1;
-
return 0;
-#else
- return cpu_context(smp_processor_id(), mm);
-#endif
}
static void r4k__flush_cache_vmap(void)
@@ -490,12 +544,16 @@ static void r4k__flush_cache_vunmap(void)
r4k_blast_dcache();
}
+/*
+ * Note: flush_tlb_range() assumes flush_cache_range() sufficiently flushes
+ * whole caches when vma is executable.
+ */
static inline void local_r4k_flush_cache_range(void * args)
{
struct vm_area_struct *vma = args;
int exec = vma->vm_flags & VM_EXEC;
- if (!(has_valid_asid(vma->vm_mm)))
+ if (!has_valid_asid(vma->vm_mm, R4K_INDEX))
return;
/*
@@ -516,14 +574,14 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma,
int exec = vma->vm_flags & VM_EXEC;
if (cpu_has_dc_aliases || exec)
- r4k_on_each_cpu(local_r4k_flush_cache_range, vma);
+ r4k_on_each_cpu(R4K_INDEX, local_r4k_flush_cache_range, vma);
}
static inline void local_r4k_flush_cache_mm(void * args)
{
struct mm_struct *mm = args;
- if (!has_valid_asid(mm))
+ if (!has_valid_asid(mm, R4K_INDEX))
return;
/*
@@ -548,7 +606,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
if (!cpu_has_dc_aliases)
return;
- r4k_on_each_cpu(local_r4k_flush_cache_mm, mm);
+ r4k_on_each_cpu(R4K_INDEX, local_r4k_flush_cache_mm, mm);
}
struct flush_cache_page_args {
@@ -573,10 +631,10 @@ static inline void local_r4k_flush_cache_page(void *args)
void *vaddr;
/*
- * If ownes no valid ASID yet, cannot possibly have gotten
+ * If owns no valid ASID yet, cannot possibly have gotten
* this page into the cache.
*/
- if (!has_valid_asid(mm))
+ if (!has_valid_asid(mm, R4K_HIT))
return;
addr &= PAGE_MASK;
@@ -643,7 +701,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
args.addr = addr;
args.pfn = pfn;
- r4k_on_each_cpu(local_r4k_flush_cache_page, &args);
+ r4k_on_each_cpu(R4K_HIT, local_r4k_flush_cache_page, &args);
}
static inline void local_r4k_flush_data_cache_page(void * addr)
@@ -656,18 +714,23 @@ static void r4k_flush_data_cache_page(unsigned long addr)
if (in_atomic())
local_r4k_flush_data_cache_page((void *)addr);
else
- r4k_on_each_cpu(local_r4k_flush_data_cache_page, (void *) addr);
+ r4k_on_each_cpu(R4K_HIT, local_r4k_flush_data_cache_page,
+ (void *) addr);
}
struct flush_icache_range_args {
unsigned long start;
unsigned long end;
+ unsigned int type;
};
-static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
+static inline void __local_r4k_flush_icache_range(unsigned long start,
+ unsigned long end,
+ unsigned int type)
{
if (!cpu_has_ic_fills_f_dc) {
- if (end - start >= dcache_size) {
+ if (type == R4K_INDEX ||
+ (type & R4K_INDEX && end - start >= dcache_size)) {
r4k_blast_dcache();
} else {
R4600_HIT_CACHEOP_WAR_IMPL;
@@ -675,7 +738,8 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
}
}
- if (end - start > icache_size)
+ if (type == R4K_INDEX ||
+ (type & R4K_INDEX && end - start > icache_size))
r4k_blast_icache();
else {
switch (boot_cpu_type()) {
@@ -701,23 +765,52 @@ static inline void local_r4k_flush_icache_range(unsigned long start, unsigned lo
#endif
}
+static inline void local_r4k_flush_icache_range(unsigned long start,
+ unsigned long end)
+{
+ __local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX);
+}
+
static inline void local_r4k_flush_icache_range_ipi(void *args)
{
struct flush_icache_range_args *fir_args = args;
unsigned long start = fir_args->start;
unsigned long end = fir_args->end;
+ unsigned int type = fir_args->type;
- local_r4k_flush_icache_range(start, end);
+ __local_r4k_flush_icache_range(start, end, type);
}
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
{
struct flush_icache_range_args args;
+ unsigned long size, cache_size;
args.start = start;
args.end = end;
+ args.type = R4K_HIT | R4K_INDEX;
- r4k_on_each_cpu(local_r4k_flush_icache_range_ipi, &args);
+ /*
+ * Indexed cache ops require an SMP call.
+ * Consider if that can or should be avoided.
+ */
+ preempt_disable();
+ if (r4k_op_needs_ipi(R4K_INDEX) && !r4k_op_needs_ipi(R4K_HIT)) {
+ /*
+ * If address-based cache ops don't require an SMP call, then
+ * use them exclusively for small flushes.
+ */
+ size = start - end;
+ cache_size = icache_size;
+ if (!cpu_has_ic_fills_f_dc) {
+ size *= 2;
+ cache_size += dcache_size;
+ }
+ if (size <= cache_size)
+ args.type &= ~R4K_INDEX;
+ }
+ r4k_on_each_cpu(args.type, local_r4k_flush_icache_range_ipi, &args);
+ preempt_enable();
instruction_hazard();
}
@@ -744,7 +837,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
* subset property so we have to flush the primary caches
* explicitly
*/
- if (cpu_has_safe_index_cacheops && size >= dcache_size) {
+ if (size >= dcache_size) {
r4k_blast_dcache();
} else {
R4600_HIT_CACHEOP_WAR_IMPL;
@@ -781,7 +874,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
return;
}
- if (cpu_has_safe_index_cacheops && size >= dcache_size) {
+ if (size >= dcache_size) {
r4k_blast_dcache();
} else {
R4600_HIT_CACHEOP_WAR_IMPL;
@@ -794,25 +887,76 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
}
#endif /* CONFIG_DMA_NONCOHERENT || CONFIG_DMA_MAYBE_COHERENT */
+struct flush_cache_sigtramp_args {
+ struct mm_struct *mm;
+ struct page *page;
+ unsigned long addr;
+};
+
/*
* While we're protected against bad userland addresses we don't care
* very much about what happens in that case. Usually a segmentation
* fault will dump the process later on anyway ...
*/
-static void local_r4k_flush_cache_sigtramp(void * arg)
+static void local_r4k_flush_cache_sigtramp(void *args)
{
+ struct flush_cache_sigtramp_args *fcs_args = args;
+ unsigned long addr = fcs_args->addr;
+ struct page *page = fcs_args->page;
+ struct mm_struct *mm = fcs_args->mm;
+ int map_coherent = 0;
+ void *vaddr;
+
unsigned long ic_lsize = cpu_icache_line_size();
unsigned long dc_lsize = cpu_dcache_line_size();
unsigned long sc_lsize = cpu_scache_line_size();
- unsigned long addr = (unsigned long) arg;
+
+ /*
+ * If owns no valid ASID yet, cannot possibly have gotten
+ * this page into the cache.
+ */
+ if (!has_valid_asid(mm, R4K_HIT))
+ return;
+
+ if (mm == current->active_mm) {
+ vaddr = NULL;
+ } else {
+ /*
+ * Use kmap_coherent or kmap_atomic to do flushes for
+ * another ASID than the current one.
+ */
+ map_coherent = (cpu_has_dc_aliases &&
+ page_mapcount(page) &&
+ !Page_dcache_dirty(page));
+ if (map_coherent)
+ vaddr = kmap_coherent(page, addr);
+ else
+ vaddr = kmap_atomic(page);
+ addr = (unsigned long)vaddr + (addr & ~PAGE_MASK);
+ }
R4600_HIT_CACHEOP_WAR_IMPL;
- if (dc_lsize)
- protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
- if (!cpu_icache_snoops_remote_store && scache_size)
- protected_writeback_scache_line(addr & ~(sc_lsize - 1));
+ if (!cpu_has_ic_fills_f_dc) {
+ if (dc_lsize)
+ vaddr ? flush_dcache_line(addr & ~(dc_lsize - 1))
+ : protected_writeback_dcache_line(
+ addr & ~(dc_lsize - 1));
+ if (!cpu_icache_snoops_remote_store && scache_size)
+ vaddr ? flush_scache_line(addr & ~(sc_lsize - 1))
+ : protected_writeback_scache_line(
+ addr & ~(sc_lsize - 1));
+ }
if (ic_lsize)
- protected_flush_icache_line(addr & ~(ic_lsize - 1));
+ vaddr ? flush_icache_line(addr & ~(ic_lsize - 1))
+ : protected_flush_icache_line(addr & ~(ic_lsize - 1));
+
+ if (vaddr) {
+ if (map_coherent)
+ kunmap_coherent();
+ else
+ kunmap_atomic(vaddr);
+ }
+
if (MIPS4K_ICACHE_REFILL_WAR) {
__asm__ __volatile__ (
".set push\n\t"
@@ -837,7 +981,23 @@ static void local_r4k_flush_cache_sigtramp(void * arg)
static void r4k_flush_cache_sigtramp(unsigned long addr)
{
- r4k_on_each_cpu(local_r4k_flush_cache_sigtramp, (void *) addr);
+ struct flush_cache_sigtramp_args args;
+ int npages;
+
+ down_read(&current->mm->mmap_sem);
+
+ npages = get_user_pages_fast(addr, 1, 0, &args.page);
+ if (npages < 1)
+ goto out;
+
+ args.mm = current->mm;
+ args.addr = addr;
+
+ r4k_on_each_cpu(R4K_HIT, local_r4k_flush_cache_sigtramp, &args);
+
+ put_page(args.page);
+out:
+ up_read(&current->mm->mmap_sem);
}
static void r4k_flush_icache_all(void)
@@ -851,6 +1011,15 @@ struct flush_kernel_vmap_range_args {
int size;
};
+static inline void local_r4k_flush_kernel_vmap_range_index(void *args)
+{
+ /*
+ * Aliases only affect the primary caches so don't bother with
+ * S-caches or T-caches.
+ */
+ r4k_blast_dcache();
+}
+
static inline void local_r4k_flush_kernel_vmap_range(void *args)
{
struct flush_kernel_vmap_range_args *vmra = args;
@@ -861,12 +1030,8 @@ static inline void local_r4k_flush_kernel_vmap_range(void *args)
* Aliases only affect the primary caches so don't bother with
* S-caches or T-caches.
*/
- if (cpu_has_safe_index_cacheops && size >= dcache_size)
- r4k_blast_dcache();
- else {
- R4600_HIT_CACHEOP_WAR_IMPL;
- blast_dcache_range(vaddr, vaddr + size);
- }
+ R4600_HIT_CACHEOP_WAR_IMPL;
+ blast_dcache_range(vaddr, vaddr + size);
}
static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
@@ -876,7 +1041,12 @@ static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
args.vaddr = (unsigned long) vaddr;
args.size = size;
- r4k_on_each_cpu(local_r4k_flush_kernel_vmap_range, &args);
+ if (size >= dcache_size)
+ r4k_on_each_cpu(R4K_INDEX,
+ local_r4k_flush_kernel_vmap_range_index, NULL);
+ else
+ r4k_on_each_cpu(R4K_HIT, local_r4k_flush_kernel_vmap_range,
+ &args);
}
static inline void rm7k_erratum31(void)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index cb557d28cb21..b2eadd6fa9a1 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -131,7 +131,7 @@ static void *mips_dma_alloc_noncoherent(struct device *dev, size_t size,
}
static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
struct page *page = NULL;
@@ -141,7 +141,7 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
* XXX: seems like the coherent and non-coherent implementations could
* be consolidated.
*/
- if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
+ if (attrs & DMA_ATTR_NON_CONSISTENT)
return mips_dma_alloc_noncoherent(dev, size, dma_handle, gfp);
gfp = massage_gfp_flags(dev, gfp);
@@ -176,13 +176,13 @@ static void mips_dma_free_noncoherent(struct device *dev, size_t size,
}
static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
unsigned long addr = (unsigned long) vaddr;
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page *page = NULL;
- if (dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ if (attrs & DMA_ATTR_NON_CONSISTENT) {
mips_dma_free_noncoherent(dev, size, vaddr, dma_handle);
return;
}
@@ -200,7 +200,7 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
@@ -214,7 +214,7 @@ static int mips_dma_mmap(struct device *dev, struct vm_area_struct *vma,
pfn = page_to_pfn(virt_to_page((void *)addr));
- if (dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs))
+ if (attrs & DMA_ATTR_WRITE_COMBINE)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
else
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -291,7 +291,7 @@ static inline void __dma_sync(struct page *page,
}
static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction direction, unsigned long attrs)
{
if (cpu_needs_post_dma_flush(dev))
__dma_sync(dma_addr_to_page(dev, dma_addr),
@@ -301,7 +301,7 @@ static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
}
static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction direction, unsigned long attrs)
{
int i;
struct scatterlist *sg;
@@ -322,7 +322,7 @@ static int mips_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (!plat_device_is_coherent(dev))
__dma_sync(page, offset, size, direction);
@@ -332,7 +332,7 @@ static dma_addr_t mips_dma_map_page(struct device *dev, struct page *page,
static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nhwentries, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
diff --git a/arch/mips/mm/sc-debugfs.c b/arch/mips/mm/sc-debugfs.c
index 5eefe3281b24..01f1154cdb0c 100644
--- a/arch/mips/mm/sc-debugfs.c
+++ b/arch/mips/mm/sc-debugfs.c
@@ -73,8 +73,8 @@ static int __init sc_debugfs_init(void)
file = debugfs_create_file("prefetch", S_IRUGO | S_IWUSR, dir,
NULL, &sc_prefetch_fops);
- if (IS_ERR(file))
- return PTR_ERR(file);
+ if (!file)
+ return -ENOMEM;
return 0;
}
diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c
index 9ac1efcfbcc7..78f900c59276 100644
--- a/arch/mips/mm/sc-rm7k.c
+++ b/arch/mips/mm/sc-rm7k.c
@@ -161,7 +161,7 @@ static void rm7k_tc_disable(void)
local_irq_save(flags);
blast_rm7k_tcache();
clear_c0_config(RM7K_CONF_TE);
- local_irq_save(flags);
+ local_irq_restore(flags);
}
static void rm7k_sc_disable(void)
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 4004b659ce50..55ce39606cb8 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -888,7 +888,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
}
}
if (!did_vmalloc_branch) {
- if (uasm_in_compat_space_p(swpd) && !uasm_rel_lo(swpd)) {
+ if (single_insn_swpd) {
uasm_il_b(p, r, label_vmalloc_done);
uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
} else {
@@ -1025,7 +1025,7 @@ static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep)
pte_off_odd += offsetof(pte_t, pte_high);
#endif
- if (config_enabled(CONFIG_XPA)) {
+ if (IS_ENABLED(CONFIG_XPA)) {
uasm_i_lw(p, tmp, pte_off_even, ptep); /* even pte */
UASM_i_ROTR(p, tmp, tmp, ilog2(_PAGE_GLOBAL));
UASM_i_MTC0(p, tmp, C0_ENTRYLO0);
@@ -1643,7 +1643,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr,
unsigned int hwmode = mode & (_PAGE_VALID | _PAGE_DIRTY);
unsigned int swmode = mode & ~hwmode;
- if (config_enabled(CONFIG_XPA) && !cpu_has_64bits) {
+ if (IS_ENABLED(CONFIG_XPA) && !cpu_has_64bits) {
uasm_i_lui(p, scratch, swmode >> 16);
uasm_i_or(p, pte, pte, scratch);
BUG_ON(swmode & 0xffff);
@@ -2432,7 +2432,7 @@ static void config_htw_params(void)
pwsize |= ilog2(PTRS_PER_PMD) << MIPS_PWSIZE_MDW_SHIFT;
/* Set pointer size to size of directory pointers */
- if (config_enabled(CONFIG_64BIT))
+ if (IS_ENABLED(CONFIG_64BIT))
pwsize |= MIPS_PWSIZE_PS_MASK;
/* PTEs may be multiple pointers long (e.g. with XPA) */
pwsize |= ((PTE_T_LOG2 - PGD_T_LOG2) << MIPS_PWSIZE_PTEW_SHIFT)
@@ -2448,7 +2448,7 @@ static void config_htw_params(void)
* the pwctl fields.
*/
config = 1 << MIPS_PWCTL_PWEN_SHIFT;
- if (config_enabled(CONFIG_64BIT))
+ if (IS_ENABLED(CONFIG_64BIT))
config |= MIPS_PWCTL_XU_MASK;
write_c0_pwctl(config);
pr_info("Hardware Page Table Walker enabled\n");
@@ -2522,7 +2522,7 @@ void build_tlb_refill_handler(void)
*/
static int run_once = 0;
- if (config_enabled(CONFIG_XPA) && !cpu_has_rixi)
+ if (IS_ENABLED(CONFIG_XPA) && !cpu_has_rixi)
panic("Kernels supporting XPA currently require CPUs with RIXI");
output_pgtable_bits_defines();
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
index cec524167822..763d3f1edb8a 100644
--- a/arch/mips/mm/uasm-mips.c
+++ b/arch/mips/mm/uasm-mips.c
@@ -65,7 +65,7 @@ static struct insn insn_table[] = {
#ifndef CONFIG_CPU_MIPSR6
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
#else
- { insn_cache, M6(cache_op, 0, 0, 0, cache6_op), RS | RT | SIMM9 },
+ { insn_cache, M6(spec3_op, 0, 0, 0, cache6_op), RS | RT | SIMM9 },
#endif
{ insn_cfc1, M(cop1_op, cfc_op, 0, 0, 0, 0), RT | RD },
{ insn_cfcmsa, M(msa_op, 0, msa_cfc_op, 0, 0, msa_elm_op), RD | RE },
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index 3e0282d301d6..a82970442b8a 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -378,11 +378,7 @@ UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label));
int ISAFUNC(uasm_in_compat_space_p)(long addr)
{
/* Is this address in 32bit compat space? */
-#ifdef CONFIG_64BIT
- return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
-#else
- return 1;
-#endif
+ return addr == (int)addr;
}
UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p));
diff --git a/arch/mips/mti-malta/malta-dtshim.c b/arch/mips/mti-malta/malta-dtshim.c
index f7133efc5843..151f4882ec8a 100644
--- a/arch/mips/mti-malta/malta-dtshim.c
+++ b/arch/mips/mti-malta/malta-dtshim.c
@@ -31,7 +31,7 @@ static unsigned __init gen_fdt_mem_array(__be32 *mem_array, unsigned long size)
entries = 1;
mem_array[0] = cpu_to_be32(PHYS_OFFSET);
- if (config_enabled(CONFIG_EVA)) {
+ if (IS_ENABLED(CONFIG_EVA)) {
/*
* The current Malta EVA configuration is "special" in that it
* always makes use of addresses in the upper half of the 32 bit
@@ -82,7 +82,7 @@ static void __init append_memory(void *fdt, int root_off)
physical_memsize = 32 << 20;
}
- if (config_enabled(CONFIG_CPU_BIG_ENDIAN)) {
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) {
/*
* SOC-it swaps, or perhaps doesn't swap, when DMA'ing
* the last word of physical memory.
diff --git a/arch/mips/mti-malta/malta-memory.c b/arch/mips/mti-malta/malta-memory.c
index d5f8dae6a797..a47556723b85 100644
--- a/arch/mips/mti-malta/malta-memory.c
+++ b/arch/mips/mti-malta/malta-memory.c
@@ -32,7 +32,7 @@ static void free_init_pages_eva_malta(void *begin, void *end)
void __init fw_meminit(void)
{
- bool eva = config_enabled(CONFIG_EVA);
+ bool eva = IS_ENABLED(CONFIG_EVA);
free_init_pages_eva = eva ? free_init_pages_eva_malta : NULL;
}
diff --git a/arch/mips/mti-malta/malta-setup.c b/arch/mips/mti-malta/malta-setup.c
index 33d5ff5069e5..ec5b21678fad 100644
--- a/arch/mips/mti-malta/malta-setup.c
+++ b/arch/mips/mti-malta/malta-setup.c
@@ -261,7 +261,7 @@ void __init plat_mem_setup(void)
fdt = malta_dt_shim(fdt);
__dt_setup_arch(fdt);
- if (config_enabled(CONFIG_EVA))
+ if (IS_ENABLED(CONFIG_EVA))
/* EVA has already been configured in mach-malta/kernel-init.h */
pr_info("Enhanced Virtual Addressing (EVA) activated\n");
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 1a8c96035716..39e7b472f0d8 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -426,7 +426,7 @@ static inline void emit_load_ptr(unsigned int dst, unsigned int src,
static inline void emit_load_func(unsigned int reg, ptr imm,
struct jit_ctx *ctx)
{
- if (config_enabled(CONFIG_64BIT)) {
+ if (IS_ENABLED(CONFIG_64BIT)) {
/* At this point imm is always 64-bit */
emit_load_imm(r_tmp, (u64)imm >> 32, ctx);
emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */
@@ -516,7 +516,7 @@ static inline void emit_jr(unsigned int reg, struct jit_ctx *ctx)
static inline u16 align_sp(unsigned int num)
{
/* Double word alignment for 32-bit, quadword for 64-bit */
- unsigned int align = config_enabled(CONFIG_64BIT) ? 16 : 8;
+ unsigned int align = IS_ENABLED(CONFIG_64BIT) ? 16 : 8;
num = (num + (align - 1)) & -align;
return num;
}
@@ -1199,7 +1199,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
memset(&ctx, 0, sizeof(ctx));
- ctx.offsets = kcalloc(fp->len, sizeof(*ctx.offsets), GFP_KERNEL);
+ ctx.offsets = kcalloc(fp->len + 1, sizeof(*ctx.offsets), GFP_KERNEL);
if (ctx.offsets == NULL)
return;
diff --git a/arch/mips/netlogic/common/nlm-dma.c b/arch/mips/netlogic/common/nlm-dma.c
index 3758715d4ab6..0630693bec2a 100644
--- a/arch/mips/netlogic/common/nlm-dma.c
+++ b/arch/mips/netlogic/common/nlm-dma.c
@@ -45,7 +45,7 @@
static char *nlm_swiotlb;
static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM);
@@ -62,7 +62,7 @@ static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
}
static void nlm_dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
+ void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/arch/mips/pic32/pic32mzda/init.c b/arch/mips/pic32/pic32mzda/init.c
index 77ecf32ef3dc..51599710472b 100644
--- a/arch/mips/pic32/pic32mzda/init.c
+++ b/arch/mips/pic32/pic32mzda/init.c
@@ -33,8 +33,8 @@ static ulong get_fdtaddr(void)
{
ulong ftaddr = 0;
- if ((fw_arg0 == -2) && fw_arg1 && !fw_arg2 && !fw_arg3)
- return (ulong)fw_arg1;
+ if (fw_passed_dtb && !fw_arg2 && !fw_arg3)
+ return (ulong)fw_passed_dtb;
if (__dtb_start < __dtb_end)
ftaddr = (ulong)__dtb_start;
diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c
index c50a670e60d2..1c91cad7988f 100644
--- a/arch/mips/pistachio/init.c
+++ b/arch/mips/pistachio/init.c
@@ -59,29 +59,6 @@ const char *get_system_type(void)
return sys_type;
}
-static void __init plat_setup_iocoherency(void)
-{
- /*
- * Kernel has been configured with software coherency
- * but we might choose to turn it off and use hardware
- * coherency instead.
- */
- if (mips_cm_numiocu() != 0) {
- /* Nothing special needs to be done to enable coherency */
- pr_info("CMP IOCU detected\n");
- hw_coherentio = 1;
- if (coherentio == 0)
- pr_info("Hardware DMA cache coherency disabled\n");
- else
- pr_info("Hardware DMA cache coherency enabled\n");
- } else {
- if (coherentio == 1)
- pr_info("Hardware DMA cache coherency unsupported, but enabled from command line!\n");
- else
- pr_info("Software DMA cache coherency enabled\n");
- }
-}
-
void __init *plat_get_fdt(void)
{
if (fw_arg0 != -2)
@@ -92,8 +69,6 @@ void __init *plat_get_fdt(void)
void __init plat_mem_setup(void)
{
__dt_setup_arch(plat_get_fdt());
-
- plat_setup_iocoherency();
}
#define DEFAULT_CPC_BASE_ADDR 0x1bde0000
diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c
index d40edda0ca3b..3c7c9bf57bf3 100644
--- a/arch/mips/ralink/mt7620.c
+++ b/arch/mips/ralink/mt7620.c
@@ -175,7 +175,7 @@ static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = {
};
static struct rt2880_pmx_func spis_grp_mt7628[] = {
- FUNC("pwm", 3, 14, 4),
+ FUNC("pwm_uart2", 3, 14, 4),
FUNC("util", 2, 14, 4),
FUNC("gpio", 1, 14, 4),
FUNC("spis", 0, 14, 4),
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index 063c2dd31e72..2f45b0357021 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -7,7 +7,7 @@
*/
#include <linux/linkage.h>
#include <linux/init.h>
-#include <linux/ds1286.h>
+#include <linux/rtc/ds1286.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index fb4b3520cdc6..7ee14f41fc25 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -8,7 +8,6 @@
#include <asm/sni.h>
#include <asm/time.h>
-#include <asm-generic/rtc.h>
#define SNI_CLOCK_TICK_RATE 3686400
#define SNI_COUNTER2_DIV 64
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 9627e81a6cbb..38e3494bfb63 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -236,7 +236,9 @@ source "kernel/Kconfig.hz"
config MN10300_RTC
bool "Using MN10300 RTC"
depends on MN10300_PROC_MN103E010 || MN10300_PROC_MN2WS0050
- select GENERIC_CMOS_UPDATE
+ select RTC_CLASS
+ select RTC_DRV_CMOS
+ select RTC_SYSTOHC
default n
help
This option enables support for the RTC, thus enabling time to be
diff --git a/arch/mn10300/include/asm/rtc-regs.h b/arch/mn10300/include/asm/rtc-regs.h
index c42deefaec11..c81cacecb6e3 100644
--- a/arch/mn10300/include/asm/rtc-regs.h
+++ b/arch/mn10300/include/asm/rtc-regs.h
@@ -75,9 +75,9 @@
#define RTC_PORT(x) 0xd8600000
#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
-#define CMOS_READ(addr) __SYSREG(0xd8600000 + (addr), u8)
+#define CMOS_READ(addr) __SYSREG(0xd8600000 + (u32)(addr), u8)
#define CMOS_WRITE(val, addr) \
- do { __SYSREG(0xd8600000 + (addr), u8) = val; } while (0)
+ do { __SYSREG(0xd8600000 + (u32)(addr), u8) = val; } while (0)
#define RTC_IRQ RTIRQ
diff --git a/arch/mn10300/include/asm/rtc.h b/arch/mn10300/include/asm/rtc.h
index 6c14bb1d0d9b..07dc87656197 100644
--- a/arch/mn10300/include/asm/rtc.h
+++ b/arch/mn10300/include/asm/rtc.h
@@ -25,6 +25,4 @@ static inline void calibrate_clock(void)
#endif /* !CONFIG_MN10300_RTC */
-#include <asm-generic/rtc.h>
-
#endif /* _ASM_RTC_H */
diff --git a/arch/mn10300/kernel/rtc.c b/arch/mn10300/kernel/rtc.c
index 48d7058b3295..f81f37025072 100644
--- a/arch/mn10300/kernel/rtc.c
+++ b/arch/mn10300/kernel/rtc.c
@@ -12,107 +12,19 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mc146818rtc.h>
-#include <linux/bcd.h>
-#include <linux/timex.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
#include <asm/rtc-regs.h>
#include <asm/rtc.h>
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
-/*
- * Read the current RTC time
- */
-void read_persistent_clock(struct timespec *ts)
-{
- struct rtc_time tm;
-
- get_rtc_time(&tm);
-
- ts->tv_nsec = 0;
- ts->tv_sec = mktime(tm.tm_year, tm.tm_mon, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
-
- /* if rtc is way off in the past, set something reasonable */
- if (ts->tv_sec < 0)
- ts->tv_sec = mktime(2009, 1, 1, 12, 0, 0);
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
- * ms after the second nowtime has started, because when nowtime is written
- * into the registers of the CMOS clock, it will jump to the next second
- * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
- * sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- * sets the minutes. Usually you'll only notice that after reboot!
- */
-static int set_rtc_mmss(unsigned long nowtime)
-{
- unsigned char save_control, save_freq_select;
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
-
- /* gets recalled with irq locally disabled */
- spin_lock(&rtc_lock);
- save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being
- * set */
- CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
-
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset
- * prescaler */
- CMOS_WRITE(save_freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
-
- cmos_minutes = CMOS_READ(RTC_MINUTES);
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- cmos_minutes = bcd2bin(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
- /* correct for half hour time zone */
- real_minutes += 30;
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- real_seconds = bin2bcd(real_seconds);
- real_minutes = bin2bcd(real_minutes);
- }
- CMOS_WRITE(real_seconds, RTC_SECONDS);
- CMOS_WRITE(real_minutes, RTC_MINUTES);
- } else {
- printk_once(KERN_NOTICE
- "set_rtc_mmss: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
- retval = -1;
- }
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- spin_unlock(&rtc_lock);
-
- return retval;
-}
-
-int update_persistent_clock(struct timespec now)
-{
- return set_rtc_mmss(now.tv_sec);
-}
+static const __initdata struct resource res[] = {
+ DEFINE_RES_IO(RTC_PORT(0), RTC_IO_EXTENT),
+ DEFINE_RES_IRQ(RTC_IRQ),
+};
/*
* calibrate the TSC clock against the RTC
@@ -129,4 +41,6 @@ void __init calibrate_clock(void)
RTCRA |= RTCRA_DVR;
RTCRA &= ~RTCRA_DVR;
RTCRB &= ~RTCRB_SET;
+
+ platform_device_register_simple("rtc_cmos", -1, res, ARRAY_SIZE(res));
}
diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c
index 8842394cb49a..4f4b9029f0ea 100644
--- a/arch/mn10300/mm/dma-alloc.c
+++ b/arch/mn10300/mm/dma-alloc.c
@@ -21,7 +21,7 @@
static unsigned long pci_sram_allocated = 0xbc000000;
static void *mn10300_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
unsigned long addr;
void *ret;
@@ -63,7 +63,7 @@ done:
}
static void mn10300_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
unsigned long addr = (unsigned long) vaddr & ~0x20000000;
@@ -75,7 +75,7 @@ static void mn10300_dma_free(struct device *dev, size_t size, void *vaddr,
static int mn10300_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -92,7 +92,7 @@ static int mn10300_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static dma_addr_t mn10300_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
return page_to_bus(page) + offset;
}
diff --git a/arch/mn10300/proc-mn103e010/proc-init.c b/arch/mn10300/proc-mn103e010/proc-init.c
index 27b97980dca4..102d86a6ae56 100644
--- a/arch/mn10300/proc-mn103e010/proc-init.c
+++ b/arch/mn10300/proc-mn103e010/proc-init.c
@@ -9,7 +9,10 @@
* 2 of the Licence, or (at your option) any later version.
*/
#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <asm/cacheflush.h>
#include <asm/fpu.h>
+#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/busctl-regs.h>
diff --git a/arch/mn10300/proc-mn2ws0050/proc-init.c b/arch/mn10300/proc-mn2ws0050/proc-init.c
index ee6d03dbc8d8..950cc8dbb284 100644
--- a/arch/mn10300/proc-mn2ws0050/proc-init.c
+++ b/arch/mn10300/proc-mn2ws0050/proc-init.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <asm/cacheflush.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/io.h>
diff --git a/arch/nios2/mm/dma-mapping.c b/arch/nios2/mm/dma-mapping.c
index 90422c367ed3..d800fad87896 100644
--- a/arch/nios2/mm/dma-mapping.c
+++ b/arch/nios2/mm/dma-mapping.c
@@ -59,7 +59,7 @@ static inline void __dma_sync_for_cpu(void *vaddr, size_t size,
}
static void *nios2_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -84,7 +84,7 @@ static void *nios2_dma_alloc(struct device *dev, size_t size,
}
static void nios2_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
unsigned long addr = (unsigned long) CAC_ADDR((unsigned long) vaddr);
@@ -93,7 +93,7 @@ static void nios2_dma_free(struct device *dev, size_t size, void *vaddr,
static int nios2_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
@@ -113,7 +113,7 @@ static int nios2_dma_map_sg(struct device *dev, struct scatterlist *sg,
static dma_addr_t nios2_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *addr = page_address(page) + offset;
@@ -123,14 +123,14 @@ static dma_addr_t nios2_dma_map_page(struct device *dev, struct page *page,
static void nios2_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
__dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
}
static void nios2_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nhwentries, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *addr;
int i;
diff --git a/arch/openrisc/kernel/dma.c b/arch/openrisc/kernel/dma.c
index 0b77ddb1ee07..140c99140649 100644
--- a/arch/openrisc/kernel/dma.c
+++ b/arch/openrisc/kernel/dma.c
@@ -22,7 +22,6 @@
#include <linux/dma-mapping.h>
#include <linux/dma-debug.h>
#include <linux/export.h>
-#include <linux/dma-attrs.h>
#include <asm/cpuinfo.h>
#include <asm/spr_defs.h>
@@ -83,7 +82,7 @@ page_clear_nocache(pte_t *pte, unsigned long addr,
static void *
or1k_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long va;
void *page;
@@ -101,7 +100,7 @@ or1k_dma_alloc(struct device *dev, size_t size,
va = (unsigned long)page;
- if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ if ((attrs & DMA_ATTR_NON_CONSISTENT) == 0) {
/*
* We need to iterate through the pages, clearing the dcache for
* them and setting the cache-inhibit bit.
@@ -117,7 +116,7 @@ or1k_dma_alloc(struct device *dev, size_t size,
static void
or1k_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
unsigned long va = (unsigned long)vaddr;
struct mm_walk walk = {
@@ -125,7 +124,7 @@ or1k_dma_free(struct device *dev, size_t size, void *vaddr,
.mm = &init_mm
};
- if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) {
+ if ((attrs & DMA_ATTR_NON_CONSISTENT) == 0) {
/* walk_page_range shouldn't be able to fail here */
WARN_ON(walk_page_range(va, va + size, &walk));
}
@@ -137,7 +136,7 @@ static dma_addr_t
or1k_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long cl;
dma_addr_t addr = page_to_phys(page) + offset;
@@ -170,7 +169,7 @@ or1k_map_page(struct device *dev, struct page *page,
static void
or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
/* Nothing special to do here... */
}
@@ -178,14 +177,14 @@ or1k_unmap_page(struct device *dev, dma_addr_t dma_handle,
static int
or1k_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nents, i) {
s->dma_address = or1k_map_page(dev, sg_page(s), s->offset,
- s->length, dir, NULL);
+ s->length, dir, 0);
}
return nents;
@@ -194,13 +193,13 @@ or1k_map_sg(struct device *dev, struct scatterlist *sg,
static void
or1k_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nents, i) {
- or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, NULL);
+ or1k_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, 0);
}
}
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index dc117385ce2e..cd8778103165 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -31,6 +31,7 @@ config PARISC
select TTY # Needed for pdc_cons.c
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_HASH
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_UNSTABLE_SCHED_CLOCK if (SMP || !64BIT)
diff --git a/arch/parisc/include/asm/hash.h b/arch/parisc/include/asm/hash.h
new file mode 100644
index 000000000000..dbe93311aa26
--- /dev/null
+++ b/arch/parisc/include/asm/hash.h
@@ -0,0 +1,146 @@
+#ifndef _ASM_HASH_H
+#define _ASM_HASH_H
+
+/*
+ * HP-PA only implements integer multiply in the FPU. However, for
+ * integer multiplies by constant, it has a number of shift-and-add
+ * (but no shift-and-subtract, sigh!) instructions that a compiler
+ * can synthesize a code sequence with.
+ *
+ * Unfortunately, GCC isn't very efficient at using them. For example
+ * it uses three instructions for "x *= 21" when only two are needed.
+ * But we can find a sequence manually.
+ */
+
+#define HAVE_ARCH__HASH_32 1
+
+/*
+ * This is a multiply by GOLDEN_RATIO_32 = 0x61C88647 optimized for the
+ * PA7100 pairing rules. This is an in-order 2-way superscalar processor.
+ * Only one instruction in a pair may be a shift (by more than 3 bits),
+ * but other than that, simple ALU ops (including shift-and-add by up
+ * to 3 bits) may be paired arbitrarily.
+ *
+ * PA8xxx processors also dual-issue ALU instructions, although with
+ * fewer constraints, so this schedule is good for them, too.
+ *
+ * This 6-step sequence was found by Yevgen Voronenko's implementation
+ * of the Hcub algorithm at http://spiral.ece.cmu.edu/mcm/gen.html.
+ */
+static inline u32 __attribute_const__ __hash_32(u32 x)
+{
+ u32 a, b, c;
+
+ /*
+ * Phase 1: Compute a = (x << 19) + x,
+ * b = (x << 9) + a, c = (x << 23) + b.
+ */
+ a = x << 19; /* Two shifts can't be paired */
+ b = x << 9; a += x;
+ c = x << 23; b += a;
+ c += b;
+ /* Phase 2: Return (b<<11) + (c<<6) + (a<<3) - c */
+ b <<= 11;
+ a += c << 3; b -= c;
+ return (a << 3) + b;
+}
+
+#if BITS_PER_LONG == 64
+
+#define HAVE_ARCH_HASH_64 1
+
+/*
+ * Finding a good shift-and-add chain for GOLDEN_RATIO_64 is tricky,
+ * because available software for the purpose chokes on constants this
+ * large. (It's mostly designed for compiling FIR filter coefficients
+ * into FPGAs.)
+ *
+ * However, Jason Thong pointed out a work-around. The Hcub software
+ * (http://spiral.ece.cmu.edu/mcm/gen.html) is designed for *multiple*
+ * constant multiplication, and is good at finding shift-and-add chains
+ * which share common terms.
+ *
+ * Looking at 0x0x61C8864680B583EB in binary:
+ * 0110000111001000100001100100011010000000101101011000001111101011
+ * \______________/ \__________/ \_______/ \________/
+ * \____________________________/ \____________________/
+ * you can see the non-zero bits are divided into several well-separated
+ * blocks. Hcub can find algorithms for those terms separately, which
+ * can then be shifted and added together.
+ *
+ * Dividing the input into 2, 3 or 4 blocks, Hcub can find solutions
+ * with 10, 9 or 8 adds, respectively, making a total of 11 for the
+ * whole number.
+ *
+ * Using just two large blocks, 0xC3910C8D << 31 in the high bits,
+ * and 0xB583EB in the low bits, produces as good an algorithm as any,
+ * and with one more small shift than alternatives.
+ *
+ * The high bits are a larger number and more work to compute, as well
+ * as needing one extra cycle to shift left 31 bits before the final
+ * addition, so they are the critical path for scheduling. The low bits
+ * can fit into the scheduling slots left over.
+ */
+
+
+/*
+ * This _ASSIGN(dst, src) macro performs "dst = src", but prevents GCC
+ * from inferring anything about the value assigned to "dest".
+ *
+ * This prevents it from mis-optimizing certain sequences.
+ * In particular, gcc is annoyingly eager to combine consecutive shifts.
+ * Given "x <<= 19; y += x; z += x << 1;", GCC will turn this into
+ * "y += x << 19; z += x << 20;" even though the latter sequence needs
+ * an additional instruction and temporary register.
+ *
+ * Because no actual assembly code is generated, this construct is
+ * usefully portable across all GCC platforms, and so can be test-compiled
+ * on non-PA systems.
+ *
+ * In two places, additional unused input dependencies are added. This
+ * forces GCC's scheduling so it does not rearrange instructions too much.
+ * Because the PA-8xxx is out of order, I'm not sure how much this matters,
+ * but why make it more difficult for the processor than necessary?
+ */
+#define _ASSIGN(dst, src, ...) asm("" : "=r" (dst) : "0" (src), ##__VA_ARGS__)
+
+/*
+ * Multiply by GOLDEN_RATIO_64 = 0x0x61C8864680B583EB using a heavily
+ * optimized shift-and-add sequence.
+ *
+ * Without the final shift, the multiply proper is 19 instructions,
+ * 10 cycles and uses only 4 temporaries. Whew!
+ *
+ * You are not expected to understand this.
+ */
+static __always_inline u32 __attribute_const__
+hash_64(u64 a, unsigned int bits)
+{
+ u64 b, c, d;
+
+ /*
+ * Encourage GCC to move a dynamic shift to %sar early,
+ * thereby freeing up an additional temporary register.
+ */
+ if (!__builtin_constant_p(bits))
+ asm("" : "=q" (bits) : "0" (64 - bits));
+ else
+ bits = 64 - bits;
+
+ _ASSIGN(b, a*5); c = a << 13;
+ b = (b << 2) + a; _ASSIGN(d, a << 17);
+ a = b + (a << 1); c += d;
+ d = a << 10; _ASSIGN(a, a << 19);
+ d = a - d; _ASSIGN(a, a << 4, "X" (d));
+ c += b; a += b;
+ d -= c; c += a << 1;
+ a += c << 3; _ASSIGN(b, b << (7+31), "X" (c), "X" (d));
+ a <<= 31; b += d;
+ a += b;
+ return a >> bits;
+}
+#undef _ASSIGN /* We're a widely-used header file, so don't litter! */
+
+#endif /* BITS_PER_LONG == 64 */
+
+#endif /* _ASM_HASH_H */
diff --git a/arch/parisc/include/asm/mc146818rtc.h b/arch/parisc/include/asm/mc146818rtc.h
deleted file mode 100644
index adf41631449f..000000000000
--- a/arch/parisc/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-/* empty include file to satisfy the include in genrtc.c */
-
-#endif /* _ASM_MC146818RTC_H */
diff --git a/arch/parisc/include/asm/rtc.h b/arch/parisc/include/asm/rtc.h
deleted file mode 100644
index 099d641a42c2..000000000000
--- a/arch/parisc/include/asm/rtc.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * include/asm-parisc/rtc.h
- *
- * Copyright 2002 Randolph CHung <tausq@debian.org>
- *
- * Based on: include/asm-ppc/rtc.h and the genrtc driver in the
- * 2.4 parisc linux tree
- */
-
-#ifndef __ASM_RTC_H__
-#define __ASM_RTC_H__
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-
-#include <asm/pdc.h>
-
-#define SECS_PER_HOUR (60 * 60)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-
-#define RTC_PIE 0x40 /* periodic interrupt enable */
-#define RTC_AIE 0x20 /* alarm interrupt enable */
-#define RTC_UIE 0x10 /* update-finished interrupt enable */
-
-#define RTC_BATT_BAD 0x100 /* battery bad */
-
-/* some dummy definitions */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-# define __isleap(year) \
- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
-
-/* How many days come before each month (0-12). */
-static const unsigned short int __mon_yday[2][13] =
-{
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
-static inline unsigned int get_rtc_time(struct rtc_time *wtime)
-{
- struct pdc_tod tod_data;
- long int days, rem, y;
- const unsigned short int *ip;
-
- memset(wtime, 0, sizeof(*wtime));
- if (pdc_tod_read(&tod_data) < 0)
- return RTC_24H | RTC_BATT_BAD;
-
- // most of the remainder of this function is:
-// Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc.
-// This was originally a part of the GNU C Library.
-// It is distributed under the GPL, and was swiped from offtime.c
-
-
- days = tod_data.tod_sec / SECS_PER_DAY;
- rem = tod_data.tod_sec % SECS_PER_DAY;
-
- wtime->tm_hour = rem / SECS_PER_HOUR;
- rem %= SECS_PER_HOUR;
- wtime->tm_min = rem / 60;
- wtime->tm_sec = rem % 60;
-
- y = 1970;
-
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
-
- while (days < 0 || days >= (__isleap (y) ? 366 : 365))
- {
- /* Guess a corrected year, assuming 365 days per year. */
- long int yg = y + days / 365 - (days % 365 < 0);
-
- /* Adjust DAYS and Y to match the guessed year. */
- days -= ((yg - y) * 365
- + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- y = yg;
- }
- wtime->tm_year = y - 1900;
-
- ip = __mon_yday[__isleap(y)];
- for (y = 11; days < (long int) ip[y]; --y)
- continue;
- days -= ip[y];
- wtime->tm_mon = y;
- wtime->tm_mday = days + 1;
-
- return RTC_24H;
-}
-
-static int set_rtc_time(struct rtc_time *wtime)
-{
- u_int32_t secs;
-
- secs = mktime(wtime->tm_year + 1900, wtime->tm_mon + 1, wtime->tm_mday,
- wtime->tm_hour, wtime->tm_min, wtime->tm_sec);
-
- if(pdc_tod_set(secs, 0) < 0)
- return -1;
- else
- return 0;
-
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
- struct rtc_time h;
-
- get_rtc_time(&h);
- return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_RTC_H__ */
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 22395901d47b..e5d71905cad5 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -1354,9 +1354,9 @@ int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
__pa(pdc_result), pci_addr, pci_size);
switch(pci_size) {
- case 1: *(u8 *) mem_addr = (u8) pdc_result[0];
- case 2: *(u16 *)mem_addr = (u16) pdc_result[0];
- case 4: *(u32 *)mem_addr = (u32) pdc_result[0];
+ case 1: *(u8 *) mem_addr = (u8) pdc_result[0]; break;
+ case 2: *(u16 *)mem_addr = (u16) pdc_result[0]; break;
+ case 4: *(u32 *)mem_addr = (u32) pdc_result[0]; break;
}
spin_unlock_irqrestore(&pdc_lock, flags);
diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
index a27e4928bf73..02d9ed0f3949 100644
--- a/arch/parisc/kernel/pci-dma.c
+++ b/arch/parisc/kernel/pci-dma.c
@@ -414,7 +414,7 @@ pcxl_dma_init(void)
__initcall(pcxl_dma_init);
static void *pa11_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
{
unsigned long vaddr;
unsigned long paddr;
@@ -441,7 +441,7 @@ static void *pa11_dma_alloc(struct device *dev, size_t size,
}
static void pa11_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
int order;
@@ -454,7 +454,7 @@ static void pa11_dma_free(struct device *dev, size_t size, void *vaddr,
static dma_addr_t pa11_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
void *addr = page_address(page) + offset;
BUG_ON(direction == DMA_NONE);
@@ -465,7 +465,7 @@ static dma_addr_t pa11_dma_map_page(struct device *dev, struct page *page,
static void pa11_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(direction == DMA_NONE);
@@ -484,7 +484,7 @@ static void pa11_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
@@ -503,7 +503,7 @@ static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static void pa11_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
@@ -577,11 +577,11 @@ struct dma_map_ops pcxl_dma_ops = {
};
static void *pcx_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
{
void *addr;
- if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs))
+ if ((attrs & DMA_ATTR_NON_CONSISTENT) == 0)
return NULL;
addr = (void *)__get_free_pages(flag, get_order(size));
@@ -592,7 +592,7 @@ static void *pcx_dma_alloc(struct device *dev, size_t size,
}
static void pcx_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t iova, struct dma_attrs *attrs)
+ dma_addr_t iova, unsigned long attrs)
{
free_pages((unsigned long)vaddr, get_order(size));
return;
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 31ec99a5f119..505cf1ac5af2 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -12,6 +12,7 @@
*/
#include <linux/errno.h>
#include <linux/module.h>
+#include <linux/rtc.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/param.h>
@@ -248,14 +249,47 @@ void __init start_cpu_itimer(void)
per_cpu(cpu_data, cpu).it_value = next_tick;
}
+#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pdc_tod tod_data;
+
+ memset(tm, 0, sizeof(*tm));
+ if (pdc_tod_read(&tod_data) < 0)
+ return -EOPNOTSUPP;
+
+ /* we treat tod_sec as unsigned, so this can work until year 2106 */
+ rtc_time64_to_tm(tod_data.tod_sec, tm);
+ return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+ time64_t secs = rtc_tm_to_time64(tm);
+
+ if (pdc_tod_set(secs, 0) < 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static const struct rtc_class_ops rtc_generic_ops = {
+ .read_time = rtc_generic_get_time,
+ .set_time = rtc_generic_set_time,
+};
+
static int __init rtc_init(void)
{
struct platform_device *pdev;
- pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+ pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+ &rtc_generic_ops,
+ sizeof(rtc_generic_ops));
+
return PTR_ERR_OR_ZERO(pdev);
}
device_initcall(rtc_init);
+#endif
void read_persistent_clock(struct timespec *ts)
{
diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c
index fb8e10a4fb39..eaffbb90aa14 100644
--- a/arch/parisc/lib/iomap.c
+++ b/arch/parisc/lib/iomap.c
@@ -125,22 +125,22 @@ static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
}
static const struct iomap_ops ioport_ops = {
- ioport_read8,
- ioport_read16,
- ioport_read16,
- ioport_read32,
- ioport_read32,
- ioport_write8,
- ioport_write16,
- ioport_write16,
- ioport_write32,
- ioport_write32,
- ioport_read8r,
- ioport_read16r,
- ioport_read32r,
- ioport_write8r,
- ioport_write16r,
- ioport_write32r,
+ .read8 = ioport_read8,
+ .read16 = ioport_read16,
+ .read16be = ioport_read16,
+ .read32 = ioport_read32,
+ .read32be = ioport_read32,
+ .write8 = ioport_write8,
+ .write16 = ioport_write16,
+ .write16be = ioport_write16,
+ .write32 = ioport_write32,
+ .write32be = ioport_write32,
+ .read8r = ioport_read8r,
+ .read16r = ioport_read16r,
+ .read32r = ioport_read32r,
+ .write8r = ioport_write8r,
+ .write16r = ioport_write16r,
+ .write32r = ioport_write32r,
};
/* Legacy I/O memory ops */
@@ -244,22 +244,22 @@ static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
}
static const struct iomap_ops iomem_ops = {
- iomem_read8,
- iomem_read16,
- iomem_read16be,
- iomem_read32,
- iomem_read32be,
- iomem_write8,
- iomem_write16,
- iomem_write16be,
- iomem_write32,
- iomem_write32be,
- iomem_read8r,
- iomem_read16r,
- iomem_read32r,
- iomem_write8r,
- iomem_write16r,
- iomem_write32r,
+ .read8 = iomem_read8,
+ .read16 = iomem_read16,
+ .read16be = iomem_read16be,
+ .read32 = iomem_read32,
+ .read32be = iomem_read32be,
+ .write8 = iomem_write8,
+ .write16 = iomem_write16,
+ .write16be = iomem_write16be,
+ .write32 = iomem_write32,
+ .write32be = iomem_write32be,
+ .read8r = iomem_read8r,
+ .read16r = iomem_read16r,
+ .read32r = iomem_read32r,
+ .write8r = iomem_write8r,
+ .write16r = iomem_write16r,
+ .write32r = iomem_write32r,
};
static const struct iomap_ops *iomap_ops[8] = {
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ec4047e170a0..927d2ab2ce08 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -166,6 +166,7 @@ config PPC
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
select GENERIC_CPU_AUTOPROBE
select HAVE_VIRT_CPU_ACCOUNTING
+ select HAVE_ARCH_HARDENED_USERCOPY
config GENERIC_CSUM
def_bool CPU_LITTLE_ENDIAN
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 171047822b56..63292f64b25a 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -60,6 +60,25 @@ config CODE_PATCHING_SELFTEST
depends on DEBUG_KERNEL
default n
+config JUMP_LABEL_FEATURE_CHECKS
+ bool "Enable use of jump label for cpu/mmu_has_feature()"
+ depends on JUMP_LABEL
+ default y
+ help
+ Selecting this options enables use of jump labels for some internal
+ feature checks. This should generate more optimal code for those
+ checks.
+
+config JUMP_LABEL_FEATURE_CHECK_DEBUG
+ bool "Do extra check on feature fixup calls"
+ depends on DEBUG_KERNEL && JUMP_LABEL_FEATURE_CHECKS
+ default n
+ help
+ This tries to catch incorrect usage of cpu_has_feature() and
+ mmu_has_feature() in the code.
+
+ If you don't know what this means, say N.
+
config FTR_FIXUP_SELFTEST
bool "Run self-tests of the feature-fixup code"
depends on DEBUG_KERNEL
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index ca254546cd05..1934707bf321 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -66,29 +66,28 @@ endif
UTS_MACHINE := $(OLDARCH)
ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
-override CC += -mlittle-endian
-ifneq ($(cc-name),clang)
-override CC += -mno-strict-align
-endif
-override AS += -mlittle-endian
override LD += -EL
-override CROSS32CC += -mlittle-endian
override CROSS32AS += -mlittle-endian
LDEMULATION := lppc
GNUTARGET := powerpcle
MULTIPLEWORD := -mno-multiple
KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-save-toc-indirect)
else
-ifeq ($(call cc-option-yn,-mbig-endian),y)
-override CC += -mbig-endian
-override AS += -mbig-endian
-endif
override LD += -EB
LDEMULATION := ppc
GNUTARGET := powerpc
MULTIPLEWORD := -mmultiple
endif
+cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian)
+cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian
+ifneq ($(cc-name),clang)
+ cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align
+endif
+
+aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian)
+aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian
+
ifeq ($(HAS_BIARCH),y)
override AS += -a$(CONFIG_WORD_SIZE)
override LD += -m elf$(CONFIG_WORD_SIZE)$(LDEMULATION)
@@ -232,6 +231,9 @@ cpu-as-$(CONFIG_E200) += -Wa,-me200
KBUILD_AFLAGS += $(cpu-as-y)
KBUILD_CFLAGS += $(cpu-as-y)
+KBUILD_AFLAGS += $(aflags-y)
+KBUILD_CFLAGS += $(cflags-y)
+
head-y := arch/powerpc/kernel/head_$(CONFIG_WORD_SIZE).o
head-$(CONFIG_8xx) := arch/powerpc/kernel/head_8xx.o
head-$(CONFIG_40x) := arch/powerpc/kernel/head_40x.o
diff --git a/arch/powerpc/crypto/crc32c-vpmsum_glue.c b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
index bfe3d37a24ef..9fa046d56eba 100644
--- a/arch/powerpc/crypto/crc32c-vpmsum_glue.c
+++ b/arch/powerpc/crypto/crc32c-vpmsum_glue.c
@@ -4,6 +4,7 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/kernel.h>
+#include <linux/cpufeature.h>
#include <asm/switch_to.h>
#define CHKSUM_BLOCK_SIZE 1
@@ -157,7 +158,7 @@ static void __exit crc32c_vpmsum_mod_fini(void)
crypto_unregister_shash(&alg);
}
-module_init(crc32c_vpmsum_mod_init);
+module_cpu_feature_match(PPC_MODULE_FEATURE_VEC_CRYPTO, crc32c_vpmsum_mod_init);
module_exit(crc32c_vpmsum_mod_fini);
MODULE_AUTHOR("Anton Blanchard <anton@samba.org>");
diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h b/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h
index 60f47649306f..c45189aa7476 100644
--- a/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h
@@ -11,4 +11,19 @@ extern unsigned long
radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags);
+
+static inline int hstate_get_psize(struct hstate *hstate)
+{
+ unsigned long shift;
+
+ shift = huge_page_shift(hstate);
+ if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
+ return MMU_PAGE_2M;
+ else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
+ return MMU_PAGE_1G;
+ else {
+ WARN(1, "Wrong huge page shift\n");
+ return mmu_virtual_psize;
+ }
+}
#endif
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index 5eaf86ac143d..287a656ceb57 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -24,6 +24,7 @@
#include <asm/book3s/64/pgtable.h>
#include <asm/bug.h>
#include <asm/processor.h>
+#include <asm/cpu_has_feature.h>
/*
* SLB
@@ -190,6 +191,15 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
BUG();
}
+static inline unsigned long get_sllp_encoding(int psize)
+{
+ unsigned long sllp;
+
+ sllp = ((mmu_psize_defs[psize].sllp & SLB_VSID_L) >> 6) |
+ ((mmu_psize_defs[psize].sllp & SLB_VSID_LP) >> 4);
+ return sllp;
+}
+
#endif /* __ASSEMBLY__ */
/*
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index d4eda6420523..8afb0e00f7d9 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -23,13 +23,6 @@ struct mmu_psize_def {
};
extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
-#ifdef CONFIG_PPC_RADIX_MMU
-#define radix_enabled() mmu_has_feature(MMU_FTR_RADIX)
-#else
-#define radix_enabled() (0)
-#endif
-
-
#endif /* __ASSEMBLY__ */
/* 64-bit classic hash table MMU */
@@ -107,6 +100,9 @@ extern int mmu_vmemmap_psize;
extern int mmu_io_psize;
/* MMU initialization */
+void mmu_early_init_devtree(void);
+void hash__early_init_devtree(void);
+void radix__early_init_devtree(void);
extern void radix_init_native(void);
extern void hash__early_init_mmu(void);
extern void radix__early_init_mmu(void);
@@ -132,11 +128,15 @@ extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
- if (radix_enabled())
+ if (early_radix_enabled())
return radix__setup_initial_memory_limit(first_memblock_base,
first_memblock_size);
return hash__setup_initial_memory_limit(first_memblock_base,
first_memblock_size);
}
+
+extern int (*register_process_table)(unsigned long base, unsigned long page_size,
+ unsigned long tbl_size);
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_BOOK3S_64_MMU_H_ */
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
index f12ddf5e8de5..2f6373144e2c 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h
@@ -75,11 +75,6 @@ static inline void hash__flush_tlb_page(struct vm_area_struct *vma,
{
}
-static inline void hash__flush_tlb_page_nohash(struct vm_area_struct *vma,
- unsigned long vmaddr)
-{
-}
-
static inline void hash__flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
index 00703e7e4c94..65037762b120 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
@@ -10,26 +10,32 @@ static inline int mmu_get_ap(int psize)
return mmu_psize_defs[psize].ap;
}
+extern void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
+ unsigned long end, int psize);
+extern void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
extern void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
- unsigned long ap, int nid);
extern void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
+extern void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
+ int psize);
extern void radix__tlb_flush(struct mmu_gather *tlb);
#ifdef CONFIG_SMP
extern void radix__flush_tlb_mm(struct mm_struct *mm);
extern void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
- unsigned long ap, int nid);
extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
+extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
+ int psize);
#else
#define radix__flush_tlb_mm(mm) radix__local_flush_tlb_mm(mm)
#define radix__flush_tlb_page(vma,addr) radix__local_flush_tlb_page(vma,addr)
-#define radix___flush_tlb_page(mm,addr,p,i) radix___local_flush_tlb_page(mm,addr,p,i)
+#define radix__flush_tlb_page_psize(mm,addr,p) radix__local_flush_tlb_page_psize(mm,addr,p)
#define radix__flush_tlb_pwc(tlb, addr) radix__local_flush_tlb_pwc(tlb, addr)
#endif
extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h
index 96e5769b18b0..72b925f97bab 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h
@@ -7,6 +7,25 @@
#include <asm/book3s/64/tlbflush-hash.h>
#include <asm/book3s/64/tlbflush-radix.h>
+#define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
+static inline void flush_pmd_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ if (radix_enabled())
+ return radix__flush_pmd_tlb_range(vma, start, end);
+ return hash__flush_tlb_range(vma, start, end);
+}
+
+#define __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
+static inline void flush_hugetlb_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
+{
+ if (radix_enabled())
+ return radix__flush_hugetlb_tlb_range(vma, start, end);
+ return hash__flush_tlb_range(vma, start, end);
+}
+
static inline void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
@@ -38,14 +57,6 @@ static inline void local_flush_tlb_page(struct vm_area_struct *vma,
return hash__local_flush_tlb_page(vma, vmaddr);
}
-static inline void flush_tlb_page_nohash(struct vm_area_struct *vma,
- unsigned long vmaddr)
-{
- if (radix_enabled())
- return radix__flush_tlb_page(vma, vmaddr);
- return hash__flush_tlb_page_nohash(vma, vmaddr);
-}
-
static inline void tlb_flush(struct mmu_gather *tlb)
{
if (radix_enabled())
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index 69fb16d7a811..b77f0364df94 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -11,6 +11,7 @@
#include <linux/mm.h>
#include <asm/cputable.h>
+#include <asm/cpu_has_feature.h>
/*
* No cache flushing is required when address mappings are changed,
diff --git a/arch/powerpc/include/asm/cpu_has_feature.h b/arch/powerpc/include/asm/cpu_has_feature.h
new file mode 100644
index 000000000000..2ef55f8968a2
--- /dev/null
+++ b/arch/powerpc/include/asm/cpu_has_feature.h
@@ -0,0 +1,53 @@
+#ifndef __ASM_POWERPC_CPUFEATURES_H
+#define __ASM_POWERPC_CPUFEATURES_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/bug.h>
+#include <asm/cputable.h>
+
+static inline bool early_cpu_has_feature(unsigned long feature)
+{
+ return !!((CPU_FTRS_ALWAYS & feature) ||
+ (CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
+}
+
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
+#include <linux/jump_label.h>
+
+#define NUM_CPU_FTR_KEYS 64
+
+extern struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS];
+
+static __always_inline bool cpu_has_feature(unsigned long feature)
+{
+ int i;
+
+ BUILD_BUG_ON(!__builtin_constant_p(feature));
+
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
+ if (!static_key_initialized) {
+ printk("Warning! cpu_has_feature() used prior to jump label init!\n");
+ dump_stack();
+ return early_cpu_has_feature(feature);
+ }
+#endif
+
+ if (CPU_FTRS_ALWAYS & feature)
+ return true;
+
+ if (!(CPU_FTRS_POSSIBLE & feature))
+ return false;
+
+ i = __builtin_ctzl(feature);
+ return static_branch_likely(&cpu_feature_keys[i]);
+}
+#else
+static inline bool cpu_has_feature(unsigned long feature)
+{
+ return early_cpu_has_feature(feature);
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_POWERPC_CPUFEATURE_H */
diff --git a/arch/powerpc/include/asm/cpuidle.h b/arch/powerpc/include/asm/cpuidle.h
index 3d7fc06532a1..01b8a13f0224 100644
--- a/arch/powerpc/include/asm/cpuidle.h
+++ b/arch/powerpc/include/asm/cpuidle.h
@@ -19,4 +19,17 @@ extern u64 pnv_first_deep_stop_state;
#endif
+/* Idle state entry routines */
+#ifdef CONFIG_PPC_P7_NAP
+#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
+ /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
+ std r0,0(r1); \
+ ptesync; \
+ ld r0,0(r1); \
+1: cmp cr0,r0,r0; \
+ bne 1b; \
+ IDLE_INST; \
+ b .
+#endif /* CONFIG_PPC_P7_NAP */
+
#endif
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index df4fb5faba43..82026b419341 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -2,6 +2,7 @@
#define __ASM_POWERPC_CPUTABLE_H
+#include <linux/types.h>
#include <asm/asm-compat.h>
#include <asm/feature-fixups.h>
#include <uapi/asm/cputable.h>
@@ -122,6 +123,12 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
extern const char *powerpc_base_platform;
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
+extern void cpu_feature_keys_init(void);
+#else
+static inline void cpu_feature_keys_init(void) { }
+#endif
+
/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */
enum {
TLB_INVAL_SCOPE_GLOBAL = 0, /* invalidate all TLBs */
@@ -576,14 +583,6 @@ enum {
};
#endif /* __powerpc64__ */
-static inline int cpu_has_feature(unsigned long feature)
-{
- return (CPU_FTRS_ALWAYS & feature) ||
- (CPU_FTRS_POSSIBLE
- & cur_cpu_spec->cpu_features
- & feature);
-}
-
#define HBP_NUM 1
#endif /* !__ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h
index 2dfd4fc41f3e..4f60db074725 100644
--- a/arch/powerpc/include/asm/cputime.h
+++ b/arch/powerpc/include/asm/cputime.h
@@ -28,6 +28,7 @@ static inline void setup_cputime_one_jiffy(void) { }
#include <asm/div64.h>
#include <asm/time.h>
#include <asm/param.h>
+#include <asm/cpu_has_feature.h>
typedef u64 __nocast cputime_t;
typedef u64 __nocast cputime64_t;
diff --git a/arch/powerpc/include/asm/dbell.h b/arch/powerpc/include/asm/dbell.h
index 5fa6b20eba10..378167377065 100644
--- a/arch/powerpc/include/asm/dbell.h
+++ b/arch/powerpc/include/asm/dbell.h
@@ -16,6 +16,7 @@
#include <linux/threads.h>
#include <asm/ppc-opcode.h>
+#include <asm/cpu_has_feature.h>
#define PPC_DBELL_MSG_BRDCAST (0x04000000)
#define PPC_DBELL_TYPE(x) (((x) & 0xf) << (63-36))
diff --git a/arch/powerpc/include/asm/dcr-native.h b/arch/powerpc/include/asm/dcr-native.h
index 4efc11dacb98..4a2beef74277 100644
--- a/arch/powerpc/include/asm/dcr-native.h
+++ b/arch/powerpc/include/asm/dcr-native.h
@@ -24,6 +24,7 @@
#include <linux/spinlock.h>
#include <asm/cputable.h>
+#include <asm/cpu_has_feature.h>
typedef struct {
unsigned int base;
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 77816acd4fd9..84e3f8dd5e4f 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -13,7 +13,6 @@
/* need struct page definitions */
#include <linux/mm.h>
#include <linux/scatterlist.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-debug.h>
#include <asm/io.h>
#include <asm/swiotlb.h>
@@ -25,14 +24,14 @@
/* Some dma direct funcs must be visible for use in other dma_ops */
extern void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void __dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern int dma_direct_mmap_coherent(struct device *dev,
struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t handle,
- size_t size, struct dma_attrs *attrs);
+ size_t size, unsigned long attrs);
#ifdef CONFIG_NOT_COHERENT_CACHE
/*
diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h
index 57fec8ac7b92..ddf54f5bbdd1 100644
--- a/arch/powerpc/include/asm/feature-fixups.h
+++ b/arch/powerpc/include/asm/feature-fixups.h
@@ -186,6 +186,7 @@ label##3: \
#ifndef __ASSEMBLY__
void apply_feature_fixups(void);
+void setup_feature_keys(void);
#endif
#endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index e2d9f4996e5c..c5517f463ec7 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -147,7 +147,7 @@ static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
{
pte_t pte;
pte = huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
- flush_tlb_page(vma, addr);
+ flush_hugetlb_page(vma, addr);
}
static inline int huge_pte_none(pte_t pte)
diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h
index f49a72a9062d..2c1d50792944 100644
--- a/arch/powerpc/include/asm/iommu.h
+++ b/arch/powerpc/include/asm/iommu.h
@@ -53,7 +53,7 @@ struct iommu_table_ops {
long index, long npages,
unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
#ifdef CONFIG_IOMMU_API
/*
* Exchanges existing TCE with new TCE plus direction bits;
@@ -248,12 +248,12 @@ extern int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
unsigned long mask,
enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void ppc_iommu_unmap_sg(struct iommu_table *tbl,
struct scatterlist *sglist,
int nelems,
enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
size_t size, dma_addr_t *dma_handle,
@@ -264,10 +264,10 @@ extern dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
struct page *page, unsigned long offset,
size_t size, unsigned long mask,
enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void iommu_init_early_pSeries(void);
extern void iommu_init_early_dart(struct pci_controller_ops *controller_ops);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 47e155f15433..9a287e0ac8b1 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <asm/feature-fixups.h>
+#include <asm/asm-compat.h>
#define JUMP_ENTRY_TYPE stringify_in_c(FTR_ENTRY_LONG)
#define JUMP_LABEL_NOP_SIZE 4
@@ -21,7 +22,7 @@
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
{
asm_volatile_goto("1:\n\t"
- "nop\n\t"
+ "nop # arch_static_branch\n\t"
".pushsection __jump_table, \"aw\"\n\t"
JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
".popsection \n\t"
@@ -35,7 +36,7 @@ l_yes:
static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
{
asm_volatile_goto("1:\n\t"
- "b %l[l_yes]\n\t"
+ "b %l[l_yes] # arch_static_branch_jump\n\t"
".pushsection __jump_table, \"aw\"\n\t"
JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
".popsection \n\t"
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 1f4497fb5b83..88d17b4ea9c8 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -181,8 +181,7 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
switch (b_psize) {
case MMU_PAGE_4K:
- sllp = ((mmu_psize_defs[a_psize].sllp & SLB_VSID_L) >> 6) |
- ((mmu_psize_defs[a_psize].sllp & SLB_VSID_LP) >> 4);
+ sllp = get_sllp_encoding(a_psize);
rb |= sllp << 5; /* AP field */
rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */
break;
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 76f5398e7152..0420b388dd83 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -219,8 +219,6 @@ struct machdep_calls {
#ifdef CONFIG_ARCH_RANDOM
int (*get_random_seed)(unsigned long *v);
#endif
- int (*register_process_table)(unsigned long base, unsigned long page_size,
- unsigned long tbl_size);
};
extern void e500_idle(void);
diff --git a/arch/powerpc/include/asm/mman.h b/arch/powerpc/include/asm/mman.h
index fc420cedecae..30922f699341 100644
--- a/arch/powerpc/include/asm/mman.h
+++ b/arch/powerpc/include/asm/mman.h
@@ -13,6 +13,7 @@
#include <asm/cputable.h>
#include <linux/mm.h>
+#include <asm/cpu_has_feature.h>
/*
* This file is included by linux/mman.h, so we can't use cacl_vm_prot_bits()
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 54471228f7b8..e2fb408f8398 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -12,7 +12,7 @@
*/
/*
- * First half is MMU families
+ * MMU families
*/
#define MMU_FTR_HPTE_TABLE ASM_CONST(0x00000001)
#define MMU_FTR_TYPE_8xx ASM_CONST(0x00000002)
@@ -21,9 +21,13 @@
#define MMU_FTR_TYPE_FSL_E ASM_CONST(0x00000010)
#define MMU_FTR_TYPE_47x ASM_CONST(0x00000020)
+/* Radix page table supported and enabled */
+#define MMU_FTR_TYPE_RADIX ASM_CONST(0x00000040)
+
/*
- * This is individual features
+ * Individual features below.
*/
+
/*
* We need to clear top 16bits of va (from the remaining 64 bits )in
* tlbie* instructions
@@ -93,11 +97,6 @@
*/
#define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000)
-/*
- * Radix page table available
- */
-#define MMU_FTR_RADIX ASM_CONST(0x80000000)
-
/* MMU feature bit sets for various CPUs */
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \
MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
@@ -113,6 +112,7 @@
#define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \
MMU_FTR_CI_LARGE_PAGE | MMU_FTR_NO_SLBIE_B
#ifndef __ASSEMBLY__
+#include <linux/bug.h>
#include <asm/cputable.h>
#ifdef CONFIG_PPC_FSL_BOOK3E
@@ -131,20 +131,71 @@ enum {
MMU_FTR_LOCKLESS_TLBIE | MMU_FTR_CI_LARGE_PAGE |
MMU_FTR_1T_SEGMENT | MMU_FTR_TLBIE_CROP_VA |
#ifdef CONFIG_PPC_RADIX_MMU
- MMU_FTR_RADIX |
+ MMU_FTR_TYPE_RADIX |
#endif
0,
};
-static inline int mmu_has_feature(unsigned long feature)
+static inline bool early_mmu_has_feature(unsigned long feature)
{
- return (MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature);
+ return !!(MMU_FTRS_POSSIBLE & cur_cpu_spec->mmu_features & feature);
+}
+
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
+#include <linux/jump_label.h>
+
+#define NUM_MMU_FTR_KEYS 32
+
+extern struct static_key_true mmu_feature_keys[NUM_MMU_FTR_KEYS];
+
+extern void mmu_feature_keys_init(void);
+
+static __always_inline bool mmu_has_feature(unsigned long feature)
+{
+ int i;
+
+ BUILD_BUG_ON(!__builtin_constant_p(feature));
+
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
+ if (!static_key_initialized) {
+ printk("Warning! mmu_has_feature() used prior to jump label init!\n");
+ dump_stack();
+ return early_mmu_has_feature(feature);
+ }
+#endif
+
+ if (!(MMU_FTRS_POSSIBLE & feature))
+ return false;
+
+ i = __builtin_ctzl(feature);
+ return static_branch_likely(&mmu_feature_keys[i]);
}
static inline void mmu_clear_feature(unsigned long feature)
{
+ int i;
+
+ i = __builtin_ctzl(feature);
cur_cpu_spec->mmu_features &= ~feature;
+ static_branch_disable(&mmu_feature_keys[i]);
}
+#else
+
+static inline void mmu_feature_keys_init(void)
+{
+
+}
+
+static inline bool mmu_has_feature(unsigned long feature)
+{
+ return early_mmu_has_feature(feature);
+}
+
+static inline void mmu_clear_feature(unsigned long feature)
+{
+ cur_cpu_spec->mmu_features &= ~feature;
+}
+#endif /* CONFIG_JUMP_LABEL */
extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup;
@@ -164,6 +215,28 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
}
#endif /* !CONFIG_DEBUG_VM */
+#ifdef CONFIG_PPC_RADIX_MMU
+static inline bool radix_enabled(void)
+{
+ return mmu_has_feature(MMU_FTR_TYPE_RADIX);
+}
+
+static inline bool early_radix_enabled(void)
+{
+ return early_mmu_has_feature(MMU_FTR_TYPE_RADIX);
+}
+#else
+static inline bool radix_enabled(void)
+{
+ return false;
+}
+
+static inline bool early_radix_enabled(void)
+{
+ return false;
+}
+#endif
+
#endif /* !__ASSEMBLY__ */
/* The kernel use the constants below to index in the page sizes array.
@@ -210,6 +283,7 @@ extern void early_init_mmu(void);
extern void early_init_mmu_secondary(void);
extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size);
+static inline void mmu_early_init_devtree(void) { }
#endif /* __ASSEMBLY__ */
#endif
@@ -230,9 +304,5 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
# include <asm/mmu-8xx.h>
#endif
-#ifndef radix_enabled
-#define radix_enabled() (0)
-#endif
-
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_MMU_H_ */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 40f3615bf940..f69f40f1519a 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1256,15 +1256,6 @@ static inline void msr_check_and_clear(unsigned long bits)
__msr_check_and_clear(bits);
}
-static inline unsigned long mfvtb (void)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
- if (cpu_has_feature(CPU_FTR_ARCH_207S))
- return mfspr(SPRN_VTB);
-#endif
- return 0;
-}
-
#ifdef __powerpc64__
#if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E)
#define mftb() ({unsigned long rval; \
diff --git a/arch/powerpc/include/asm/rtc.h b/arch/powerpc/include/asm/rtc.h
deleted file mode 100644
index f5802926b6c0..000000000000
--- a/arch/powerpc/include/asm/rtc.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Real-time clock definitions and interfaces
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * 2002 (c) MontaVista, Software, Inc. 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.
- *
- * Based on:
- * include/asm-m68k/rtc.h
- *
- * Copyright Richard Zidlicky
- * implementation details for genrtc/q40rtc driver
- *
- * And the old drivers/macintosh/rtc.c which was heavily based on:
- * Linux/SPARC Real Time Clock Driver
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
- *
- * With additional work by Paul Mackerras and Franz Sirl.
- */
-
-#ifndef __ASM_POWERPC_RTC_H__
-#define __ASM_POWERPC_RTC_H__
-
-#ifdef __KERNEL__
-
-#include <linux/rtc.h>
-
-#include <asm/machdep.h>
-#include <asm/time.h>
-
-#define RTC_PIE 0x40 /* periodic interrupt enable */
-#define RTC_AIE 0x20 /* alarm interrupt enable */
-#define RTC_UIE 0x10 /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100 /* battery bad */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-static inline unsigned int get_rtc_time(struct rtc_time *time)
-{
- if (ppc_md.get_rtc_time)
- ppc_md.get_rtc_time(time);
- return RTC_24H;
-}
-
-/* Set the current date and time in the real time clock. */
-static inline int set_rtc_time(struct rtc_time *time)
-{
- if (ppc_md.set_rtc_time)
- return ppc_md.set_rtc_time(time);
- return -EINVAL;
-}
-
-static inline unsigned int get_rtc_ss(void)
-{
- struct rtc_time h;
-
- get_rtc_time(&h);
- return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-
-#endif /* __KERNEL__ */
-#endif /* __ASM_POWERPC_RTC_H__ */
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index 09211640a0e0..b240666b7bc1 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -18,6 +18,7 @@
#include <linux/percpu.h>
#include <asm/processor.h>
+#include <asm/cpu_has_feature.h>
/* time.c */
extern unsigned long tb_ticks_per_jiffy;
@@ -103,7 +104,7 @@ static inline u64 get_vtb(void)
{
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_ARCH_207S))
- return mfvtb();
+ return mfspr(SPRN_VTB);
#endif
return 0;
}
diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h
index 20733fa518ae..f6f68f73e858 100644
--- a/arch/powerpc/include/asm/tlb.h
+++ b/arch/powerpc/include/asm/tlb.h
@@ -46,5 +46,18 @@ static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
#endif
}
+#ifdef CONFIG_SMP
+static inline int mm_is_core_local(struct mm_struct *mm)
+{
+ return cpumask_subset(mm_cpumask(mm),
+ topology_sibling_cpumask(smp_processor_id()));
+}
+#else
+static inline int mm_is_core_local(struct mm_struct *mm)
+{
+ return 1;
+}
+#endif
+
#endif /* __KERNEL__ */
#endif /* __ASM_POWERPC_TLB_H */
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h
index 1b38eea28e5a..13dbcd41885e 100644
--- a/arch/powerpc/include/asm/tlbflush.h
+++ b/arch/powerpc/include/asm/tlbflush.h
@@ -54,7 +54,6 @@ extern void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
#define flush_tlb_page(vma,addr) local_flush_tlb_page(vma,addr)
#define __flush_tlb_page(mm,addr,p,i) __local_flush_tlb_page(mm,addr,p,i)
#endif
-#define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr)
#elif defined(CONFIG_PPC_STD_MMU_32)
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index b7c20f0b8fbe..c1dc6c14deb8 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -310,10 +310,15 @@ static inline unsigned long copy_from_user(void *to,
{
unsigned long over;
- if (access_ok(VERIFY_READ, from, n))
+ if (access_ok(VERIFY_READ, from, n)) {
+ if (!__builtin_constant_p(n))
+ check_object_size(to, n, false);
return __copy_tofrom_user((__force void __user *)to, from, n);
+ }
if ((unsigned long)from < TASK_SIZE) {
over = (unsigned long)from + n - TASK_SIZE;
+ if (!__builtin_constant_p(n - over))
+ check_object_size(to, n - over, false);
return __copy_tofrom_user((__force void __user *)to, from,
n - over) + over;
}
@@ -325,10 +330,15 @@ static inline unsigned long copy_to_user(void __user *to,
{
unsigned long over;
- if (access_ok(VERIFY_WRITE, to, n))
+ if (access_ok(VERIFY_WRITE, to, n)) {
+ if (!__builtin_constant_p(n))
+ check_object_size(from, n, true);
return __copy_tofrom_user(to, (__force void __user *)from, n);
+ }
if ((unsigned long)to < TASK_SIZE) {
over = (unsigned long)to + n - TASK_SIZE;
+ if (!__builtin_constant_p(n))
+ check_object_size(from, n - over, true);
return __copy_tofrom_user(to, (__force void __user *)from,
n - over) + over;
}
@@ -372,6 +382,10 @@ static inline unsigned long __copy_from_user_inatomic(void *to,
if (ret == 0)
return 0;
}
+
+ if (!__builtin_constant_p(n))
+ check_object_size(to, n, false);
+
return __copy_tofrom_user((__force void __user *)to, from, n);
}
@@ -398,6 +412,9 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to,
if (ret == 0)
return 0;
}
+ if (!__builtin_constant_p(n))
+ check_object_size(from, n, true);
+
return __copy_tofrom_user(to, (__force const void __user *)from, n);
}
diff --git a/arch/powerpc/include/asm/xics.h b/arch/powerpc/include/asm/xics.h
index f5f729c11578..f0b238516e9b 100644
--- a/arch/powerpc/include/asm/xics.h
+++ b/arch/powerpc/include/asm/xics.h
@@ -159,6 +159,8 @@ extern void xics_teardown_cpu(void);
extern void xics_kexec_teardown_cpu(int secondary);
extern void xics_migrate_irqs_away(void);
extern void icp_native_eoi(struct irq_data *d);
+extern int xics_set_irq_type(struct irq_data *d, unsigned int flow_type);
+extern int xics_retrigger(struct irq_data *data);
#ifdef CONFIG_SMP
extern int xics_get_irq_server(unsigned int virq, const struct cpumask *cpumask,
unsigned int strict_check);
diff --git a/arch/powerpc/include/asm/xor.h b/arch/powerpc/include/asm/xor.h
index 0abb97f3be10..a36c2069d8ed 100644
--- a/arch/powerpc/include/asm/xor.h
+++ b/arch/powerpc/include/asm/xor.h
@@ -23,6 +23,7 @@
#ifdef CONFIG_ALTIVEC
#include <asm/cputable.h>
+#include <asm/cpu_has_feature.h>
void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
unsigned long *v2_in);
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index c2d21d11c2d2..3a9e44c45c78 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -91,6 +91,11 @@
#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */
#define ELF_NFPREG 33 /* includes fpscr */
+#define ELF_NVMX 34 /* includes all vector registers */
+#define ELF_NVSX 32 /* includes all VSX registers */
+#define ELF_NTMSPRREG 3 /* include tfhar, tfiar, texasr */
+#define ELF_NEBB 3 /* includes ebbrr, ebbhr, bescr */
+#define ELF_NPMU 5 /* includes siar, sdar, sier, mmcr2, mmcr0 */
typedef unsigned long elf_greg_t64;
typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index c7097f933114..033f3385fa49 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -26,6 +26,7 @@
#include <asm/emulated_ops.h>
#include <asm/switch_to.h>
#include <asm/disassemble.h>
+#include <asm/cpu_has_feature.h>
struct aligninfo {
unsigned char len;
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index d81f826d1029..74248ab18e98 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -15,6 +15,7 @@
#include <linux/threads.h>
#include <linux/init.h>
#include <linux/export.h>
+#include <linux/jump_label.h>
#include <asm/oprofile_impl.h>
#include <asm/cputable.h>
@@ -2224,3 +2225,39 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
return NULL;
}
+
+#ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
+struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS] = {
+ [0 ... NUM_CPU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT
+};
+EXPORT_SYMBOL_GPL(cpu_feature_keys);
+
+void __init cpu_feature_keys_init(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_CPU_FTR_KEYS; i++) {
+ unsigned long f = 1ul << i;
+
+ if (!(cur_cpu_spec->cpu_features & f))
+ static_branch_disable(&cpu_feature_keys[i]);
+ }
+}
+
+struct static_key_true mmu_feature_keys[NUM_MMU_FTR_KEYS] = {
+ [0 ... NUM_MMU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT
+};
+EXPORT_SYMBOL_GPL(mmu_feature_keys);
+
+void __init mmu_feature_keys_init(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_MMU_FTR_KEYS; i++) {
+ unsigned long f = 1ul << i;
+
+ if (!(cur_cpu_spec->mmu_features & f))
+ static_branch_disable(&mmu_feature_keys[i]);
+ }
+}
+#endif
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 41a7d9d49a5a..fb7cbaa37658 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -18,7 +18,7 @@
*/
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
dma_handle, dev->coherent_dma_mask, flag,
@@ -27,7 +27,7 @@ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
static void dma_iommu_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
}
@@ -40,7 +40,7 @@ static void dma_iommu_free_coherent(struct device *dev, size_t size,
static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return iommu_map_page(dev, get_iommu_table_base(dev), page, offset,
size, device_to_mask(dev), direction, attrs);
@@ -49,7 +49,7 @@ static dma_addr_t dma_iommu_map_page(struct device *dev, struct page *page,
static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
iommu_unmap_page(get_iommu_table_base(dev), dma_handle, size, direction,
attrs);
@@ -58,7 +58,7 @@ static void dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return ppc_iommu_map_sg(dev, get_iommu_table_base(dev), sglist, nelems,
device_to_mask(dev), direction, attrs);
@@ -66,7 +66,7 @@ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
static void dma_iommu_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
ppc_iommu_unmap_sg(get_iommu_table_base(dev), sglist, nelems,
direction, attrs);
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 3f1472a78f39..e64a6016fba7 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -64,7 +64,7 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask)
void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
#ifdef CONFIG_NOT_COHERENT_CACHE
@@ -121,7 +121,7 @@ void *__dma_direct_alloc_coherent(struct device *dev, size_t size,
void __dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
#ifdef CONFIG_NOT_COHERENT_CACHE
__dma_free_coherent(size, vaddr);
@@ -132,7 +132,7 @@ void __dma_direct_free_coherent(struct device *dev, size_t size,
static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu_table *iommu;
@@ -156,7 +156,7 @@ static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
static void dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu_table *iommu;
@@ -177,7 +177,7 @@ static void dma_direct_free_coherent(struct device *dev, size_t size,
int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t handle, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long pfn;
@@ -195,7 +195,7 @@ int dma_direct_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -211,7 +211,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
static void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
}
@@ -232,7 +232,7 @@ static inline dma_addr_t dma_direct_map_page(struct device *dev,
unsigned long offset,
size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(dir == DMA_NONE);
__dma_sync_page(page, offset, size, dir);
@@ -243,7 +243,7 @@ static inline void dma_direct_unmap_page(struct device *dev,
dma_addr_t dma_address,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
}
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index c9bc78e9c610..7429556eb8df 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -168,10 +168,10 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
int n = 0, l = 0;
char buffer[128];
- n += scnprintf(buf+n, len-n, "%04x:%02x:%02x:%01x\n",
+ n += scnprintf(buf+n, len-n, "%04x:%02x:%02x.%01x\n",
edev->phb->global_number, pdn->busno,
PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
- pr_warn("EEH: of node=%04x:%02x:%02x:%01x\n",
+ pr_warn("EEH: of node=%04x:%02x:%02x.%01x\n",
edev->phb->global_number, pdn->busno,
PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index fcb2887f5a33..6b8bc0dd09d4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -532,7 +532,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
#ifdef CONFIG_PPC_STD_MMU_64
BEGIN_MMU_FTR_SECTION
b 2f
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
BEGIN_FTR_SECTION
clrrdi r6,r8,28 /* get its ESID */
clrrdi r9,r1,28 /* get current sp ESID */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 694def6c9d61..df6d45eb4115 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -144,29 +144,14 @@ machine_check_pSeries_1:
* vector
*/
SET_SCRATCH0(r13) /* save r13 */
-#ifdef CONFIG_PPC_P7_NAP
-BEGIN_FTR_SECTION
- /* Running native on arch 2.06 or later, check if we are
- * waking up from nap. We only handle no state loss and
- * supervisor state loss. We do -not- handle hypervisor
- * state loss at this time.
+ /*
+ * Running native on arch 2.06 or later, we may wakeup from winkle
+ * inside machine check. If yes, then last bit of HSPGR0 would be set
+ * to 1. Hence clear it unconditionally.
*/
- mfspr r13,SPRN_SRR1
- rlwinm. r13,r13,47-31,30,31
- OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
- beq 9f
-
- mfspr r13,SPRN_SRR1
- rlwinm. r13,r13,47-31,30,31
- /* waking up from powersave (nap) state */
- cmpwi cr1,r13,2
- /* Total loss of HV state is fatal. let's just stay stuck here */
- OPT_GET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
- bgt cr1,.
-9:
- OPT_SET_SPR(r13, SPRN_CFAR, CPU_FTR_CFAR)
-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
-#endif /* CONFIG_PPC_P7_NAP */
+ GET_PACA(r13)
+ clrrdi r13,r13,1
+ SET_PACA(r13)
EXCEPTION_PROLOG_0(PACA_EXMC)
BEGIN_FTR_SECTION
b machine_check_powernv_early
@@ -940,7 +925,7 @@ BEGIN_MMU_FTR_SECTION
b do_hash_page /* Try to handle as hpte fault */
MMU_FTR_SECTION_ELSE
b handle_page_fault
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
.align 7
.globl h_data_storage_common
@@ -971,7 +956,7 @@ BEGIN_MMU_FTR_SECTION
b do_hash_page /* Try to handle as hpte fault */
MMU_FTR_SECTION_ELSE
b handle_page_fault
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception)
@@ -1273,25 +1258,51 @@ machine_check_handle_early:
* Check if thread was in power saving mode. We come here when any
* of the following is true:
* a. thread wasn't in power saving mode
- * b. thread was in power saving mode with no state loss or
- * supervisor state loss
+ * b. thread was in power saving mode with no state loss,
+ * supervisor state loss or hypervisor state loss.
*
- * Go back to nap again if (b) is true.
+ * Go back to nap/sleep/winkle mode again if (b) is true.
*/
rlwinm. r11,r12,47-31,30,31 /* Was it in power saving mode? */
beq 4f /* No, it wasn;t */
/* Thread was in power saving mode. Go back to nap again. */
cmpwi r11,2
- bne 3f
- /* Supervisor state loss */
+ blt 3f
+ /* Supervisor/Hypervisor state loss */
li r0,1
stb r0,PACA_NAPSTATELOST(r13)
3: bl machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
GET_PACA(r13)
ld r1,PACAR1(r13)
- li r3,PNV_THREAD_NAP
- b pnv_enter_arch207_idle_mode
+ /*
+ * Check what idle state this CPU was in and go back to same mode
+ * again.
+ */
+ lbz r3,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi r3,PNV_THREAD_NAP
+ bgt 10f
+ IDLE_STATE_ENTER_SEQ(PPC_NAP)
+ /* No return */
+10:
+ cmpwi r3,PNV_THREAD_SLEEP
+ bgt 2f
+ IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
+ /* No return */
+
+2:
+ /*
+ * Go back to winkle. Please note that this thread was woken up in
+ * machine check from winkle and have not restored the per-subcore
+ * state. Hence before going back to winkle, set last bit of HSPGR0
+ * to 1. This will make sure that if this thread gets woken up
+ * again at reset vector 0x100 then it will get chance to restore
+ * the subcore state.
+ */
+ ori r13,r13,1
+ SET_PACA(r13)
+ IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
+ /* No return */
4:
#endif
/*
@@ -1392,7 +1403,7 @@ slb_miss_realmode:
#ifdef CONFIG_PPC_STD_MMU_64
BEGIN_MMU_FTR_SECTION
bl slb_allocate_realmode
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_RADIX)
+END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX)
#endif
/* All done -- return from exception. */
@@ -1406,7 +1417,7 @@ BEGIN_MMU_FTR_SECTION
beq- 2f
FTR_SECTION_ELSE
b 2f
-ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_RADIX)
+ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
.machine push
.machine "power4"
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index a89f4f7a66bd..c1ca9282f4a0 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -65,7 +65,7 @@ static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *mem;
@@ -78,7 +78,7 @@ static void *ibmebus_alloc_coherent(struct device *dev,
static void ibmebus_free_coherent(struct device *dev,
size_t size, void *vaddr,
dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
kfree(vaddr);
}
@@ -88,7 +88,7 @@ static dma_addr_t ibmebus_map_page(struct device *dev,
unsigned long offset,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return (dma_addr_t)(page_address(page) + offset);
}
@@ -97,7 +97,7 @@ static void ibmebus_unmap_page(struct device *dev,
dma_addr_t dma_addr,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return;
}
@@ -105,7 +105,7 @@ static void ibmebus_unmap_page(struct device *dev,
static int ibmebus_map_sg(struct device *dev,
struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -121,7 +121,7 @@ static int ibmebus_map_sg(struct device *dev,
static void ibmebus_unmap_sg(struct device *dev,
struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return;
}
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index 8a56a51fc0cb..2265c6398a17 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -44,18 +44,6 @@
PSSCR_PSLL_MASK | PSSCR_TR_MASK | \
PSSCR_MTL_MASK
-/* Idle state entry routines */
-
-#define IDLE_STATE_ENTER_SEQ(IDLE_INST) \
- /* Magic NAP/SLEEP/WINKLE mode enter sequence */ \
- std r0,0(r1); \
- ptesync; \
- ld r0,0(r1); \
-1: cmp cr0,r0,r0; \
- bne 1b; \
- IDLE_INST; \
- b .
-
.text
/*
@@ -363,8 +351,8 @@ _GLOBAL(power9_idle_stop)
* cr3 - set to gt if waking up with partial/complete hypervisor state loss
*/
_GLOBAL(pnv_restore_hyp_resource)
- ld r2,PACATOC(r13);
BEGIN_FTR_SECTION
+ ld r2,PACATOC(r13);
/*
* POWER ISA 3. Use PSSCR to determine if we
* are waking up from deep idle state
@@ -395,6 +383,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
*/
clrldi r5,r13,63
clrrdi r13,r13,1
+
+ /* Now that we are sure r13 is corrected, load TOC */
+ ld r2,PACATOC(r13);
cmpwi cr4,r5,1
mtspr SPRN_HSPRG0,r13
@@ -572,7 +563,7 @@ common_exit:
BEGIN_MMU_FTR_SECTION
b no_segments
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_RADIX)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
/* Restore SLB from PACA */
ld r8,PACA_SLBSHADOWPTR(r13)
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index a8e3490b54e3..37d6e741be82 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -307,7 +307,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
void *page, unsigned int npages,
enum dma_data_direction direction,
unsigned long mask, unsigned int align_order,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long entry;
dma_addr_t ret = DMA_ERROR_CODE;
@@ -431,7 +431,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
struct scatterlist *sglist, int nelems,
unsigned long mask, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t dma_next = 0, dma_addr;
struct scatterlist *s, *outs, *segstart;
@@ -574,7 +574,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl,
void ppc_iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
@@ -753,7 +753,7 @@ void iommu_free_table(struct iommu_table *tbl, const char *node_name)
dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
struct page *page, unsigned long offset, size_t size,
unsigned long mask, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t dma_handle = DMA_ERROR_CODE;
void *vaddr;
@@ -790,7 +790,7 @@ dma_addr_t iommu_map_page(struct device *dev, struct iommu_table *tbl,
void iommu_unmap_page(struct iommu_table *tbl, dma_addr_t dma_handle,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned int npages;
@@ -845,7 +845,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
nio_pages = size >> tbl->it_page_shift;
io_order = get_iommu_order(size, tbl);
mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
- mask >> tbl->it_page_shift, io_order, NULL);
+ mask >> tbl->it_page_shift, io_order, 0);
if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order);
return NULL;
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index ac910d9982df..08887cf2b20e 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -75,6 +75,7 @@
#endif
#define CREATE_TRACE_POINTS
#include <asm/trace.h>
+#include <asm/cpu_has_feature.h>
DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
EXPORT_PER_CPU_SYMBOL(irq_stat);
diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
index ef267fd9dd22..5e7ece0fda9f 100644
--- a/arch/powerpc/kernel/mce.c
+++ b/arch/powerpc/kernel/mce.c
@@ -92,7 +92,8 @@ void save_mce_event(struct pt_regs *regs, long handled,
mce->in_use = 1;
mce->initiator = MCE_INITIATOR_CPU;
- if (handled)
+ /* Mark it recovered if we have handled it and MSR(RI=1). */
+ if (handled && (regs->msr & MSR_RI))
mce->disposition = MCE_DISPOSITION_RECOVERED;
else
mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 93dae296b6be..fa20060ff7a5 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -184,7 +184,7 @@ void setup_paca(struct paca_struct *new_paca)
* if we do a GET_PACA() before the feature fixups have been
* applied
*/
- if (cpu_has_feature(CPU_FTR_HVMODE))
+ if (early_cpu_has_feature(CPU_FTR_HVMODE))
mtspr(SPRN_SPRG_HPACA, local_paca);
#endif
mtspr(SPRN_SPRG_PACA, local_paca);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index a5c0153ede37..7fdf324d5b51 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -78,6 +78,7 @@ EXPORT_SYMBOL(get_pci_dma_ops);
static int get_phb_number(struct device_node *dn)
{
int ret, phb_id = -1;
+ u32 prop_32;
u64 prop;
/*
@@ -86,8 +87,10 @@ static int get_phb_number(struct device_node *dn)
* reading "ibm,opal-phbid", only present in OPAL environment.
*/
ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
- if (ret)
- ret = of_property_read_u32_index(dn, "reg", 1, (u32 *)&prop);
+ if (ret) {
+ ret = of_property_read_u32_index(dn, "reg", 1, &prop_32);
+ prop = prop_32;
+ }
if (!ret)
phb_id = (int)(prop & (MAX_PHBS - 1));
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index a8cca88e972f..9ee2623e0f67 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -58,6 +58,7 @@
#include <asm/code-patching.h>
#include <asm/exec.h>
#include <asm/livepatch.h>
+#include <asm/cpu_has_feature.h>
#include <linux/kprobes.h>
#include <linux/kdebug.h>
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bae3db791150..b0245bed6f54 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -170,7 +170,7 @@ static struct ibm_pa_feature {
*/
{CPU_FTR_TM_COMP, 0, 0,
PPC_FEATURE2_HTM_COMP|PPC_FEATURE2_HTM_NOSC_COMP, 22, 0, 0},
- {0, MMU_FTR_RADIX, 0, 0, 40, 0, 0},
+ {0, MMU_FTR_TYPE_RADIX, 0, 0, 40, 0, 0},
};
static void __init scan_features(unsigned long node, const unsigned char *ftrs,
@@ -647,14 +647,6 @@ static void __init early_reserve_mem(void)
#endif
}
-static bool disable_radix;
-static int __init parse_disable_radix(char *p)
-{
- disable_radix = true;
- return 0;
-}
-early_param("disable_radix", parse_disable_radix);
-
void __init early_init_devtree(void *params)
{
phys_addr_t limit;
@@ -744,11 +736,8 @@ void __init early_init_devtree(void *params)
*/
spinning_secondaries = boot_cpu_count - 1;
#endif
- /*
- * now fixup radix MMU mode based on kernel command line
- */
- if (disable_radix)
- cur_cpu_spec->mmu_features &= ~MMU_FTR_RADIX;
+
+ mmu_early_init_devtree();
#ifdef CONFIG_PPC_POWERNV
/* Scan and build the list of machine check recoverable ranges */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 6ee4b72cda42..4e74fc588a3f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2940,7 +2940,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
/* Don't print anything after quiesce under OPAL, it crashes OFW */
if (of_platform != PLATFORM_OPAL) {
- prom_printf("Booting Linux via __start() ...\n");
+ prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
prom_debug("->dt_header_start=0x%x\n", hdr);
}
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 134bee9ac664..bf91658a8a40 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -38,6 +38,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/switch_to.h>
+#include <asm/tm.h>
#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>
@@ -64,6 +65,10 @@ struct pt_regs_offset {
{.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
#define REG_OFFSET_END {.name = NULL, .offset = 0}
+#define TVSO(f) (offsetof(struct thread_vr_state, f))
+#define TFSO(f) (offsetof(struct thread_fp_state, f))
+#define TSO(f) (offsetof(struct thread_struct, f))
+
static const struct pt_regs_offset regoffset_table[] = {
GPR_OFFSET_NAME(0),
GPR_OFFSET_NAME(1),
@@ -114,6 +119,24 @@ static const struct pt_regs_offset regoffset_table[] = {
REG_OFFSET_END,
};
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static void flush_tmregs_to_thread(struct task_struct *tsk)
+{
+ /*
+ * If task is not current, it will have been flushed already to
+ * it's thread_struct during __switch_to().
+ *
+ * A reclaim flushes ALL the state.
+ */
+
+ if (tsk == current && MSR_TM_SUSPENDED(mfmsr()))
+ tm_reclaim_current(TM_CAUSE_SIGNAL);
+
+}
+#else
+static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
+#endif
+
/**
* regs_query_register_offset() - query register offset from its name
* @name: the name of a register
@@ -181,6 +204,26 @@ static int set_user_msr(struct task_struct *task, unsigned long msr)
return 0;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static unsigned long get_user_ckpt_msr(struct task_struct *task)
+{
+ return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
+}
+
+static int set_user_ckpt_msr(struct task_struct *task, unsigned long msr)
+{
+ task->thread.ckpt_regs.msr &= ~MSR_DEBUGCHANGE;
+ task->thread.ckpt_regs.msr |= msr & MSR_DEBUGCHANGE;
+ return 0;
+}
+
+static int set_user_ckpt_trap(struct task_struct *task, unsigned long trap)
+{
+ task->thread.ckpt_regs.trap = trap & 0xfff0;
+ return 0;
+}
+#endif
+
#ifdef CONFIG_PPC64
static int get_user_dscr(struct task_struct *task, unsigned long *data)
{
@@ -358,6 +401,29 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
return ret;
}
+/*
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which returns the current running values of
+ * all the FPR registers, needs to know whether any transaction is active
+ * or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * u64 fpr[32];
+ * u64 fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ * !defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ */
static int fpr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
@@ -368,14 +434,31 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
#endif
flush_fp_to_thread(target);
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ /* copy to local buffer then write that out */
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.TS_TRANS_FPR(i);
+ buf[32] = target->thread.transact_fp.fpscr;
+ } else {
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.TS_FPR(i);
+ buf[32] = target->thread.fp_state.fpscr;
+ }
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
/* copy to local buffer then write that out */
for (i = 0; i < 32 ; i++)
buf[i] = target->thread.TS_FPR(i);
buf[32] = target->thread.fp_state.fpscr;
return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+#endif
-#else
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32]));
@@ -384,6 +467,29 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset,
#endif
}
+/*
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which setss the current running values of
+ * all the FPR registers, needs to know whether any transaction is active
+ * or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * u64 fpr[32];
+ * u64 fpscr;
+ * };
+ *
+ * There are two config options CONFIG_VSX and CONFIG_PPC_TRANSACTIONAL_MEM
+ * which determines the final code in this function. All the combinations of
+ * these two config options are possible except the one below as transactional
+ * memory config pulls in CONFIG_VSX automatically.
+ *
+ * !defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ */
static int fpr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
@@ -394,7 +500,27 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
#endif
flush_fp_to_thread(target);
-#ifdef CONFIG_VSX
+#if defined(CONFIG_VSX) && defined(CONFIG_PPC_TRANSACTIONAL_MEM)
+ /* copy to local buffer then write that out */
+ i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+ if (i)
+ return i;
+
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+ for (i = 0; i < 32 ; i++)
+ target->thread.TS_TRANS_FPR(i) = buf[i];
+ target->thread.transact_fp.fpscr = buf[32];
+ } else {
+ for (i = 0; i < 32 ; i++)
+ target->thread.TS_FPR(i) = buf[i];
+ target->thread.fp_state.fpscr = buf[32];
+ }
+ return 0;
+#endif
+
+#if defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
/* copy to local buffer then write that out */
i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
if (i)
@@ -403,7 +529,9 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,
target->thread.TS_FPR(i) = buf[i];
target->thread.fp_state.fpscr = buf[32];
return 0;
-#else
+#endif
+
+#if !defined(CONFIG_VSX) && !defined(CONFIG_PPC_TRANSACTIONAL_MEM)
BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) !=
offsetof(struct thread_fp_state, fpr[32]));
@@ -433,10 +561,28 @@ static int vr_active(struct task_struct *target,
return target->thread.used_vr ? regset->n : 0;
}
+/*
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * gets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * vector128 vr[32];
+ * vector128 vscr;
+ * vector128 vrsave;
+ * };
+ */
static int vr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
{
+ struct thread_vr_state *addr;
int ret;
flush_altivec_to_thread(target);
@@ -444,8 +590,19 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
offsetof(struct thread_vr_state, vr[32]));
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ flush_fp_to_thread(target);
+ flush_tmregs_to_thread(target);
+ addr = &target->thread.transact_vr;
+ } else {
+ addr = &target->thread.vr_state;
+ }
+#else
+ addr = &target->thread.vr_state;
+#endif
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
- &target->thread.vr_state, 0,
+ addr, 0,
33 * sizeof(vector128));
if (!ret) {
/*
@@ -456,7 +613,16 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
u32 word;
} vrsave;
memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ vrsave.word = target->thread.transact_vrsave;
+ else
+ vrsave.word = target->thread.vrsave;
+#else
vrsave.word = target->thread.vrsave;
+#endif
+
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
33 * sizeof(vector128), -1);
}
@@ -464,10 +630,28 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset,
return ret;
}
+/*
+ * When the transaction is active, 'transact_vr' holds the current running
+ * value of all the VMX registers and 'vr_state' holds the last checkpointed
+ * value of all the VMX registers for the current transaction to fall back
+ * on in case it aborts. When transaction is not active 'vr_state' holds
+ * the current running state of all the VMX registers. So this function which
+ * sets the current running values of all the VMX registers, needs to know
+ * whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * vector128 vr[32];
+ * vector128 vscr;
+ * vector128 vrsave;
+ * };
+ */
static int vr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
+ struct thread_vr_state *addr;
int ret;
flush_altivec_to_thread(target);
@@ -475,8 +659,19 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) !=
offsetof(struct thread_vr_state, vr[32]));
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ flush_fp_to_thread(target);
+ flush_tmregs_to_thread(target);
+ addr = &target->thread.transact_vr;
+ } else {
+ addr = &target->thread.vr_state;
+ }
+#else
+ addr = &target->thread.vr_state;
+#endif
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
- &target->thread.vr_state, 0,
+ addr, 0,
33 * sizeof(vector128));
if (!ret && count > 0) {
/*
@@ -487,11 +682,28 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset,
u32 word;
} vrsave;
memset(&vrsave, 0, sizeof(vrsave));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ vrsave.word = target->thread.transact_vrsave;
+ else
+ vrsave.word = target->thread.vrsave;
+#else
vrsave.word = target->thread.vrsave;
+#endif
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
33 * sizeof(vector128), -1);
- if (!ret)
+ if (!ret) {
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ target->thread.transact_vrsave = vrsave.word;
+ else
+ target->thread.vrsave = vrsave.word;
+#else
target->thread.vrsave = vrsave.word;
+#endif
+ }
}
return ret;
@@ -512,6 +724,21 @@ static int vsr_active(struct task_struct *target,
return target->thread.used_vsr ? regset->n : 0;
}
+/*
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which returns the current running values of
+ * all the FPR registers, needs to know whether any transaction is active
+ * or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * u64 vsx[32];
+ * };
+ */
static int vsr_get(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
void *kbuf, void __user *ubuf)
@@ -519,16 +746,47 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset,
u64 buf[32];
int ret, i;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+#endif
flush_vsx_to_thread(target);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.
+ transact_fp.fpr[i][TS_VSRLOWOFFSET];
+ } else {
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.
+ fp_state.fpr[i][TS_VSRLOWOFFSET];
+ }
+#else
for (i = 0; i < 32 ; i++)
buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+#endif
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
buf, 0, 32 * sizeof(double));
return ret;
}
+/*
+ * When the transaction is active, 'transact_fp' holds the current running
+ * value of all FPR registers and 'fp_state' holds the last checkpointed
+ * value of all FPR registers for the current transaction. When transaction
+ * is not active 'fp_state' holds the current running state of all the FPR
+ * registers. So this function which sets the current running values of all
+ * the FPR registers, needs to know whether any transaction is active or not.
+ *
+ * Userspace interface buffer layout:
+ *
+ * struct data {
+ * u64 vsx[32];
+ * };
+ */
static int vsr_set(struct task_struct *target, const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
@@ -536,12 +794,30 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
u64 buf[32];
int ret,i;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+#endif
flush_vsx_to_thread(target);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
buf, 0, 32 * sizeof(double));
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (MSR_TM_ACTIVE(target->thread.regs->msr)) {
+ for (i = 0; i < 32 ; i++)
+ target->thread.transact_fp.
+ fpr[i][TS_VSRLOWOFFSET] = buf[i];
+ } else {
+ for (i = 0; i < 32 ; i++)
+ target->thread.fp_state.
+ fpr[i][TS_VSRLOWOFFSET] = buf[i];
+ }
+#else
for (i = 0; i < 32 ; i++)
target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+#endif
return ret;
@@ -614,8 +890,1030 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset,
}
#endif /* CONFIG_SPE */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+/**
+ * tm_cgpr_active - get active number of registers in CGPR
+ * @target: The target task.
+ * @regset: The user regset structure.
+ *
+ * This function checks for the active number of available
+ * regisers in transaction checkpointed GPR category.
+ */
+static int tm_cgpr_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return 0;
+
+ return regset->n;
+}
+
+/**
+ * tm_cgpr_get - get CGPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy from.
+ * @ubuf: User buffer to copy into.
+ *
+ * This function gets transaction checkpointed GPR registers.
+ *
+ * When the transaction is active, 'ckpt_regs' holds all the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function gets those checkpointed GPR registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ckpt_regs,
+ 0, offsetof(struct pt_regs, msr));
+ if (!ret) {
+ unsigned long msr = get_user_ckpt_msr(target);
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr,
+ offsetof(struct pt_regs, msr),
+ offsetof(struct pt_regs, msr) +
+ sizeof(msr));
+ }
+
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
+ offsetof(struct pt_regs, msr) + sizeof(long));
+
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ckpt_regs.orig_gpr3,
+ offsetof(struct pt_regs, orig_gpr3),
+ sizeof(struct pt_regs));
+ if (!ret)
+ ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+ sizeof(struct pt_regs), -1);
+
+ return ret;
+}
/*
+ * tm_cgpr_set - set the CGPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy into.
+ * @ubuf: User buffer to copy from.
+ *
+ * This function sets in transaction checkpointed GPR registers.
+ *
+ * When the transaction is active, 'ckpt_regs' holds the checkpointed
+ * GPR register values for the current transaction to fall back on if it
+ * aborts in between. This function sets those checkpointed GPR registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * struct pt_regs ckpt_regs;
+ * };
+ */
+static int tm_cgpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ unsigned long reg;
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ckpt_regs,
+ 0, PT_MSR * sizeof(reg));
+
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
+ PT_MSR * sizeof(reg),
+ (PT_MSR + 1) * sizeof(reg));
+ if (!ret)
+ ret = set_user_ckpt_msr(target, reg);
+ }
+
+ BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
+ offsetof(struct pt_regs, msr) + sizeof(long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ckpt_regs.orig_gpr3,
+ PT_ORIG_R3 * sizeof(reg),
+ (PT_MAX_PUT_REG + 1) * sizeof(reg));
+
+ if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
+ ret = user_regset_copyin_ignore(
+ &pos, &count, &kbuf, &ubuf,
+ (PT_MAX_PUT_REG + 1) * sizeof(reg),
+ PT_TRAP * sizeof(reg));
+
+ if (!ret && count > 0) {
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
+ PT_TRAP * sizeof(reg),
+ (PT_TRAP + 1) * sizeof(reg));
+ if (!ret)
+ ret = set_user_ckpt_trap(target, reg);
+ }
+
+ if (!ret)
+ ret = user_regset_copyin_ignore(
+ &pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
+
+ return ret;
+}
+
+/**
+ * tm_cfpr_active - get active number of registers in CFPR
+ * @target: The target task.
+ * @regset: The user regset structure.
+ *
+ * This function checks for the active number of available
+ * regisers in transaction checkpointed FPR category.
+ */
+static int tm_cfpr_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return 0;
+
+ return regset->n;
+}
+
+/**
+ * tm_cfpr_get - get CFPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy from.
+ * @ubuf: User buffer to copy into.
+ *
+ * This function gets in transaction checkpointed FPR registers.
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * values for the current transaction to fall back on if it aborts
+ * in between. This function gets those checkpointed FPR registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * u64 fpr[32];
+ * u64 fpscr;
+ *};
+ */
+static int tm_cfpr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ u64 buf[33];
+ int i;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ /* copy to local buffer then write that out */
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.TS_FPR(i);
+ buf[32] = target->thread.fp_state.fpscr;
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+}
+
+/**
+ * tm_cfpr_set - set CFPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy into.
+ * @ubuf: User buffer to copy from.
+ *
+ * This function sets in transaction checkpointed FPR registers.
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * FPR register values for the current transaction to fall back on
+ * if it aborts in between. This function sets these checkpointed
+ * FPR registers. The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * u64 fpr[32];
+ * u64 fpscr;
+ *};
+ */
+static int tm_cfpr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ u64 buf[33];
+ int i;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ /* copy to local buffer then write that out */
+ i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
+ if (i)
+ return i;
+ for (i = 0; i < 32 ; i++)
+ target->thread.TS_FPR(i) = buf[i];
+ target->thread.fp_state.fpscr = buf[32];
+ return 0;
+}
+
+/**
+ * tm_cvmx_active - get active number of registers in CVMX
+ * @target: The target task.
+ * @regset: The user regset structure.
+ *
+ * This function checks for the active number of available
+ * regisers in checkpointed VMX category.
+ */
+static int tm_cvmx_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return 0;
+
+ return regset->n;
+}
+
+/**
+ * tm_cvmx_get - get CMVX registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy from.
+ * @ubuf: User buffer to copy into.
+ *
+ * This function gets in transaction checkpointed VMX registers.
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between. The userspace interface buffer
+ * layout is as follows.
+ *
+ * struct data {
+ * vector128 vr[32];
+ * vector128 vscr;
+ * vector128 vrsave;
+ *};
+ */
+static int tm_cvmx_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ /* Flush the state */
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.vr_state, 0,
+ 33 * sizeof(vector128));
+ if (!ret) {
+ /*
+ * Copy out only the low-order word of vrsave.
+ */
+ union {
+ elf_vrreg_t reg;
+ u32 word;
+ } vrsave;
+ memset(&vrsave, 0, sizeof(vrsave));
+ vrsave.word = target->thread.vrsave;
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
+ 33 * sizeof(vector128), -1);
+ }
+
+ return ret;
+}
+
+/**
+ * tm_cvmx_set - set CMVX registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy into.
+ * @ubuf: User buffer to copy from.
+ *
+ * This function sets in transaction checkpointed VMX registers.
+ *
+ * When the transaction is active 'vr_state' and 'vr_save' hold
+ * the checkpointed values for the current transaction to fall
+ * back on if it aborts in between. The userspace interface buffer
+ * layout is as follows.
+ *
+ * struct data {
+ * vector128 vr[32];
+ * vector128 vscr;
+ * vector128 vrsave;
+ *};
+ */
+static int tm_cvmx_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.vr_state, 0,
+ 33 * sizeof(vector128));
+ if (!ret && count > 0) {
+ /*
+ * We use only the low-order word of vrsave.
+ */
+ union {
+ elf_vrreg_t reg;
+ u32 word;
+ } vrsave;
+ memset(&vrsave, 0, sizeof(vrsave));
+ vrsave.word = target->thread.vrsave;
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
+ 33 * sizeof(vector128), -1);
+ if (!ret)
+ target->thread.vrsave = vrsave.word;
+ }
+
+ return ret;
+}
+
+/**
+ * tm_cvsx_active - get active number of registers in CVSX
+ * @target: The target task.
+ * @regset: The user regset structure.
+ *
+ * This function checks for the active number of available
+ * regisers in transaction checkpointed VSX category.
+ */
+static int tm_cvsx_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return 0;
+
+ flush_vsx_to_thread(target);
+ return target->thread.used_vsr ? regset->n : 0;
+}
+
+/**
+ * tm_cvsx_get - get CVSX registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy from.
+ * @ubuf: User buffer to copy into.
+ *
+ * This function gets in transaction checkpointed VSX registers.
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * values for the current transaction to fall back on if it aborts
+ * in between. This function gets those checkpointed VSX registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * u64 vsx[32];
+ *};
+ */
+static int tm_cvsx_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ u64 buf[32];
+ int ret, i;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ /* Flush the state */
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+ flush_vsx_to_thread(target);
+
+ for (i = 0; i < 32 ; i++)
+ buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ buf, 0, 32 * sizeof(double));
+
+ return ret;
+}
+
+/**
+ * tm_cvsx_set - set CFPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy into.
+ * @ubuf: User buffer to copy from.
+ *
+ * This function sets in transaction checkpointed VSX registers.
+ *
+ * When the transaction is active 'fp_state' holds the checkpointed
+ * VSX register values for the current transaction to fall back on
+ * if it aborts in between. This function sets these checkpointed
+ * FPR registers. The userspace interface buffer layout is as follows.
+ *
+ * struct data {
+ * u64 vsx[32];
+ *};
+ */
+static int tm_cvsx_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ u64 buf[32];
+ int ret, i;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ /* Flush the state */
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+ flush_vsx_to_thread(target);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ buf, 0, 32 * sizeof(double));
+ for (i = 0; i < 32 ; i++)
+ target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
+
+ return ret;
+}
+
+/**
+ * tm_spr_active - get active number of registers in TM SPR
+ * @target: The target task.
+ * @regset: The user regset structure.
+ *
+ * This function checks the active number of available
+ * regisers in the transactional memory SPR category.
+ */
+static int tm_spr_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ return regset->n;
+}
+
+/**
+ * tm_spr_get - get the TM related SPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy from.
+ * @ubuf: User buffer to copy into.
+ *
+ * This function gets transactional memory related SPR registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct {
+ * u64 tm_tfhar;
+ * u64 tm_texasr;
+ * u64 tm_tfiar;
+ * };
+ */
+static int tm_spr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ /* Build tests */
+ BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+ BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+ BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ /* Flush the states */
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ /* TFHAR register */
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tfhar, 0, sizeof(u64));
+
+ /* TEXASR register */
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_texasr, sizeof(u64),
+ 2 * sizeof(u64));
+
+ /* TFIAR register */
+ if (!ret)
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tfiar,
+ 2 * sizeof(u64), 3 * sizeof(u64));
+ return ret;
+}
+
+/**
+ * tm_spr_set - set the TM related SPR registers
+ * @target: The target task.
+ * @regset: The user regset structure.
+ * @pos: The buffer position.
+ * @count: Number of bytes to copy.
+ * @kbuf: Kernel buffer to copy into.
+ * @ubuf: User buffer to copy from.
+ *
+ * This function sets transactional memory related SPR registers.
+ * The userspace interface buffer layout is as follows.
+ *
+ * struct {
+ * u64 tm_tfhar;
+ * u64 tm_texasr;
+ * u64 tm_tfiar;
+ * };
+ */
+static int tm_spr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ /* Build tests */
+ BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
+ BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
+ BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ /* Flush the states */
+ flush_fp_to_thread(target);
+ flush_altivec_to_thread(target);
+ flush_tmregs_to_thread(target);
+
+ /* TFHAR register */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tfhar, 0, sizeof(u64));
+
+ /* TEXASR register */
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_texasr, sizeof(u64),
+ 2 * sizeof(u64));
+
+ /* TFIAR register */
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tfiar,
+ 2 * sizeof(u64), 3 * sizeof(u64));
+ return ret;
+}
+
+static int tm_tar_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ return regset->n;
+
+ return 0;
+}
+
+static int tm_tar_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tar, 0, sizeof(u64));
+ return ret;
+}
+
+static int tm_tar_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_tar, 0, sizeof(u64));
+ return ret;
+}
+
+static int tm_ppr_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ return regset->n;
+
+ return 0;
+}
+
+
+static int tm_ppr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_ppr, 0, sizeof(u64));
+ return ret;
+}
+
+static int tm_ppr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_ppr, 0, sizeof(u64));
+ return ret;
+}
+
+static int tm_dscr_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (MSR_TM_ACTIVE(target->thread.regs->msr))
+ return regset->n;
+
+ return 0;
+}
+
+static int tm_dscr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_dscr, 0, sizeof(u64));
+ return ret;
+}
+
+static int tm_dscr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ return -ENODEV;
+
+ if (!MSR_TM_ACTIVE(target->thread.regs->msr))
+ return -ENODATA;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tm_dscr, 0, sizeof(u64));
+ return ret;
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
+#ifdef CONFIG_PPC64
+static int ppr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ppr, 0, sizeof(u64));
+ return ret;
+}
+
+static int ppr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ppr, 0, sizeof(u64));
+ return ret;
+}
+
+static int dscr_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.dscr, 0, sizeof(u64));
+ return ret;
+}
+static int dscr_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.dscr, 0, sizeof(u64));
+ return ret;
+}
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+static int tar_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tar, 0, sizeof(u64));
+ return ret;
+}
+static int tar_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.tar, 0, sizeof(u64));
+ return ret;
+}
+
+static int ebb_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ if (target->thread.used_ebb)
+ return regset->n;
+
+ return 0;
+}
+
+static int ebb_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ /* Build tests */
+ BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
+ BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
+
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ if (!target->thread.used_ebb)
+ return -ENODATA;
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ebbrr, 0, 3 * sizeof(unsigned long));
+}
+
+static int ebb_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret = 0;
+
+ /* Build tests */
+ BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
+ BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
+
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ if (target->thread.used_ebb)
+ return -ENODATA;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ebbrr, 0, sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.ebbhr, sizeof(unsigned long),
+ 2 * sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.bescr,
+ 2 * sizeof(unsigned long), 3 * sizeof(unsigned long));
+
+ return ret;
+}
+static int pmu_active(struct task_struct *target,
+ const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ return regset->n;
+}
+
+static int pmu_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ /* Build tests */
+ BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
+ BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
+ BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
+ BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
+
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &target->thread.siar, 0,
+ 5 * sizeof(unsigned long));
+}
+
+static int pmu_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret = 0;
+
+ /* Build tests */
+ BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
+ BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
+ BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
+ BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
+
+ if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+ return -ENODEV;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.siar, 0,
+ sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.sdar, sizeof(unsigned long),
+ 2 * sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.sier, 2 * sizeof(unsigned long),
+ 3 * sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.mmcr2, 3 * sizeof(unsigned long),
+ 4 * sizeof(unsigned long));
+
+ if (!ret)
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &target->thread.mmcr0, 4 * sizeof(unsigned long),
+ 5 * sizeof(unsigned long));
+ return ret;
+}
+#endif
+/*
* These are our native regset flavors.
*/
enum powerpc_regset {
@@ -630,6 +1928,25 @@ enum powerpc_regset {
#ifdef CONFIG_SPE
REGSET_SPE,
#endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ REGSET_TM_CGPR, /* TM checkpointed GPR registers */
+ REGSET_TM_CFPR, /* TM checkpointed FPR registers */
+ REGSET_TM_CVMX, /* TM checkpointed VMX registers */
+ REGSET_TM_CVSX, /* TM checkpointed VSX registers */
+ REGSET_TM_SPR, /* TM specific SPR registers */
+ REGSET_TM_CTAR, /* TM checkpointed TAR register */
+ REGSET_TM_CPPR, /* TM checkpointed PPR register */
+ REGSET_TM_CDSCR, /* TM checkpointed DSCR register */
+#endif
+#ifdef CONFIG_PPC64
+ REGSET_PPR, /* PPR register */
+ REGSET_DSCR, /* DSCR register */
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+ REGSET_TAR, /* TAR register */
+ REGSET_EBB, /* EBB registers */
+ REGSET_PMR, /* Performance Monitor Registers */
+#endif
};
static const struct user_regset native_regsets[] = {
@@ -664,6 +1981,77 @@ static const struct user_regset native_regsets[] = {
.active = evr_active, .get = evr_get, .set = evr_set
},
#endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ [REGSET_TM_CGPR] = {
+ .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+ .size = sizeof(long), .align = sizeof(long),
+ .active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set
+ },
+ [REGSET_TM_CFPR] = {
+ .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+ .size = sizeof(double), .align = sizeof(double),
+ .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
+ },
+ [REGSET_TM_CVMX] = {
+ .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+ .size = sizeof(vector128), .align = sizeof(vector128),
+ .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+ },
+ [REGSET_TM_CVSX] = {
+ .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
+ .size = sizeof(double), .align = sizeof(double),
+ .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
+ },
+ [REGSET_TM_SPR] = {
+ .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+ },
+ [REGSET_TM_CTAR] = {
+ .core_note_type = NT_PPC_TM_CTAR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set
+ },
+ [REGSET_TM_CPPR] = {
+ .core_note_type = NT_PPC_TM_CPPR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set
+ },
+ [REGSET_TM_CDSCR] = {
+ .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set
+ },
+#endif
+#ifdef CONFIG_PPC64
+ [REGSET_PPR] = {
+ .core_note_type = NT_PPC_PPR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = ppr_get, .set = ppr_set
+ },
+ [REGSET_DSCR] = {
+ .core_note_type = NT_PPC_DSCR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = dscr_get, .set = dscr_set
+ },
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+ [REGSET_TAR] = {
+ .core_note_type = NT_PPC_TAR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = tar_get, .set = tar_set
+ },
+ [REGSET_EBB] = {
+ .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = ebb_active, .get = ebb_get, .set = ebb_set
+ },
+ [REGSET_PMR] = {
+ .core_note_type = NT_PPC_PMU, .n = ELF_NPMU,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = pmu_active, .get = pmu_get, .set = pmu_set
+ },
+#endif
};
static const struct user_regset_view user_ppc_native_view = {
@@ -674,24 +2062,35 @@ static const struct user_regset_view user_ppc_native_view = {
#ifdef CONFIG_PPC64
#include <linux/compat.h>
-static int gpr32_get(struct task_struct *target,
+static int gpr32_get_common(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
- void *kbuf, void __user *ubuf)
+ void *kbuf, void __user *ubuf, bool tm_active)
{
const unsigned long *regs = &target->thread.regs->gpr[0];
+ const unsigned long *ckpt_regs;
compat_ulong_t *k = kbuf;
compat_ulong_t __user *u = ubuf;
compat_ulong_t reg;
int i;
- if (target->thread.regs == NULL)
- return -EIO;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ ckpt_regs = &target->thread.ckpt_regs.gpr[0];
+#endif
+ if (tm_active) {
+ regs = ckpt_regs;
+ } else {
+ if (target->thread.regs == NULL)
+ return -EIO;
- if (!FULL_REGS(target->thread.regs)) {
- /* We have a partial register set. Fill 14-31 with bogus values */
- for (i = 14; i < 32; i++)
- target->thread.regs->gpr[i] = NV_REG_POISON;
+ if (!FULL_REGS(target->thread.regs)) {
+ /*
+ * We have a partial register set.
+ * Fill 14-31 with bogus values.
+ */
+ for (i = 14; i < 32; i++)
+ target->thread.regs->gpr[i] = NV_REG_POISON;
+ }
}
pos /= sizeof(reg);
@@ -731,20 +2130,31 @@ static int gpr32_get(struct task_struct *target,
PT_REGS_COUNT * sizeof(reg), -1);
}
-static int gpr32_set(struct task_struct *target,
+static int gpr32_set_common(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
- const void *kbuf, const void __user *ubuf)
+ const void *kbuf, const void __user *ubuf, bool tm_active)
{
unsigned long *regs = &target->thread.regs->gpr[0];
+ unsigned long *ckpt_regs;
const compat_ulong_t *k = kbuf;
const compat_ulong_t __user *u = ubuf;
compat_ulong_t reg;
- if (target->thread.regs == NULL)
- return -EIO;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ ckpt_regs = &target->thread.ckpt_regs.gpr[0];
+#endif
- CHECK_FULL_REGS(target->thread.regs);
+ if (tm_active) {
+ regs = ckpt_regs;
+ } else {
+ regs = &target->thread.regs->gpr[0];
+
+ if (target->thread.regs == NULL)
+ return -EIO;
+
+ CHECK_FULL_REGS(target->thread.regs);
+ }
pos /= sizeof(reg);
count /= sizeof(reg);
@@ -804,6 +2214,40 @@ static int gpr32_set(struct task_struct *target,
(PT_TRAP + 1) * sizeof(reg), -1);
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static int tm_cgpr32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ return gpr32_get_common(target, regset, pos, count, kbuf, ubuf, 1);
+}
+
+static int tm_cgpr32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, 1);
+}
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+
+static int gpr32_get(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+{
+ return gpr32_get_common(target, regset, pos, count, kbuf, ubuf, 0);
+}
+
+static int gpr32_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ return gpr32_set_common(target, regset, pos, count, kbuf, ubuf, 0);
+}
+
/*
* These are the regset flavors matching the CONFIG_PPC32 native set.
*/
@@ -832,6 +2276,73 @@ static const struct user_regset compat_regsets[] = {
.active = evr_active, .get = evr_get, .set = evr_set
},
#endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ [REGSET_TM_CGPR] = {
+ .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
+ .size = sizeof(long), .align = sizeof(long),
+ .active = tm_cgpr_active,
+ .get = tm_cgpr32_get, .set = tm_cgpr32_set
+ },
+ [REGSET_TM_CFPR] = {
+ .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
+ .size = sizeof(double), .align = sizeof(double),
+ .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
+ },
+ [REGSET_TM_CVMX] = {
+ .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
+ .size = sizeof(vector128), .align = sizeof(vector128),
+ .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
+ },
+ [REGSET_TM_CVSX] = {
+ .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
+ .size = sizeof(double), .align = sizeof(double),
+ .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
+ },
+ [REGSET_TM_SPR] = {
+ .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
+ },
+ [REGSET_TM_CTAR] = {
+ .core_note_type = NT_PPC_TM_CTAR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set
+ },
+ [REGSET_TM_CPPR] = {
+ .core_note_type = NT_PPC_TM_CPPR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set
+ },
+ [REGSET_TM_CDSCR] = {
+ .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set
+ },
+#endif
+#ifdef CONFIG_PPC64
+ [REGSET_PPR] = {
+ .core_note_type = NT_PPC_PPR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = ppr_get, .set = ppr_set
+ },
+ [REGSET_DSCR] = {
+ .core_note_type = NT_PPC_DSCR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = dscr_get, .set = dscr_set
+ },
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+ [REGSET_TAR] = {
+ .core_note_type = NT_PPC_TAR, .n = 1,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .get = tar_get, .set = tar_set
+ },
+ [REGSET_EBB] = {
+ .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = ebb_active, .get = ebb_get, .set = ebb_set
+ },
+#endif
};
static const struct user_regset_view user_ppc_compat_view = {
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 714b4ba7ab86..dba265c586df 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -66,6 +66,7 @@
#include <asm/hugetlb.h>
#include <asm/livepatch.h>
#include <asm/mmu_context.h>
+#include <asm/cpu_has_feature.h>
#include "setup.h"
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 00f57754407e..24ec3ea4b3a2 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -37,6 +37,7 @@
#include <asm/serial.h>
#include <asm/udbg.h>
#include <asm/code-patching.h>
+#include <asm/cpu_has_feature.h>
#define DBG(fmt...)
@@ -92,15 +93,16 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
* and we are running with enough of the MMU enabled to have our
* proper kernel virtual addresses
*
- * Find out what kind of machine we're on and save any data we need
- * from the early boot process (devtree is copied on pmac by prom_init()).
- * This is called very early on the boot process, after a minimal
- * MMU environment has been set up but before MMU_init is called.
+ * We do the initial parsing of the flat device-tree and prepares
+ * for the MMU to be fully initialized.
*/
extern unsigned int memset_nocache_branch; /* Insn to be replaced by NOP */
notrace void __init machine_init(u64 dt_ptr)
{
+ /* Configure static keys first, now that we're relocated. */
+ setup_feature_keys();
+
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index d8216aed22b7..7ac8e6eaab5b 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -227,8 +227,8 @@ static void __init configure_exceptions(void)
opal_configure_cores();
/* Enable AIL if supported, and we are in hypervisor mode */
- if (cpu_has_feature(CPU_FTR_HVMODE) &&
- cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ if (early_cpu_has_feature(CPU_FTR_HVMODE) &&
+ early_cpu_has_feature(CPU_FTR_ARCH_207S)) {
unsigned long lpcr = mfspr(SPRN_LPCR);
mtspr(SPRN_LPCR, lpcr | LPCR_AIL_3);
}
@@ -298,11 +298,12 @@ void __init early_setup(unsigned long dt_ptr)
*/
configure_exceptions();
- /* Initialize the hash table or TLB handling */
- early_init_mmu();
-
/* Apply all the dynamic patching */
apply_feature_fixups();
+ setup_feature_keys();
+
+ /* Initialize the hash table or TLB handling */
+ early_init_mmu();
/*
* At this point, we can let interrupts switch to virtual mode
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 5a1f015ea9f3..25a39052bf6b 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -55,6 +55,7 @@
#include <asm/debug.h>
#include <asm/kexec.h>
#include <asm/asm-prototypes.h>
+#include <asm/cpu_has_feature.h>
#ifdef DEBUG
#include <asm/udbg.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 4e7759c8ca30..3efbedefba6a 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -56,6 +56,7 @@
#include <linux/irq_work.h>
#include <linux/clk-provider.h>
#include <linux/suspend.h>
+#include <linux/rtc.h>
#include <asm/trace.h>
#include <asm/io.h>
@@ -1159,6 +1160,29 @@ void calibrate_delay(void)
loops_per_jiffy = tb_ticks_per_jiffy;
}
+#if IS_ENABLED(CONFIG_RTC_DRV_GENERIC)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
+{
+ ppc_md.get_rtc_time(tm);
+ return rtc_valid_tm(tm);
+}
+
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
+{
+ if (!ppc_md.set_rtc_time)
+ return -EOPNOTSUPP;
+
+ if (ppc_md.set_rtc_time(tm) < 0)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static const struct rtc_class_ops rtc_generic_ops = {
+ .read_time = rtc_generic_get_time,
+ .set_time = rtc_generic_set_time,
+};
+
static int __init rtc_init(void)
{
struct platform_device *pdev;
@@ -1166,9 +1190,12 @@ static int __init rtc_init(void)
if (!ppc_md.get_rtc_time)
return -ENODEV;
- pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+ pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+ &rtc_generic_ops,
+ sizeof(rtc_generic_ops));
return PTR_ERR_OR_ZERO(pdev);
}
device_initcall(rtc_init);
+#endif
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 6767605ea8da..4111d30badfa 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -22,6 +22,7 @@
#include <linux/security.h>
#include <linux/memblock.h>
+#include <asm/cpu_has_feature.h>
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/mmu.h>
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
index cbabd143acae..78a7449bf489 100644
--- a/arch/powerpc/kernel/vdso32/Makefile
+++ b/arch/powerpc/kernel/vdso32/Makefile
@@ -30,7 +30,7 @@ CPPFLAGS_vdso32.lds += -P -C -Upowerpc
$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so
# link rule for the .so file, .lds has to be first
-$(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32)
+$(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) FORCE
$(call if_changed,vdso32ld)
# strip rule for the .so file
@@ -39,12 +39,12 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)
# assembly rules for the .S files
-$(obj-vdso32): %.o: %.S
+$(obj-vdso32): %.o: %.S FORCE
$(call if_changed_dep,vdso32as)
# actual build commands
quiet_cmd_vdso32ld = VDSO32L $@
- cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@
+ cmd_vdso32ld = $(CROSS32CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
quiet_cmd_vdso32as = VDSO32A $@
cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $<
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
index c710802b8fb6..366ae09b14c1 100644
--- a/arch/powerpc/kernel/vdso64/Makefile
+++ b/arch/powerpc/kernel/vdso64/Makefile
@@ -23,7 +23,7 @@ CPPFLAGS_vdso64.lds += -P -C -U$(ARCH)
$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
# link rule for the .so file, .lds has to be first
-$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64)
+$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE
$(call if_changed,vdso64ld)
# strip rule for the .so file
@@ -32,12 +32,12 @@ $(obj)/%.so: $(obj)/%.so.dbg FORCE
$(call if_changed,objcopy)
# assembly rules for the .S files
-$(obj-vdso64): %.o: %.S
+$(obj-vdso64): %.o: %.S FORCE
$(call if_changed_dep,vdso64as)
# actual build commands
quiet_cmd_vdso64ld = VDSO64L $@
- cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@
+ cmd_vdso64ld = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^)
quiet_cmd_vdso64as = VDSO64A $@
cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 8d7358f3a273..b3813ddb2fb4 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -482,7 +482,7 @@ static void vio_cmo_balance(struct work_struct *work)
static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
void *ret;
@@ -503,7 +503,7 @@ static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
@@ -515,7 +515,7 @@ static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl;
@@ -539,7 +539,7 @@ static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl;
@@ -552,7 +552,7 @@ static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl;
@@ -588,7 +588,7 @@ static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
static void vio_dma_iommu_unmap_sg(struct device *dev,
struct scatterlist *sglist, int nelems,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
struct iommu_table *tbl;
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c
index a75ba38a2d81..05aa11399a78 100644
--- a/arch/powerpc/kvm/book3s_xics.c
+++ b/arch/powerpc/kvm/book3s_xics.c
@@ -1329,20 +1329,16 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type)
xics->kvm = kvm;
/* Already there ? */
- mutex_lock(&kvm->lock);
if (kvm->arch.xics)
ret = -EEXIST;
else
kvm->arch.xics = xics;
- mutex_unlock(&kvm->lock);
if (ret) {
kfree(xics);
return ret;
}
- xics_debugfs_init(xics);
-
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
if (cpu_has_feature(CPU_FTR_ARCH_206)) {
/* Enable real mode support */
@@ -1354,9 +1350,17 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type)
return 0;
}
+static void kvmppc_xics_init(struct kvm_device *dev)
+{
+ struct kvmppc_xics *xics = (struct kvmppc_xics *)dev->private;
+
+ xics_debugfs_init(xics);
+}
+
struct kvm_device_ops kvm_xics_ops = {
.name = "kvm-xics",
.create = kvmppc_xics_create,
+ .init = kvmppc_xics_init,
.destroy = kvmppc_xics_free,
.set_attr = xics_set_attr,
.get_attr = xics_get_attr,
diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S
index d90870a66b60..0a57fe6d49cc 100644
--- a/arch/powerpc/lib/checksum_32.S
+++ b/arch/powerpc/lib/checksum_32.S
@@ -127,8 +127,9 @@ _GLOBAL(csum_partial_copy_generic)
stw r7,12(r1)
stw r8,8(r1)
- andi. r0,r4,1 /* is destination address even ? */
- cmplwi cr7,r0,0
+ rlwinm r0,r4,3,0x8
+ rlwnm r6,r6,r0,0,31 /* odd destination address: rotate one byte */
+ cmplwi cr7,r0,0 /* is destination address even ? */
addic r12,r6,0
addi r6,r4,-4
neg r0,r4
@@ -237,7 +238,7 @@ _GLOBAL(csum_partial_copy_generic)
66: addze r3,r12
addi r1,r1,16
beqlr+ cr7
- rlwinm r3,r3,8,0,31 /* swap bytes for odd destination */
+ rlwinm r3,r3,8,0,31 /* odd destination address: rotate one byte */
blr
/* read fault */
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
index defb2998b818..043415f0bdb1 100644
--- a/arch/powerpc/lib/feature-fixups.c
+++ b/arch/powerpc/lib/feature-fixups.c
@@ -13,6 +13,7 @@
*/
#include <linux/types.h>
+#include <linux/jump_label.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
@@ -152,9 +153,18 @@ static void do_final_fixups(void)
#endif
}
-void apply_feature_fixups(void)
+static unsigned long __initdata saved_cpu_features;
+static unsigned int __initdata saved_mmu_features;
+#ifdef CONFIG_PPC64
+static unsigned long __initdata saved_firmware_features;
+#endif
+
+void __init apply_feature_fixups(void)
{
- struct cpu_spec *spec = *PTRRELOC(&cur_cpu_spec);
+ struct cpu_spec *spec = PTRRELOC(*PTRRELOC(&cur_cpu_spec));
+
+ *PTRRELOC(&saved_cpu_features) = spec->cpu_features;
+ *PTRRELOC(&saved_mmu_features) = spec->mmu_features;
/*
* Apply the CPU-specific and firmware specific fixups to kernel text
@@ -173,12 +183,40 @@ void apply_feature_fixups(void)
PTRRELOC(&__stop___lwsync_fixup));
#ifdef CONFIG_PPC64
+ saved_firmware_features = powerpc_firmware_features;
do_feature_fixups(powerpc_firmware_features,
&__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
#endif
do_final_fixups();
}
+void __init setup_feature_keys(void)
+{
+ /*
+ * Initialise jump label. This causes all the cpu/mmu_has_feature()
+ * checks to take on their correct polarity based on the current set of
+ * CPU/MMU features.
+ */
+ jump_label_init();
+ cpu_feature_keys_init();
+ mmu_feature_keys_init();
+}
+
+static int __init check_features(void)
+{
+ WARN(saved_cpu_features != cur_cpu_spec->cpu_features,
+ "CPU features changed after feature patching!\n");
+ WARN(saved_mmu_features != cur_cpu_spec->mmu_features,
+ "MMU features changed after feature patching!\n");
+#ifdef CONFIG_PPC64
+ WARN(saved_firmware_features != powerpc_firmware_features,
+ "Firmware features changed after feature patching!\n");
+#endif
+
+ return 0;
+}
+late_initcall(check_features);
+
#ifdef CONFIG_FTR_FIXUP_SELFTEST
#define check(x) \
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 88ce7d212320..0e4e9654bd2c 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -72,8 +72,7 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
/* clear out bits after (52) [0....52.....63] */
va &= ~((1ul << (64 - 52)) - 1);
va |= ssize << 8;
- sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) |
- ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4);
+ sllp = get_sllp_encoding(apsize);
va |= sllp << 5;
asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
: : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
@@ -122,8 +121,7 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
/* clear out bits after(52) [0....52.....63] */
va &= ~((1ul << (64 - 52)) - 1);
va |= ssize << 8;
- sllp = ((mmu_psize_defs[apsize].sllp & SLB_VSID_L) >> 6) |
- ((mmu_psize_defs[apsize].sllp & SLB_VSID_LP) >> 4);
+ sllp = get_sllp_encoding(apsize);
va |= sllp << 5;
asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
: : "r"(va) : "memory");
@@ -749,5 +747,5 @@ void __init hpte_init_native(void)
mmu_hash_ops.hugepage_invalidate = native_hugepage_invalidate;
if (cpu_has_feature(CPU_FTR_ARCH_300))
- ppc_md.register_process_table = native_register_proc_table;
+ register_process_table = native_register_proc_table;
}
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index b78b5d211278..0821556e16f4 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -363,11 +363,6 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node,
return 0;
}
-static void __init htab_init_seg_sizes(void)
-{
- of_scan_flat_dt(htab_dt_scan_seg_sizes, NULL);
-}
-
static int __init get_idx_from_shift(unsigned int shift)
{
int idx = -1;
@@ -539,7 +534,7 @@ static bool might_have_hea(void)
#endif /* #ifdef CONFIG_PPC_64K_PAGES */
-static void __init htab_init_page_sizes(void)
+static void __init htab_scan_page_sizes(void)
{
int rc;
@@ -554,17 +549,23 @@ static void __init htab_init_page_sizes(void)
* Try to find the available page sizes in the device-tree
*/
rc = of_scan_flat_dt(htab_dt_scan_page_sizes, NULL);
- if (rc != 0) /* Found */
- goto found;
-
- /*
- * Not in the device-tree, let's fallback on known size
- * list for 16M capable GP & GR
- */
- if (mmu_has_feature(MMU_FTR_16M_PAGE))
+ if (rc == 0 && early_mmu_has_feature(MMU_FTR_16M_PAGE)) {
+ /*
+ * Nothing in the device-tree, but the CPU supports 16M pages,
+ * so let's fallback on a known size list for 16M capable CPUs.
+ */
memcpy(mmu_psize_defs, mmu_psize_defaults_gp,
sizeof(mmu_psize_defaults_gp));
-found:
+ }
+
+#ifdef CONFIG_HUGETLB_PAGE
+ /* Reserve 16G huge page memory sections for huge pages */
+ of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL);
+#endif /* CONFIG_HUGETLB_PAGE */
+}
+
+static void __init htab_init_page_sizes(void)
+{
if (!debug_pagealloc_enabled()) {
/*
* Pick a size for the linear mapping. Currently, we only
@@ -630,11 +631,6 @@ found:
,mmu_psize_defs[mmu_vmemmap_psize].shift
#endif
);
-
-#ifdef CONFIG_HUGETLB_PAGE
- /* Reserve 16G huge page memory sections for huge pages */
- of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL);
-#endif /* CONFIG_HUGETLB_PAGE */
}
static int __init htab_dt_scan_pftsize(unsigned long node,
@@ -759,12 +755,6 @@ static void __init htab_initialize(void)
DBG(" -> htab_initialize()\n");
- /* Initialize segment sizes */
- htab_init_seg_sizes();
-
- /* Initialize page sizes */
- htab_init_page_sizes();
-
if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) {
mmu_kernel_ssize = MMU_SEGSIZE_1T;
mmu_highuser_ssize = MMU_SEGSIZE_1T;
@@ -885,8 +875,19 @@ static void __init htab_initialize(void)
#undef KB
#undef MB
+void __init hash__early_init_devtree(void)
+{
+ /* Initialize segment sizes */
+ of_scan_flat_dt(htab_dt_scan_seg_sizes, NULL);
+
+ /* Initialize page sizes */
+ htab_scan_page_sizes();
+}
+
void __init hash__early_init_mmu(void)
{
+ htab_init_page_sizes();
+
/*
* initialize page table size
*/
diff --git a/arch/powerpc/mm/hugetlbpage-radix.c b/arch/powerpc/mm/hugetlbpage-radix.c
index 1e11559e1aac..35254a678456 100644
--- a/arch/powerpc/mm/hugetlbpage-radix.c
+++ b/arch/powerpc/mm/hugetlbpage-radix.c
@@ -5,39 +5,34 @@
#include <asm/cacheflush.h>
#include <asm/machdep.h>
#include <asm/mman.h>
+#include <asm/tlb.h>
void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
{
- unsigned long ap, shift;
+ int psize;
struct hstate *hstate = hstate_file(vma->vm_file);
- shift = huge_page_shift(hstate);
- if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
- ap = mmu_get_ap(MMU_PAGE_2M);
- else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
- ap = mmu_get_ap(MMU_PAGE_1G);
- else {
- WARN(1, "Wrong huge page shift\n");
- return ;
- }
- radix___flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
+ psize = hstate_get_psize(hstate);
+ radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, psize);
}
void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
{
- unsigned long ap, shift;
+ int psize;
struct hstate *hstate = hstate_file(vma->vm_file);
- shift = huge_page_shift(hstate);
- if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
- ap = mmu_get_ap(MMU_PAGE_2M);
- else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
- ap = mmu_get_ap(MMU_PAGE_1G);
- else {
- WARN(1, "Wrong huge page shift\n");
- return ;
- }
- radix___local_flush_tlb_page(vma->vm_mm, vmaddr, ap, 0);
+ psize = hstate_get_psize(hstate);
+ radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, psize);
+}
+
+void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ int psize;
+ struct hstate *hstate = hstate_file(vma->vm_file);
+
+ psize = hstate_get_psize(hstate);
+ radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
}
/*
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 33709bdb0419..16ada1eb7e26 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -411,3 +411,25 @@ struct page *realmode_pfn_to_page(unsigned long pfn)
EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
#endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */
+
+#ifdef CONFIG_PPC_STD_MMU_64
+static bool disable_radix;
+static int __init parse_disable_radix(char *p)
+{
+ disable_radix = true;
+ return 0;
+}
+early_param("disable_radix", parse_disable_radix);
+
+void __init mmu_early_init_devtree(void)
+{
+ /* Disable radix mode based on kernel command line. */
+ if (disable_radix)
+ cur_cpu_spec->mmu_features &= ~MMU_FTR_TYPE_RADIX;
+
+ if (early_radix_enabled())
+ radix__early_init_devtree();
+ else
+ hash__early_init_devtree();
+}
+#endif /* CONFIG_PPC_STD_MMU_64 */
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c
index 670318766545..34079302cc17 100644
--- a/arch/powerpc/mm/pgtable-book3s64.c
+++ b/arch/powerpc/mm/pgtable-book3s64.c
@@ -14,6 +14,9 @@
#include "mmu_decl.h"
#include <trace/events/thp.h>
+int (*register_process_table)(unsigned long base, unsigned long page_size,
+ unsigned long tbl_size);
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
/*
* This is called when relaxing access to a hugepage. It's also called in the page
@@ -33,7 +36,7 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address,
changed = !pmd_same(*(pmdp), entry);
if (changed) {
__ptep_set_access_flags(pmdp_ptep(pmdp), pmd_pte(entry));
- flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+ flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
}
return changed;
}
@@ -66,7 +69,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
{
pmd_hugepage_update(vma->vm_mm, address, pmdp, _PAGE_PRESENT, 0);
- flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+ flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
/*
* This ensures that generic code that rely on IRQ disabling
* to prevent a parallel THP split work as expected.
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 003ff48a11b6..af897d91d09f 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -171,7 +171,7 @@ redo:
* of process table here. But our linear mapping also enable us to use
* physical address here.
*/
- ppc_md.register_process_table(__pa(process_tb), 0, PRTB_SIZE_SHIFT - 12);
+ register_process_table(__pa(process_tb), 0, PRTB_SIZE_SHIFT - 12);
pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd);
}
@@ -198,7 +198,7 @@ static void __init radix_init_partition_table(void)
void __init radix_init_native(void)
{
- ppc_md.register_process_table = native_register_process_table;
+ register_process_table = native_register_process_table;
}
static int __init get_idx_from_shift(unsigned int shift)
@@ -264,7 +264,7 @@ static int __init radix_dt_scan_page_sizes(unsigned long node,
return 1;
}
-static void __init radix_init_page_sizes(void)
+void __init radix__early_init_devtree(void)
{
int rc;
@@ -343,7 +343,6 @@ void __init radix__early_init_mmu(void)
__pte_frag_nr = H_PTE_FRAG_NR;
__pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT;
- radix_init_page_sizes();
if (!firmware_has_feature(FW_FEATURE_LPAR)) {
radix_init_native();
lpcr = mfspr(SPRN_LPCR);
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index 88a307504b5a..0b6fb244d0a1 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -225,7 +225,7 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
if (!is_vm_hugetlb_page(vma))
assert_pte_locked(vma->vm_mm, address);
__ptep_set_access_flags(ptep, entry);
- flush_tlb_page_nohash(vma, address);
+ flush_tlb_page(vma, address);
}
return changed;
}
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index e1f22700fb16..48df05ef5231 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -140,10 +140,11 @@ void radix__local_flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
}
EXPORT_SYMBOL(radix__local_flush_tlb_pwc);
-void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
- unsigned long ap, int nid)
+void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
+ int psize)
{
unsigned long pid;
+ unsigned long ap = mmu_get_ap(psize);
preempt_disable();
pid = mm ? mm->context.id : 0;
@@ -159,18 +160,12 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd
if (vma && is_vm_hugetlb_page(vma))
return __local_flush_hugetlb_page(vma, vmaddr);
#endif
- radix___local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
- mmu_get_ap(mmu_virtual_psize), 0);
+ radix__local_flush_tlb_page_psize(vma ? vma->vm_mm : NULL, vmaddr,
+ mmu_virtual_psize);
}
EXPORT_SYMBOL(radix__local_flush_tlb_page);
#ifdef CONFIG_SMP
-static int mm_is_core_local(struct mm_struct *mm)
-{
- return cpumask_subset(mm_cpumask(mm),
- topology_sibling_cpumask(smp_processor_id()));
-}
-
void radix__flush_tlb_mm(struct mm_struct *mm)
{
unsigned long pid;
@@ -221,10 +216,11 @@ no_context:
}
EXPORT_SYMBOL(radix__flush_tlb_pwc);
-void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
- unsigned long ap, int nid)
+void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
+ int psize)
{
unsigned long pid;
+ unsigned long ap = mmu_get_ap(psize);
preempt_disable();
pid = mm ? mm->context.id : 0;
@@ -250,8 +246,8 @@ void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
if (vma && is_vm_hugetlb_page(vma))
return flush_hugetlb_page(vma, vmaddr);
#endif
- radix___flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
- mmu_get_ap(mmu_virtual_psize), 0);
+ radix__flush_tlb_page_psize(vma ? vma->vm_mm : NULL, vmaddr,
+ mmu_virtual_psize);
}
EXPORT_SYMBOL(radix__flush_tlb_page);
@@ -299,8 +295,65 @@ static int radix_get_mmu_psize(int page_size)
void radix__tlb_flush(struct mmu_gather *tlb)
{
+ int psize = 0;
struct mm_struct *mm = tlb->mm;
- radix__flush_tlb_mm(mm);
+ int page_size = tlb->page_size;
+
+ psize = radix_get_mmu_psize(page_size);
+ /*
+ * if page size is not something we understand, do a full mm flush
+ */
+ if (psize != -1 && !tlb->fullmm && !tlb->need_flush_all)
+ radix__flush_tlb_range_psize(mm, tlb->start, tlb->end, psize);
+ else
+ radix__flush_tlb_mm(mm);
+}
+
+#define TLB_FLUSH_ALL -1UL
+/*
+ * Number of pages above which we will do a bcast tlbie. Just a
+ * number at this point copied from x86
+ */
+static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
+
+void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
+ unsigned long end, int psize)
+{
+ unsigned long pid;
+ unsigned long addr;
+ int local = mm_is_core_local(mm);
+ unsigned long ap = mmu_get_ap(psize);
+ int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
+ unsigned long page_size = 1UL << mmu_psize_defs[psize].shift;
+
+
+ preempt_disable();
+ pid = mm ? mm->context.id : 0;
+ if (unlikely(pid == MMU_NO_CONTEXT))
+ goto err_out;
+
+ if (end == TLB_FLUSH_ALL ||
+ (end - start) > tlb_single_page_flush_ceiling * page_size) {
+ if (local)
+ _tlbiel_pid(pid, RIC_FLUSH_TLB);
+ else
+ _tlbie_pid(pid, RIC_FLUSH_TLB);
+ goto err_out;
+ }
+ for (addr = start; addr < end; addr += page_size) {
+
+ if (local)
+ _tlbiel_va(addr, pid, ap, RIC_FLUSH_TLB);
+ else {
+ if (lock_tlbie)
+ raw_spin_lock(&native_tlbie_lock);
+ _tlbie_va(addr, pid, ap, RIC_FLUSH_TLB);
+ if (lock_tlbie)
+ raw_spin_unlock(&native_tlbie_lock);
+ }
+ }
+err_out:
+ preempt_enable();
}
void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
@@ -340,3 +393,10 @@ void radix__flush_tlb_lpid(unsigned long lpid)
asm volatile("eieio; tlbsync; ptesync": : :"memory");
}
EXPORT_SYMBOL(radix__flush_tlb_lpid);
+
+void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ radix__flush_tlb_range_psize(vma->vm_mm, start, end, MMU_PAGE_2M);
+}
+EXPORT_SYMBOL(radix__flush_pmd_tlb_range);
diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c
index 558e30cce33e..702d7689d714 100644
--- a/arch/powerpc/mm/tlb_hash32.c
+++ b/arch/powerpc/mm/tlb_hash32.c
@@ -49,17 +49,6 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
EXPORT_SYMBOL(flush_hash_entry);
/*
- * Called by ptep_set_access_flags, must flush on CPUs for which the
- * DSI handler can't just "fixup" the TLB on a write fault
- */
-void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr)
-{
- if (Hash != 0)
- return;
- _tlbie(addr);
-}
-
-/*
* Called at the end of a mmu_gather operation to make sure the
* TLB flush is completely done.
*/
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c
index f4668488512c..050badc0ebd3 100644
--- a/arch/powerpc/mm/tlb_nohash.c
+++ b/arch/powerpc/mm/tlb_nohash.c
@@ -215,12 +215,6 @@ EXPORT_SYMBOL(local_flush_tlb_page);
static DEFINE_RAW_SPINLOCK(tlbivax_lock);
-static int mm_is_core_local(struct mm_struct *mm)
-{
- return cpumask_subset(mm_cpumask(mm),
- topology_sibling_cpumask(smp_processor_id()));
-}
-
struct tlb_flush_param {
unsigned long addr;
unsigned int pid;
diff --git a/arch/powerpc/perf/power9-events-list.h b/arch/powerpc/perf/power9-events-list.h
index cda6fcb809ca..6447dc1c3d89 100644
--- a/arch/powerpc/perf/power9-events-list.h
+++ b/arch/powerpc/perf/power9-events-list.h
@@ -34,15 +34,15 @@ EVENT(PM_L1_ICACHE_MISS, 0x200fd)
/* Instruction Demand sectors wriittent into IL1 */
EVENT(PM_L1_DEMAND_WRITE, 0x0408c)
/* Instruction prefetch written into IL1 */
-EVENT(PM_IC_PREF_WRITE, 0x0408e)
+EVENT(PM_IC_PREF_WRITE, 0x0488c)
/* The data cache was reloaded from local core's L3 due to a demand load */
EVENT(PM_DATA_FROM_L3, 0x4c042)
/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
EVENT(PM_DATA_FROM_L3MISS, 0x300fe)
/* All successful D-side store dispatches for this thread */
-EVENT(PM_L2_ST, 0x16081)
+EVENT(PM_L2_ST, 0x16880)
/* All successful D-side store dispatches for this thread that were L2 Miss */
-EVENT(PM_L2_ST_MISS, 0x26081)
+EVENT(PM_L2_ST_MISS, 0x26880)
/* Total HW L3 prefetches(Load+store) */
EVENT(PM_L3_PREF_ALL, 0x4e052)
/* Data PTEG reload */
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index 3663f71fd913..fbdae8377b71 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -321,6 +321,17 @@ config OF_RTC
Uses information from the OF or flattened device tree to instantiate
platform devices for direct mapped RTC chips like the DS1742 or DS1743.
+config GEN_RTC
+ bool "Use the platform RTC operations from user space"
+ select RTC_CLASS
+ select RTC_DRV_GENERIC
+ help
+ This option provides backwards compatibility with the old gen_rtc.ko
+ module that was traditionally used for old PowerPC machines.
+ Platforms should migrate to enabling the RTC_DRV_GENERIC by hand
+ replacing their get_rtc_time/set_rtc_time callbacks with
+ a proper RTC device driver.
+
config SIMPLE_GPIO
bool "Support for simple, memory-mapped GPIO controllers"
depends on PPC
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 9027d7c48507..f7d1a4953ea0 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -166,7 +166,7 @@ static void invalidate_tce_cache(struct cbe_iommu *iommu, unsigned long *pte,
static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int i;
unsigned long *io_pte, base_pte;
@@ -193,7 +193,7 @@ static int tce_build_cell(struct iommu_table *tbl, long index, long npages,
base_pte = CBE_IOPTE_PP_W | CBE_IOPTE_PP_R | CBE_IOPTE_M |
CBE_IOPTE_SO_RW | (window->ioid & CBE_IOPTE_IOID_Mask);
#endif
- if (unlikely(dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs)))
+ if (unlikely(attrs & DMA_ATTR_WEAK_ORDERING))
base_pte &= ~CBE_IOPTE_SO_RW;
io_pte = (unsigned long *)tbl->it_base + (index - tbl->it_offset);
@@ -526,7 +526,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
__set_bit(0, window->table.it_map);
tce_build_cell(&window->table, window->table.it_offset, 1,
- (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
+ (unsigned long)iommu->pad_page, DMA_TO_DEVICE, 0);
return window;
}
@@ -572,7 +572,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev)
static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (iommu_fixed_is_weak)
return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
@@ -586,7 +586,7 @@ static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
static void dma_fixed_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (iommu_fixed_is_weak)
iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
@@ -598,9 +598,9 @@ static void dma_fixed_free_coherent(struct device *dev, size_t size,
static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
return dma_direct_ops.map_page(dev, page, offset, size,
direction, attrs);
else
@@ -611,9 +611,9 @@ static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page,
static void dma_fixed_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
dma_direct_ops.unmap_page(dev, dma_addr, size, direction,
attrs);
else
@@ -623,9 +623,9 @@ static void dma_fixed_unmap_page(struct device *dev, dma_addr_t dma_addr,
static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
return dma_direct_ops.map_sg(dev, sg, nents, direction, attrs);
else
return ppc_iommu_map_sg(dev, cell_get_iommu_table(dev), sg,
@@ -635,9 +635,9 @@ static int dma_fixed_map_sg(struct device *dev, struct scatterlist *sg,
static void dma_fixed_unmap_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
- if (iommu_fixed_is_weak == dma_get_attr(DMA_ATTR_WEAK_ORDERING, attrs))
+ if (iommu_fixed_is_weak == (attrs & DMA_ATTR_WEAK_ORDERING))
dma_direct_ops.unmap_sg(dev, sg, nents, direction, attrs);
else
ppc_iommu_unmap_sg(cell_get_iommu_table(dev), sg, nents,
@@ -1162,7 +1162,7 @@ static int __init setup_iommu_fixed(char *str)
pciep = of_find_node_by_type(NULL, "pcie-endpoint");
if (strcmp(str, "weak") == 0 || (pciep && strcmp(str, "strong") != 0))
- iommu_fixed_is_weak = 1;
+ iommu_fixed_is_weak = DMA_ATTR_WEAK_ORDERING;
of_node_put(pciep);
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index d17e98bc0c10..e7d075077cb0 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -35,6 +35,7 @@
#include <asm/pgtable.h>
#include <asm/reg.h>
#include <asm/cell-regs.h>
+#include <asm/cpu_has_feature.h>
#include "pervasive.h"
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 5be15cff758d..2975754c65ea 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -496,8 +496,10 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, umode_t mode)
gang = alloc_spu_gang();
SPUFS_I(inode)->i_ctx = NULL;
SPUFS_I(inode)->i_gang = gang;
- if (!gang)
+ if (!gang) {
+ ret = -ENOMEM;
goto out_iput;
+ }
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 43dd3fb514e0..c61667e8bb06 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -88,7 +88,7 @@ static int iommu_table_iobmap_inited;
static int iobmap_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u32 *ip;
u32 rpn;
@@ -187,6 +187,11 @@ static void pci_dma_dev_setup_pasemi(struct pci_dev *dev)
if (dev->vendor == 0x1959 && dev->device == 0xa007 &&
!firmware_has_feature(FW_FEATURE_LPAR)) {
dev->dev.archdata.dma_ops = &dma_direct_ops;
+ /*
+ * Set the coherent DMA mask to prevent the iommu
+ * being used unnecessarily
+ */
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(44);
return;
}
#endif
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
index 4383a5ff82ba..00e1a0195c78 100644
--- a/arch/powerpc/platforms/powernv/npu-dma.c
+++ b/arch/powerpc/platforms/powernv/npu-dma.c
@@ -73,7 +73,7 @@ EXPORT_SYMBOL(pnv_pci_get_npu_dev);
static void *dma_npu_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
NPU_DMA_OP_UNSUPPORTED();
return NULL;
@@ -81,7 +81,7 @@ static void *dma_npu_alloc(struct device *dev, size_t size,
static void dma_npu_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
NPU_DMA_OP_UNSUPPORTED();
}
@@ -89,7 +89,7 @@ static void dma_npu_free(struct device *dev, size_t size,
static dma_addr_t dma_npu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
NPU_DMA_OP_UNSUPPORTED();
return 0;
@@ -97,7 +97,7 @@ static dma_addr_t dma_npu_map_page(struct device *dev, struct page *page,
static int dma_npu_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
NPU_DMA_OP_UNSUPPORTED();
return 0;
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c
index e505223b4ec5..ed8bba68a162 100644
--- a/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ b/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -228,7 +228,8 @@ int __init opal_event_init(void)
}
/* Install interrupt handler */
- rc = request_irq(virq, opal_interrupt, 0, "opal", NULL);
+ rc = request_irq(virq, opal_interrupt, IRQF_TRIGGER_LOW,
+ "opal", NULL);
if (rc) {
irq_dispose_mapping(virq);
pr_warn("Error %d requesting irq %d (0x%x)\n",
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 8b4fc68cebcb..6c9a65b52e63 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -399,6 +399,7 @@ static int opal_recover_mce(struct pt_regs *regs,
if (!(regs->msr & MSR_RI)) {
/* If MSR_RI isn't set, we cannot recover */
+ pr_err("Machine check interrupt unrecoverable: MSR(RI=0)\n");
recovered = 0;
} else if (evt->disposition == MCE_DISPOSITION_RECOVERED) {
/* Platform corrected itself */
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 891fc4a453df..fd9444f9fb0c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -111,10 +111,17 @@ static int __init iommu_setup(char *str)
}
early_param("iommu", iommu_setup);
-static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
+static inline bool pnv_pci_is_m64(struct pnv_phb *phb, struct resource *r)
{
- return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
- (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
+ /*
+ * WARNING: We cannot rely on the resource flags. The Linux PCI
+ * allocation code sometimes decides to put a 64-bit prefetchable
+ * BAR in the 32-bit window, so we have to compare the addresses.
+ *
+ * For simplicity we only test resource start.
+ */
+ return (r->start >= phb->ioda.m64_base &&
+ r->start < (phb->ioda.m64_base + phb->ioda.m64_size));
}
static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
@@ -229,7 +236,7 @@ static void pnv_ioda_reserve_dev_m64_pe(struct pci_dev *pdev,
sgsz = phb->ioda.m64_segsize;
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
r = &pdev->resource[i];
- if (!r->parent || !pnv_pci_is_mem_pref_64(r->flags))
+ if (!r->parent || !pnv_pci_is_m64(phb, r))
continue;
start = _ALIGN_DOWN(r->start - base, sgsz);
@@ -1806,7 +1813,7 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl,
static int pnv_ioda1_tce_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int ret = pnv_tce_build(tbl, index, npages, uaddr, direction,
attrs);
@@ -1877,7 +1884,7 @@ static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm,
unsigned shift, unsigned long index,
unsigned long npages)
{
- __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
+ __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm);
unsigned long start, end, inc;
/* We'll invalidate DMA address in PE scope */
@@ -1950,7 +1957,7 @@ static void pnv_pci_ioda2_tce_invalidate(struct iommu_table *tbl,
static int pnv_ioda2_tce_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int ret = pnv_tce_build(tbl, index, npages, uaddr, direction,
attrs);
@@ -2863,7 +2870,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
res = &pdev->resource[i + PCI_IOV_RESOURCES];
if (!res->flags || res->parent)
continue;
- if (!pnv_pci_is_mem_pref_64(res->flags)) {
+ if (!pnv_pci_is_m64(phb, res)) {
dev_warn(&pdev->dev, "Don't support SR-IOV with"
" non M64 VF BAR%d: %pR. \n",
i, res);
@@ -2958,7 +2965,7 @@ static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
index++;
}
} else if ((res->flags & IORESOURCE_MEM) &&
- !pnv_pci_is_mem_pref_64(res->flags)) {
+ !pnv_pci_is_m64(phb, res)) {
region.start = res->start -
phb->hose->mem_offset[0] -
phb->ioda.m32_pci_base;
@@ -3083,9 +3090,12 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
bridge = bridge->bus->self;
}
- /* We fail back to M32 if M64 isn't supported */
- if (phb->ioda.m64_segsize &&
- pnv_pci_is_mem_pref_64(type))
+ /*
+ * We fall back to M32 if M64 isn't supported. We enforce the M64
+ * alignment for any 64-bit resource, PCIe doesn't care and
+ * bridges only do 64-bit prefetchable anyway.
+ */
+ if (phb->ioda.m64_segsize && (type & IORESOURCE_MEM_64))
return phb->ioda.m64_segsize;
if (type & IORESOURCE_MEM)
return phb->ioda.m32_segsize;
@@ -3125,7 +3135,7 @@ static void pnv_pci_fixup_bridge_resources(struct pci_bus *bus,
w = NULL;
if (r->flags & type & IORESOURCE_IO)
w = &hose->io_resource;
- else if (pnv_pci_is_mem_pref_64(r->flags) &&
+ else if (pnv_pci_is_m64(phb, r) &&
(type & IORESOURCE_PREFETCH) &&
phb->ioda.m64_segsize)
w = &hose->mem_resources[1];
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 6701dd5ded20..a21d831c1114 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -704,7 +704,7 @@ static __be64 *pnv_tce(struct iommu_table *tbl, long idx)
int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 proto_tce = iommu_direction_to_tce_perm(direction);
u64 rpn = __pa(uaddr) >> tbl->it_page_shift;
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index d088d4f06116..e64df7894d6e 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -181,7 +181,7 @@ struct pnv_phb {
extern struct pci_ops pnv_pci_ops;
extern int pnv_tce_build(struct iommu_table *tbl, long index, long npages,
unsigned long uaddr, enum dma_data_direction direction,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void pnv_tce_free(struct iommu_table *tbl, long index, long npages);
extern int pnv_tce_xchg(struct iommu_table *tbl, long index,
unsigned long *hpa, enum dma_data_direction *direction);
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 5606fe36faf2..8af1c15aef85 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -516,7 +516,7 @@ core_initcall(ps3_system_bus_init);
*/
static void * ps3_alloc_coherent(struct device *_dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int result;
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -553,7 +553,7 @@ clean_none:
}
static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -569,7 +569,7 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -592,7 +592,7 @@ static dma_addr_t ps3_sb_map_page(struct device *_dev, struct page *page,
static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -626,7 +626,7 @@ static dma_addr_t ps3_ioc0_map_page(struct device *_dev, struct page *page,
}
static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr,
- size_t size, enum dma_data_direction direction, struct dma_attrs *attrs)
+ size_t size, enum dma_data_direction direction, unsigned long attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
int result;
@@ -640,7 +640,7 @@ static void ps3_unmap_page(struct device *_dev, dma_addr_t dma_addr,
}
static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction direction, unsigned long attrs)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
@@ -670,14 +670,14 @@ static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl,
static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg,
int nents,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG();
return 0;
}
static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction, struct dma_attrs *attrs)
+ int nents, enum dma_data_direction direction, unsigned long attrs)
{
#if defined(CONFIG_PS3_DYNAMIC_DMA)
BUG_ON("do");
@@ -686,7 +686,7 @@ static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg,
static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG();
}
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 791c6142c4a7..11b45b58c81b 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -20,9 +20,9 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/rtc.h>
#include <asm/firmware.h>
-#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 43f7beb2902d..76ec104e88be 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -320,19 +320,6 @@ static int dlpar_remove_device_tree_lmb(struct of_drconf_cell *lmb)
return dlpar_update_device_tree_lmb(lmb);
}
-static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
-{
- unsigned long section_nr;
- struct mem_section *mem_sect;
- struct memory_block *mem_block;
-
- section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
- mem_sect = __nr_to_section(section_nr);
-
- mem_block = find_memory_block(mem_sect);
- return mem_block;
-}
-
#ifdef CONFIG_MEMORY_HOTREMOVE
static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
{
@@ -420,6 +407,19 @@ static bool lmb_is_removable(struct of_drconf_cell *lmb)
static int dlpar_add_lmb(struct of_drconf_cell *);
+static struct memory_block *lmb_to_memblock(struct of_drconf_cell *lmb)
+{
+ unsigned long section_nr;
+ struct mem_section *mem_sect;
+ struct memory_block *mem_block;
+
+ section_nr = pfn_to_section_nr(PFN_DOWN(lmb->base_addr));
+ mem_sect = __nr_to_section(section_nr);
+
+ mem_block = find_memory_block(mem_sect);
+ return mem_block;
+}
+
static int dlpar_remove_lmb(struct of_drconf_cell *lmb)
{
struct memory_block *mem_block;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 770a753b52c9..0024e451bb36 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -123,7 +123,7 @@ static void iommu_pseries_free_group(struct iommu_table_group *table_group,
static int tce_build_pSeries(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 proto_tce;
__be64 *tcep, *tces;
@@ -173,7 +173,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 rc = 0;
u64 proto_tce, tce;
@@ -216,7 +216,7 @@ static DEFINE_PER_CPU(__be64 *, tce_page);
static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 rc = 0;
u64 proto_tce;
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 26904f4879ec..3573d54b2770 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -185,7 +185,7 @@ static void dart_flush(struct iommu_table *tbl)
static int dart_build(struct iommu_table *tbl, long index,
long npages, unsigned long uaddr,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned int *dp, *orig_dp;
unsigned int rpn;
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 984e816f3faf..68e7c0dd2e45 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -491,6 +491,7 @@ int fsl_rio_setup(struct platform_device *dev)
rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
if (!rmu_node) {
dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n");
+ rc = -ENOENT;
goto err_rmu;
}
rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
diff --git a/arch/powerpc/sysdev/xics/Kconfig b/arch/powerpc/sysdev/xics/Kconfig
index 0031eda320c3..385e7aa9e273 100644
--- a/arch/powerpc/sysdev/xics/Kconfig
+++ b/arch/powerpc/sysdev/xics/Kconfig
@@ -1,6 +1,7 @@
config PPC_XICS
def_bool n
select PPC_SMP_MUXED_IPI
+ select HARDIRQS_SW_RESEND
config PPC_ICP_NATIVE
def_bool n
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index 27c936c080a6..1c6bf4b66f56 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -156,7 +156,9 @@ static struct irq_chip ics_opal_irq_chip = {
.irq_mask = ics_opal_mask_irq,
.irq_unmask = ics_opal_unmask_irq,
.irq_eoi = NULL, /* Patched at init time */
- .irq_set_affinity = ics_opal_set_affinity
+ .irq_set_affinity = ics_opal_set_affinity,
+ .irq_set_type = xics_set_irq_type,
+ .irq_retrigger = xics_retrigger,
};
static int ics_opal_map(struct ics *ics, unsigned int virq);
diff --git a/arch/powerpc/sysdev/xics/ics-rtas.c b/arch/powerpc/sysdev/xics/ics-rtas.c
index 3854dd41558d..78ee5c778ef8 100644
--- a/arch/powerpc/sysdev/xics/ics-rtas.c
+++ b/arch/powerpc/sysdev/xics/ics-rtas.c
@@ -163,7 +163,9 @@ static struct irq_chip ics_rtas_irq_chip = {
.irq_mask = ics_rtas_mask_irq,
.irq_unmask = ics_rtas_unmask_irq,
.irq_eoi = NULL, /* Patched at init time */
- .irq_set_affinity = ics_rtas_set_affinity
+ .irq_set_affinity = ics_rtas_set_affinity,
+ .irq_set_type = xics_set_irq_type,
+ .irq_retrigger = xics_retrigger,
};
static int ics_rtas_map(struct ics *ics, unsigned int virq)
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index a795a5f0301c..9d530f479588 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -328,8 +328,12 @@ static int xics_host_map(struct irq_domain *h, unsigned int virq,
pr_devel("xics: map virq %d, hwirq 0x%lx\n", virq, hw);
- /* They aren't all level sensitive but we just don't really know */
- irq_set_status_flags(virq, IRQ_LEVEL);
+ /*
+ * Mark interrupts as edge sensitive by default so that resend
+ * actually works. The device-tree parsing will turn the LSIs
+ * back to level.
+ */
+ irq_clear_status_flags(virq, IRQ_LEVEL);
/* Don't call into ICS for IPIs */
if (hw == XICS_IPI) {
@@ -351,13 +355,54 @@ static int xics_host_xlate(struct irq_domain *h, struct device_node *ct,
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
{
- /* Current xics implementation translates everything
- * to level. It is not technically right for MSIs but this
- * is irrelevant at this point. We might get smarter in the future
- */
*out_hwirq = intspec[0];
- *out_flags = IRQ_TYPE_LEVEL_LOW;
+ /*
+ * If intsize is at least 2, we look for the type in the second cell,
+ * we assume the LSB indicates a level interrupt.
+ */
+ if (intsize > 1) {
+ if (intspec[1] & 1)
+ *out_flags = IRQ_TYPE_LEVEL_LOW;
+ else
+ *out_flags = IRQ_TYPE_EDGE_RISING;
+ } else
+ *out_flags = IRQ_TYPE_LEVEL_LOW;
+
+ return 0;
+}
+
+int xics_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+ /*
+ * We only support these. This has really no effect other than setting
+ * the corresponding descriptor bits mind you but those will in turn
+ * affect the resend function when re-enabling an edge interrupt.
+ *
+ * Set set the default to edge as explained in map().
+ */
+ if (flow_type == IRQ_TYPE_DEFAULT || flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_EDGE_RISING;
+
+ if (flow_type != IRQ_TYPE_EDGE_RISING &&
+ flow_type != IRQ_TYPE_LEVEL_LOW)
+ return -EINVAL;
+
+ irqd_set_trigger_type(d, flow_type);
+
+ return IRQ_SET_MASK_OK_NOCOPY;
+}
+
+int xics_retrigger(struct irq_data *data)
+{
+ /*
+ * We need to push a dummy CPPR when retriggering, since the subsequent
+ * EOI will try to pop it. Passing 0 works, as the function hard codes
+ * the priority value anyway.
+ */
+ xics_push_cppr(0);
+
+ /* Tell the core to do a soft retrigger */
return 0;
}
diff --git a/arch/powerpc/xmon/ppc-dis.c b/arch/powerpc/xmon/ppc-dis.c
index 89098f320ad5..ee9891734149 100644
--- a/arch/powerpc/xmon/ppc-dis.c
+++ b/arch/powerpc/xmon/ppc-dis.c
@@ -20,6 +20,7 @@ along with this file; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#include <asm/cputable.h>
+#include <asm/cpu_has_feature.h>
#include "nonstdio.h"
#include "ansidecl.h"
#include "ppc.h"
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 9e607bf2d640..e751fe25d6ab 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -123,6 +123,7 @@ config S390
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_EARLY_PFN_TO_NID
+ select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_JUMP_LABEL
select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
select HAVE_ARCH_SECCOMP_FILTER
@@ -871,4 +872,17 @@ config S390_GUEST
Select this option if you want to run the kernel as a guest under
the KVM hypervisor.
+config S390_GUEST_OLD_TRANSPORT
+ def_bool y
+ prompt "Guest support for old s390 virtio transport (DEPRECATED)"
+ depends on S390_GUEST
+ help
+ Enable this option to add support for the old s390-virtio
+ transport (i.e. virtio devices NOT based on virtio-ccw). This
+ type of virtio devices is only available on the experimental
+ kuli userspace or with old (< 2.6) qemu. If you are running
+ with a modern version of qemu (which supports virtio-ccw since
+ 1.4 and uses it by default since version 2.4), you probably won't
+ need this.
+
endmenu
diff --git a/arch/s390/boot/compressed/head.S b/arch/s390/boot/compressed/head.S
index f86a4eef28a9..28c4f96a2d9c 100644
--- a/arch/s390/boot/compressed/head.S
+++ b/arch/s390/boot/compressed/head.S
@@ -21,16 +21,21 @@ ENTRY(startup_continue)
lg %r15,.Lstack-.LPG1(%r13)
aghi %r15,-160
brasl %r14,decompress_kernel
- # setup registers for memory mover & branch to target
+ # Set up registers for memory mover. We move the decompressed image to
+ # 0x11000, starting at offset 0x11000 in the decompressed image so
+ # that code living at 0x11000 in the image will end up at 0x11000 in
+ # memory.
lgr %r4,%r2
lg %r2,.Loffset-.LPG1(%r13)
la %r4,0(%r2,%r4)
lg %r3,.Lmvsize-.LPG1(%r13)
lgr %r5,%r3
- # move the memory mover someplace safe
+ # Move the memory mover someplace safe so it doesn't overwrite itself.
la %r1,0x200
mvc 0(mover_end-mover,%r1),mover-.LPG1(%r13)
- # decompress image is started at 0x11000
+ # When the memory mover is done we pass control to
+ # arch/s390/kernel/head64.S:startup_continue which lives at 0x11000 in
+ # the decompressed image.
lgr %r6,%r2
br %r1
mover:
diff --git a/arch/s390/configs/default_defconfig b/arch/s390/configs/default_defconfig
index 889ea3450210..26e0c7f08814 100644
--- a/arch/s390/configs/default_defconfig
+++ b/arch/s390/configs/default_defconfig
@@ -678,7 +678,7 @@ CONFIG_CRYPTO_SHA512_S390=m
CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
CONFIG_X509_CERTIFICATE_PARSER=m
diff --git a/arch/s390/configs/gcov_defconfig b/arch/s390/configs/gcov_defconfig
index 1bcfd764910a..24879dab47bc 100644
--- a/arch/s390/configs/gcov_defconfig
+++ b/arch/s390/configs/gcov_defconfig
@@ -616,7 +616,7 @@ CONFIG_CRYPTO_SHA512_S390=m
CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
CONFIG_X509_CERTIFICATE_PARSER=m
diff --git a/arch/s390/configs/performance_defconfig b/arch/s390/configs/performance_defconfig
index 13ff090139c8..a5c1e5f2a0ca 100644
--- a/arch/s390/configs/performance_defconfig
+++ b/arch/s390/configs/performance_defconfig
@@ -615,7 +615,7 @@ CONFIG_CRYPTO_SHA512_S390=m
CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
CONFIG_CRYPTO_GHASH_S390=m
-CONFIG_CRYPTO_CRC32_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
CONFIG_X509_CERTIFICATE_PARSER=m
diff --git a/arch/s390/crypto/crc32-vx.c b/arch/s390/crypto/crc32-vx.c
index 577ae1d4ae89..2bad9d837029 100644
--- a/arch/s390/crypto/crc32-vx.c
+++ b/arch/s390/crypto/crc32-vx.c
@@ -51,6 +51,9 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size);
struct kernel_fpu vxstate; \
unsigned long prealign, aligned, remaining; \
\
+ if (datalen < VX_MIN_LEN + VX_ALIGN_MASK) \
+ return ___crc32_sw(crc, data, datalen); \
+ \
if ((unsigned long)data & VX_ALIGN_MASK) { \
prealign = VX_ALIGNMENT - \
((unsigned long)data & VX_ALIGN_MASK); \
@@ -59,9 +62,6 @@ u32 crc32c_le_vgfm_16(u32 crc, unsigned char const *buf, size_t size);
data = (void *)((unsigned long)data + prealign); \
} \
\
- if (datalen < VX_MIN_LEN) \
- return ___crc32_sw(crc, data, datalen); \
- \
aligned = datalen & ~VX_ALIGN_MASK; \
remaining = datalen & VX_ALIGN_MASK; \
\
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index ccccebeeaaf6..73610f2e3b4f 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -234,7 +234,7 @@ CONFIG_CRYPTO_SHA256_S390=m
CONFIG_CRYPTO_SHA512_S390=m
CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
-CONFIG_CRYPTO_CRC32_S390=m
+CONFIG_CRYPTO_CRC32_S390=y
CONFIG_CRC7=m
# CONFIG_XZ_DEC_X86 is not set
# CONFIG_XZ_DEC_POWERPC is not set
diff --git a/arch/s390/include/asm/dma-mapping.h b/arch/s390/include/asm/dma-mapping.h
index 3249b7464889..ffaba07f50ab 100644
--- a/arch/s390/include/asm/dma-mapping.h
+++ b/arch/s390/include/asm/dma-mapping.h
@@ -5,7 +5,6 @@
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-debug.h>
#include <linux/io.h>
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 56e4d8234ef2..4431905f8cfa 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -309,7 +309,9 @@ ENTRY(startup_kdump)
l %r15,.Lstack-.LPG0(%r13)
ahi %r15,-STACK_FRAME_OVERHEAD
brasl %r14,verify_facilities
- /* Continue with startup code in head64.S */
+# For uncompressed images, continue in
+# arch/s390/kernel/head64.S. For compressed images, continue in
+# arch/s390/boot/compressed/head.S.
jg startup_continue
.Lstack:
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 3f3ae4865d57..f142215ed30d 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1672,6 +1672,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
KVM_SYNC_CRS |
KVM_SYNC_ARCH0 |
KVM_SYNC_PFAULT;
+ kvm_s390_set_prefix(vcpu, 0);
if (test_kvm_facility(vcpu->kvm, 64))
vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
/* fprs can be synchronized via vrs, even if the guest has no vx. With
@@ -2361,8 +2362,10 @@ retry:
rc = gmap_mprotect_notify(vcpu->arch.gmap,
kvm_s390_get_prefix(vcpu),
PAGE_SIZE * 2, PROT_WRITE);
- if (rc)
+ if (rc) {
+ kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
return rc;
+ }
goto retry;
}
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c
index e390bbb16443..48352bffbc92 100644
--- a/arch/s390/lib/string.c
+++ b/arch/s390/lib/string.c
@@ -237,11 +237,10 @@ char * strrchr(const char * s, int c)
EXPORT_SYMBOL(strrchr);
static inline int clcle(const char *s1, unsigned long l1,
- const char *s2, unsigned long l2,
- int *diff)
+ const char *s2, unsigned long l2)
{
register unsigned long r2 asm("2") = (unsigned long) s1;
- register unsigned long r3 asm("3") = (unsigned long) l2;
+ register unsigned long r3 asm("3") = (unsigned long) l1;
register unsigned long r4 asm("4") = (unsigned long) s2;
register unsigned long r5 asm("5") = (unsigned long) l2;
int cc;
@@ -252,7 +251,6 @@ static inline int clcle(const char *s1, unsigned long l1,
" srl %0,28"
: "=&d" (cc), "+a" (r2), "+a" (r3),
"+a" (r4), "+a" (r5) : : "cc");
- *diff = *(char *)r2 - *(char *)r4;
return cc;
}
@@ -270,9 +268,9 @@ char * strstr(const char * s1,const char * s2)
return (char *) s1;
l1 = __strend(s1) - s1;
while (l1-- >= l2) {
- int cc, dummy;
+ int cc;
- cc = clcle(s1, l1, s2, l2, &dummy);
+ cc = clcle(s1, l2, s2, l2);
if (!cc)
return (char *) s1;
s1++;
@@ -313,11 +311,11 @@ EXPORT_SYMBOL(memchr);
*/
int memcmp(const void *cs, const void *ct, size_t n)
{
- int ret, diff;
+ int ret;
- ret = clcle(cs, n, ct, n, &diff);
+ ret = clcle(cs, n, ct, n);
if (ret)
- ret = diff;
+ ret = ret == 1 ? -1 : 1;
return ret;
}
EXPORT_SYMBOL(memcmp);
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index d96596128e9f..f481fcde067b 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -104,6 +104,7 @@ static inline unsigned long copy_from_user_mvcp(void *x, const void __user *ptr,
unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
{
+ check_object_size(to, n, false);
if (static_branch_likely(&have_mvcos))
return copy_from_user_mvcos(to, from, n);
return copy_from_user_mvcp(to, from, n);
@@ -177,6 +178,7 @@ static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void *x,
unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
{
+ check_object_size(from, n, true);
if (static_branch_likely(&have_mvcos))
return copy_to_user_mvcos(to, from, n);
return copy_to_user_mvcs(to, from, n);
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 7104ffb5a67f..af7cf28cf97e 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -252,6 +252,8 @@ static int change_page_attr(unsigned long addr, unsigned long end,
int rc = -EINVAL;
pgd_t *pgdp;
+ if (addr == end)
+ return 0;
if (end >= MODULES_END)
return -EINVAL;
mutex_lock(&cpa_mutex);
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 070f1ae5cfad..7297fce9bf80 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -286,7 +286,7 @@ static inline void zpci_err_dma(unsigned long rc, unsigned long addr)
static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
unsigned long nr_pages, iommu_page_index;
@@ -332,7 +332,7 @@ out_err:
static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
unsigned long iommu_page_index;
@@ -355,7 +355,7 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr,
static void *s390_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
struct page *page;
@@ -370,7 +370,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
pa = page_to_phys(page);
memset((void *) pa, 0, size);
- map = s390_dma_map_pages(dev, page, 0, size, DMA_BIDIRECTIONAL, NULL);
+ map = s390_dma_map_pages(dev, page, 0, size, DMA_BIDIRECTIONAL, 0);
if (dma_mapping_error(dev, map)) {
free_pages(pa, get_order(size));
return NULL;
@@ -384,19 +384,19 @@ static void *s390_dma_alloc(struct device *dev, size_t size,
static void s390_dma_free(struct device *dev, size_t size,
void *pa, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
size = PAGE_ALIGN(size);
atomic64_sub(size / PAGE_SIZE, &zdev->allocated_pages);
- s390_dma_unmap_pages(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL);
+ s390_dma_unmap_pages(dev, dma_handle, size, DMA_BIDIRECTIONAL, 0);
free_pages((unsigned long) pa, get_order(size));
}
static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nr_elements, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int mapped_elements = 0;
struct scatterlist *s;
@@ -405,7 +405,7 @@ static int s390_dma_map_sg(struct device *dev, struct scatterlist *sg,
for_each_sg(sg, s, nr_elements, i) {
struct page *page = sg_page(s);
s->dma_address = s390_dma_map_pages(dev, page, s->offset,
- s->length, dir, NULL);
+ s->length, dir, 0);
if (!dma_mapping_error(dev, s->dma_address)) {
s->dma_length = s->length;
mapped_elements++;
@@ -419,7 +419,7 @@ unmap:
for_each_sg(sg, s, mapped_elements, i) {
if (s->dma_address)
s390_dma_unmap_pages(dev, s->dma_address, s->dma_length,
- dir, NULL);
+ dir, 0);
s->dma_address = 0;
s->dma_length = 0;
}
@@ -429,13 +429,14 @@ unmap:
static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
int nr_elements, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
for_each_sg(sg, s, nr_elements, i) {
- s390_dma_unmap_pages(dev, s->dma_address, s->dma_length, dir, NULL);
+ s390_dma_unmap_pages(dev, s->dma_address, s->dma_length, dir,
+ 0);
s->dma_address = 0;
s->dma_length = 0;
}
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 0d5f3a9bb315..ee086958b2b2 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -38,6 +38,7 @@ config SUPERH
select GENERIC_IDLE_POLL_SETUP
select GENERIC_CLOCKEVENTS
select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
+ select GENERIC_SCHED_CLOCK
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
@@ -45,6 +46,7 @@ config SUPERH
select OLD_SIGSUSPEND
select OLD_SIGACTION
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_NMI
help
The SuperH is a RISC processor targeted for use in embedded systems
@@ -184,6 +186,12 @@ config CPU_SH2A
select CPU_SH2
select UNCACHED_MAPPING
+config CPU_J2
+ bool
+ select CPU_SH2
+ select OF
+ select OF_EARLY_FLATTREE
+
config CPU_SH3
bool
select CPU_HAS_INTEVT
@@ -250,6 +258,12 @@ config CPU_SUBTYPE_SH7619
select CPU_SH2
select SYS_SUPPORTS_SH_CMT
+config CPU_SUBTYPE_J2
+ bool "Support J2 processor"
+ select CPU_J2
+ select SYS_SUPPORTS_SMP
+ select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+
# SH-2A Processor Support
config CPU_SUBTYPE_SH7201
@@ -739,6 +753,26 @@ endmenu
menu "Boot options"
+config USE_BUILTIN_DTB
+ bool "Use builtin DTB"
+ default n
+ depends on SH_DEVICE_TREE
+ help
+ Link a device tree blob for particular hardware into the kernel,
+ suppressing use of the DTB pointer provided by the bootloader.
+ This option should only be used with legacy bootloaders that are
+ not capable of providing a DTB to the kernel, or for experimental
+ hardware without stable device tree bindings.
+
+config BUILTIN_DTB_SOURCE
+ string "Source file for builtin DTB"
+ default ""
+ depends on USE_BUILTIN_DTB
+ help
+ Base name (without suffix, relative to arch/sh/boot/dts) for the
+ a DTS file that will be used to produce the DTB linked into the
+ kernel.
+
config ZERO_PAGE_OFFSET
hex
default "0x00010000" if PAGE_SIZE_64KB || SH_RTS7751R2D || \
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index bf5b3f5f4962..00476662ac2c 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -31,6 +31,7 @@ isa-y := $(isa-y)-up
endif
cflags-$(CONFIG_CPU_SH2) := $(call cc-option,-m2,)
+cflags-$(CONFIG_CPU_J2) := $(call cc-option,-mj2,)
cflags-$(CONFIG_CPU_SH2A) += $(call cc-option,-m2a,) \
$(call cc-option,-m2a-nofpu,) \
$(call cc-option,-m4-nofpu,)
@@ -130,6 +131,8 @@ head-y := arch/sh/kernel/head_$(BITS).o
core-y += arch/sh/kernel/ arch/sh/mm/ arch/sh/boards/
core-$(CONFIG_SH_FPU_EMU) += arch/sh/math-emu/
+core-$(CONFIG_USE_BUILTIN_DTB) += arch/sh/boot/dts/
+
# Mach groups
machdir-$(CONFIG_SOLUTION_ENGINE) += mach-se
machdir-$(CONFIG_SH_HP6XX) += mach-hp6xx
diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index e0db04664e2e..e9c2c42031fe 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -11,6 +11,7 @@ config SH_DEVICE_TREE
select OF
select OF_EARLY_FLATTREE
select CLKSRC_OF
+ select COMMON_CLK
select GENERIC_CALIBRATE_DELAY
help
Select Board Described by Device Tree to build a kernel that
diff --git a/arch/sh/boards/board-secureedge5410.c b/arch/sh/boards/board-secureedge5410.c
index 98b36205aa7b..97ec67ffec2b 100644
--- a/arch/sh/boards/board-secureedge5410.c
+++ b/arch/sh/boards/board-secureedge5410.c
@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/delay.h>
-#include <linux/module.h>
#include <linux/sched.h>
#include <asm/machvec.h>
#include <mach/secureedge5410.h>
@@ -49,7 +48,7 @@ static int __init eraseconfig_init(void)
irq);
return 0;
}
-module_init(eraseconfig_init);
+device_initcall(eraseconfig_init);
/*
* Initialize IRQ setting
diff --git a/arch/sh/boards/of-generic.c b/arch/sh/boards/of-generic.c
index 911ffb9f115b..1fb6d5714bae 100644
--- a/arch/sh/boards/of-generic.c
+++ b/arch/sh/boards/of-generic.c
@@ -124,13 +124,22 @@ static void __init sh_of_time_init(void)
static void __init sh_of_setup(char **cmdline_p)
{
+ struct device_node *root;
+
+#ifdef CONFIG_USE_BUILTIN_DTB
+ unflatten_and_copy_device_tree();
+#else
unflatten_device_tree();
+#endif
board_time_init = sh_of_time_init;
- sh_mv.mv_name = of_flat_dt_get_machine_name();
- if (!sh_mv.mv_name)
- sh_mv.mv_name = "Unknown SH model";
+ sh_mv.mv_name = "Unknown SH model";
+ root = of_find_node_by_path("/");
+ if (root) {
+ of_property_read_string(root, "model", &sh_mv.mv_name);
+ of_node_put(root);
+ }
sh_of_smp_probe();
}
diff --git a/arch/sh/boot/dts/Makefile b/arch/sh/boot/dts/Makefile
new file mode 100644
index 000000000000..e5ce3a0de7f4
--- /dev/null
+++ b/arch/sh/boot/dts/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_USE_BUILTIN_DTB) += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
+
+clean-files := *.dtb.S
diff --git a/arch/sh/boot/dts/j2_mimas_v2.dts b/arch/sh/boot/dts/j2_mimas_v2.dts
new file mode 100755
index 000000000000..880de75360b3
--- /dev/null
+++ b/arch/sh/boot/dts/j2_mimas_v2.dts
@@ -0,0 +1,96 @@
+/dts-v1/;
+
+/ {
+ compatible = "jcore,j2-soc";
+ model = "J2 FPGA SoC on Mimas v2 board";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&aic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "jcore,j2";
+ reg = <0>;
+ clock-frequency = <50000000>;
+ d-cache-size = <8192>;
+ i-cache-size = <8192>;
+ d-cache-block-size = <16>;
+ i-cache-block-size = <16>;
+ };
+ };
+
+ memory@10000000 {
+ device_type = "memory";
+ reg = <0x10000000 0x4000000>;
+ };
+
+ aliases {
+ serial0 = &uart0;
+ spi0 = &spi0;
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ };
+
+ soc@abcd0000 {
+ compatible = "simple-bus";
+ ranges = <0 0xabcd0000 0x100000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aic: interrupt-controller@200 {
+ compatible = "jcore,aic1";
+ reg = <0x200 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ };
+
+ cache-controller@c0 {
+ compatible = "jcore,cache";
+ reg = <0xc0 4>;
+ };
+
+ timer@200 {
+ compatible = "jcore,pit";
+ reg = <0x200 0x30>;
+ interrupts = <0x48>;
+ };
+
+ spi0: spi@40 {
+ compatible = "jcore,spi2";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi-max-frequency = <25000000>;
+
+ reg = <0x40 0x8>;
+
+ sdcard@0 {
+ compatible = "mmc-spi-slot";
+ reg = <0>;
+ spi-max-frequency = <25000000>;
+ voltage-ranges = <3200 3400>;
+ mode = <0>;
+ };
+ };
+
+ uart0: serial@100 {
+ clock-frequency = <125000000>;
+ compatible = "xlnx,xps-uartlite-1.00.a";
+ current-speed = <19200>;
+ device_type = "serial";
+ interrupts = <0x12>;
+ port-number = <0>;
+ reg = <0x100 0x10>;
+ };
+ };
+};
diff --git a/arch/sh/configs/j2_defconfig b/arch/sh/configs/j2_defconfig
new file mode 100644
index 000000000000..94d1eca52f72
--- /dev/null
+++ b/arch/sh/configs/j2_defconfig
@@ -0,0 +1,40 @@
+CONFIG_SMP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_CPU_SUBTYPE_J2=y
+CONFIG_MEMORY_START=0x10000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_CPU_BIG_ENDIAN=y
+CONFIG_SH_DEVICE_TREE=y
+CONFIG_HZ_100=y
+CONFIG_CMDLINE_OVERWRITE=y
+CONFIG_CMDLINE="console=ttyUL0 earlycon"
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_NETDEVICES=y
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_I2C=y
+CONFIG_SPI=y
+CONFIG_SPI_JCORE=y
+CONFIG_WATCHDOG=y
+CONFIG_MMC=y
+CONFIG_MMC_SPI=y
+CONFIG_CLKSRC_JCORE_PIT=y
+CONFIG_JCORE_AIC=y
+CONFIG_EXT4_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_UTF8=y
diff --git a/arch/sh/drivers/heartbeat.c b/arch/sh/drivers/heartbeat.c
index 7efc9c354fc7..49bace446a1a 100644
--- a/arch/sh/drivers/heartbeat.c
+++ b/arch/sh/drivers/heartbeat.c
@@ -19,7 +19,6 @@
* for more details.
*/
#include <linux/init.h>
-#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/timer.h>
@@ -139,26 +138,11 @@ static int heartbeat_drv_probe(struct platform_device *pdev)
return mod_timer(&hd->timer, jiffies + 1);
}
-static int heartbeat_drv_remove(struct platform_device *pdev)
-{
- struct heartbeat_data *hd = platform_get_drvdata(pdev);
-
- del_timer_sync(&hd->timer);
- iounmap(hd->base);
-
- platform_set_drvdata(pdev, NULL);
-
- if (!pdev->dev.platform_data)
- kfree(hd);
-
- return 0;
-}
-
static struct platform_driver heartbeat_driver = {
.probe = heartbeat_drv_probe,
- .remove = heartbeat_drv_remove,
.driver = {
- .name = DRV_NAME,
+ .name = DRV_NAME,
+ .suppress_bind_attrs = true,
},
};
@@ -167,14 +151,4 @@ static int __init heartbeat_init(void)
printk(KERN_NOTICE DRV_NAME ": version %s loaded\n", DRV_VERSION);
return platform_driver_register(&heartbeat_driver);
}
-
-static void __exit heartbeat_exit(void)
-{
- platform_driver_unregister(&heartbeat_driver);
-}
-module_init(heartbeat_init);
-module_exit(heartbeat_exit);
-
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR("Paul Mundt");
-MODULE_LICENSE("GPL v2");
+device_initcall(heartbeat_init);
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index c399e1c55685..8a7bd80c8b33 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -1,6 +1,12 @@
#ifndef __ASM_SH_ATOMIC_H
#define __ASM_SH_ATOMIC_H
+#if defined(CONFIG_CPU_J2)
+
+#include <asm-generic/atomic.h>
+
+#else
+
/*
* Atomic operations that C can't guarantee us. Useful for
* resource counting etc..
@@ -63,4 +69,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
return c;
}
+#endif /* CONFIG_CPU_J2 */
+
#endif /* __ASM_SH_ATOMIC_H */
diff --git a/arch/sh/include/asm/barrier.h b/arch/sh/include/asm/barrier.h
index 8a84e05adb2e..3c30b6e166b6 100644
--- a/arch/sh/include/asm/barrier.h
+++ b/arch/sh/include/asm/barrier.h
@@ -29,6 +29,11 @@
#define wmb() mb()
#define ctrl_barrier() __icbi(PAGE_OFFSET)
#else
+#if defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
+#define __smp_mb() do { int tmp = 0; __asm__ __volatile__ ("cas.l %0,%0,@%1" : "+r"(tmp) : "z"(&tmp) : "memory", "t"); } while(0)
+#define __smp_rmb() __smp_mb()
+#define __smp_wmb() __smp_mb()
+#endif
#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
#endif
diff --git a/arch/sh/include/asm/bitops-cas.h b/arch/sh/include/asm/bitops-cas.h
new file mode 100644
index 000000000000..88f793c04d3c
--- /dev/null
+++ b/arch/sh/include/asm/bitops-cas.h
@@ -0,0 +1,93 @@
+#ifndef __ASM_SH_BITOPS_CAS_H
+#define __ASM_SH_BITOPS_CAS_H
+
+static inline unsigned __bo_cas(volatile unsigned *p, unsigned old, unsigned new)
+{
+ __asm__ __volatile__("cas.l %1,%0,@r0"
+ : "+r"(new)
+ : "r"(old), "z"(p)
+ : "t", "memory" );
+ return new;
+}
+
+static inline void set_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old|mask) != old);
+}
+
+static inline void clear_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old&~mask) != old);
+}
+
+static inline void change_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old^mask) != old);
+}
+
+static inline int test_and_set_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old|mask) != old);
+
+ return !!(old & mask);
+}
+
+static inline int test_and_clear_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old&~mask) != old);
+
+ return !!(old & mask);
+}
+
+static inline int test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned mask, old;
+ volatile unsigned *a = addr;
+
+ a += nr >> 5;
+ mask = 1U << (nr & 0x1f);
+
+ do old = *a;
+ while (__bo_cas(a, old, old^mask) != old);
+
+ return !!(old & mask);
+}
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#endif /* __ASM_SH_BITOPS_CAS_H */
diff --git a/arch/sh/include/asm/bitops.h b/arch/sh/include/asm/bitops.h
index fc8e652cf173..a8699d60a8c4 100644
--- a/arch/sh/include/asm/bitops.h
+++ b/arch/sh/include/asm/bitops.h
@@ -18,6 +18,8 @@
#include <asm/bitops-op32.h>
#elif defined(CONFIG_CPU_SH4A)
#include <asm/bitops-llsc.h>
+#elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
+#include <asm/bitops-cas.h>
#else
#include <asm-generic/bitops/atomic.h>
#include <asm-generic/bitops/non-atomic.h>
diff --git a/arch/sh/include/asm/cmpxchg-cas.h b/arch/sh/include/asm/cmpxchg-cas.h
new file mode 100644
index 000000000000..d0d86649e8c1
--- /dev/null
+++ b/arch/sh/include/asm/cmpxchg-cas.h
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH_CMPXCHG_CAS_H
+#define __ASM_SH_CMPXCHG_CAS_H
+
+static inline unsigned long
+__cmpxchg_u32(volatile u32 *m, unsigned long old, unsigned long new)
+{
+ __asm__ __volatile__("cas.l %1,%0,@r0"
+ : "+r"(new)
+ : "r"(old), "z"(m)
+ : "t", "memory" );
+ return new;
+}
+
+static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
+{
+ unsigned long old;
+ do old = *m;
+ while (__cmpxchg_u32(m, old, val) != old);
+ return old;
+}
+
+#include <asm/cmpxchg-xchg.h>
+
+#endif /* __ASM_SH_CMPXCHG_CAS_H */
diff --git a/arch/sh/include/asm/cmpxchg-xchg.h b/arch/sh/include/asm/cmpxchg-xchg.h
index 7219719c23a3..1e881f5db659 100644
--- a/arch/sh/include/asm/cmpxchg-xchg.h
+++ b/arch/sh/include/asm/cmpxchg-xchg.h
@@ -21,7 +21,7 @@ static inline u32 __xchg_cmpxchg(volatile void *ptr, u32 x, int size)
int off = (unsigned long)ptr % sizeof(u32);
volatile u32 *p = ptr - off;
#ifdef __BIG_ENDIAN
- int bitoff = (sizeof(u32) - 1 - off) * BITS_PER_BYTE;
+ int bitoff = (sizeof(u32) - size - off) * BITS_PER_BYTE;
#else
int bitoff = off * BITS_PER_BYTE;
#endif
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
index 5225916c1057..3dfe0467a773 100644
--- a/arch/sh/include/asm/cmpxchg.h
+++ b/arch/sh/include/asm/cmpxchg.h
@@ -13,6 +13,8 @@
#include <asm/cmpxchg-grb.h>
#elif defined(CONFIG_CPU_SH4A)
#include <asm/cmpxchg-llsc.h>
+#elif defined(CONFIG_CPU_J2) && defined(CONFIG_SMP)
+#include <asm/cmpxchg-cas.h>
#else
#include <asm/cmpxchg-irq.h>
#endif
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index e11cf0c8206b..0052ad40e86d 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -17,9 +17,9 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
/* arch/sh/mm/consistent.c */
extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void dma_generic_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs);
+ unsigned long attrs);
#endif /* __ASM_SH_DMA_MAPPING_H */
diff --git a/arch/sh/include/asm/futex-cas.h b/arch/sh/include/asm/futex-cas.h
new file mode 100644
index 000000000000..267cb7a5f101
--- /dev/null
+++ b/arch/sh/include/asm/futex-cas.h
@@ -0,0 +1,34 @@
+#ifndef __ASM_SH_FUTEX_CAS_H
+#define __ASM_SH_FUTEX_CAS_H
+
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+ u32 __user *uaddr,
+ u32 oldval, u32 newval)
+{
+ int err = 0;
+ __asm__ __volatile__(
+ "1:\n\t"
+ "cas.l %2, %1, @r0\n"
+ "2:\n\t"
+#ifdef CONFIG_MMU
+ ".section .fixup,\"ax\"\n"
+ "3:\n\t"
+ "mov.l 4f, %0\n\t"
+ "jmp @%0\n\t"
+ " mov %3, %0\n\t"
+ ".balign 4\n"
+ "4: .long 2b\n\t"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n\t"
+ ".long 1b, 3b\n\t"
+ ".previous"
+#endif
+ :"+r" (err), "+r" (newval)
+ :"r" (oldval), "i" (-EFAULT), "z" (uaddr)
+ :"t", "memory");
+ if (err) return err;
+ *uval = newval;
+ return 0;
+}
+
+#endif /* __ASM_SH_FUTEX_CAS_H */
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index 63d33129ea23..ab01dbee0a82 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -1,92 +1,6 @@
#ifndef __ASM_SH_FUTEX_IRQ_H
#define __ASM_SH_FUTEX_IRQ_H
-
-static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
- int *oldval)
-{
- unsigned long flags;
- int ret;
-
- local_irq_save(flags);
-
- ret = get_user(*oldval, uaddr);
- if (!ret)
- ret = put_user(oparg, uaddr);
-
- local_irq_restore(flags);
-
- return ret;
-}
-
-static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
- int *oldval)
-{
- unsigned long flags;
- int ret;
-
- local_irq_save(flags);
-
- ret = get_user(*oldval, uaddr);
- if (!ret)
- ret = put_user(*oldval + oparg, uaddr);
-
- local_irq_restore(flags);
-
- return ret;
-}
-
-static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
- int *oldval)
-{
- unsigned long flags;
- int ret;
-
- local_irq_save(flags);
-
- ret = get_user(*oldval, uaddr);
- if (!ret)
- ret = put_user(*oldval | oparg, uaddr);
-
- local_irq_restore(flags);
-
- return ret;
-}
-
-static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
- int *oldval)
-{
- unsigned long flags;
- int ret;
-
- local_irq_save(flags);
-
- ret = get_user(*oldval, uaddr);
- if (!ret)
- ret = put_user(*oldval & oparg, uaddr);
-
- local_irq_restore(flags);
-
- return ret;
-}
-
-static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
- int *oldval)
-{
- unsigned long flags;
- int ret;
-
- local_irq_save(flags);
-
- ret = get_user(*oldval, uaddr);
- if (!ret)
- ret = put_user(*oldval ^ oparg, uaddr);
-
- local_irq_restore(flags);
-
- return ret;
-}
-
static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
u32 __user *uaddr,
u32 oldval, u32 newval)
diff --git a/arch/sh/include/asm/futex-llsc.h b/arch/sh/include/asm/futex-llsc.h
new file mode 100644
index 000000000000..23591703bec0
--- /dev/null
+++ b/arch/sh/include/asm/futex-llsc.h
@@ -0,0 +1,41 @@
+#ifndef __ASM_SH_FUTEX_LLSC_H
+#define __ASM_SH_FUTEX_LLSC_H
+
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+ u32 __user *uaddr,
+ u32 oldval, u32 newval)
+{
+ int err = 0;
+ __asm__ __volatile__(
+ "synco\n"
+ "1:\n\t"
+ "movli.l @%2, r0\n\t"
+ "mov r0, %1\n\t"
+ "cmp/eq %1, %4\n\t"
+ "bf 2f\n\t"
+ "mov %5, r0\n\t"
+ "movco.l r0, @%2\n\t"
+ "bf 1b\n"
+ "2:\n\t"
+ "synco\n\t"
+#ifdef CONFIG_MMU
+ ".section .fixup,\"ax\"\n"
+ "3:\n\t"
+ "mov.l 4f, %0\n\t"
+ "jmp @%0\n\t"
+ " mov %3, %0\n\t"
+ ".balign 4\n"
+ "4: .long 2b\n\t"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n\t"
+ ".long 1b, 3b\n\t"
+ ".previous"
+#endif
+ :"+r" (err), "=&r" (*uval)
+ :"r" (uaddr), "i" (-EFAULT), "r" (oldval), "r" (newval)
+ :"t", "memory", "r0");
+ if (err) return err;
+ return 0;
+}
+
+#endif /* __ASM_SH_FUTEX_LLSC_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 7be39a646fbd..d0078747d308 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -7,16 +7,34 @@
#include <linux/uaccess.h>
#include <asm/errno.h>
-/* XXX: UP variants, fix for SH-4A and SMP.. */
+#if !defined(CONFIG_SMP)
#include <asm/futex-irq.h>
+#elif defined(CONFIG_CPU_J2)
+#include <asm/futex-cas.h>
+#elif defined(CONFIG_CPU_SH4A)
+#include <asm/futex-llsc.h>
+#else
+#error SMP not supported on this configuration.
+#endif
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+ u32 oldval, u32 newval)
+{
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+ return -EFAULT;
+
+ return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
+}
static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
{
int op = (encoded_op >> 28) & 7;
int cmp = (encoded_op >> 24) & 15;
- int oparg = (encoded_op << 8) >> 20;
- int cmparg = (encoded_op << 20) >> 20;
- int oldval = 0, ret;
+ u32 oparg = (encoded_op << 8) >> 20;
+ u32 cmparg = (encoded_op << 20) >> 20;
+ u32 oldval, newval, prev;
+ int ret;
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
oparg = 1 << oparg;
@@ -26,26 +44,39 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
pagefault_disable();
- switch (op) {
- case FUTEX_OP_SET:
- ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
- break;
- case FUTEX_OP_ADD:
- ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
- break;
- case FUTEX_OP_OR:
- ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
- break;
- case FUTEX_OP_ANDN:
- ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
- break;
- case FUTEX_OP_XOR:
- ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
- break;
- default:
- ret = -ENOSYS;
- break;
- }
+ do {
+ if (op == FUTEX_OP_SET)
+ ret = oldval = 0;
+ else
+ ret = get_user(oldval, uaddr);
+
+ if (ret) break;
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ newval = oparg;
+ break;
+ case FUTEX_OP_ADD:
+ newval = oldval + oparg;
+ break;
+ case FUTEX_OP_OR:
+ newval = oldval | oparg;
+ break;
+ case FUTEX_OP_ANDN:
+ newval = oldval & ~oparg;
+ break;
+ case FUTEX_OP_XOR:
+ newval = oldval ^ oparg;
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ if (ret) break;
+
+ ret = futex_atomic_cmpxchg_inatomic(&prev, uaddr, oldval, newval);
+ } while (!ret && prev != oldval);
pagefault_enable();
@@ -53,10 +84,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
switch (cmp) {
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
- case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
- case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
- case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
- case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = ((int)oldval < (int)cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = ((int)oldval >= (int)cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = ((int)oldval <= (int)cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = ((int)oldval > (int)cmparg); break;
default: ret = -ENOSYS;
}
}
@@ -64,15 +95,5 @@ static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
return ret;
}
-static inline int
-futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
- u32 oldval, u32 newval)
-{
- if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
- return -EFAULT;
-
- return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
-}
-
#endif /* __KERNEL__ */
#endif /* __ASM_SH_FUTEX_H */
diff --git a/arch/sh/include/asm/mc146818rtc.h b/arch/sh/include/asm/mc146818rtc.h
deleted file mode 100644
index 0aee96a97330..000000000000
--- a/arch/sh/include/asm/mc146818rtc.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Machine dependent access functions for RTC registers.
- */
-#ifndef _ASM_MC146818RTC_H
-#define _ASM_MC146818RTC_H
-
-#endif /* _ASM_MC146818RTC_H */
diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h
index 1506897648aa..f9a09942a32d 100644
--- a/arch/sh/include/asm/processor.h
+++ b/arch/sh/include/asm/processor.h
@@ -15,7 +15,7 @@
*/
enum cpu_type {
/* SH-2 types */
- CPU_SH7619,
+ CPU_SH7619, CPU_J2,
/* SH-2A types */
CPU_SH7201, CPU_SH7203, CPU_SH7206, CPU_SH7263, CPU_SH7264, CPU_SH7269,
diff --git a/arch/sh/include/asm/rtc.h b/arch/sh/include/asm/rtc.h
index 52b0c2dba979..f7b010d48af7 100644
--- a/arch/sh/include/asm/rtc.h
+++ b/arch/sh/include/asm/rtc.h
@@ -6,17 +6,6 @@ extern void (*board_time_init)(void);
extern void (*rtc_sh_get_time)(struct timespec *);
extern int (*rtc_sh_set_time)(const time_t);
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100 /* battery bad */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
-struct rtc_time;
-unsigned int get_rtc_time(struct rtc_time *);
-int set_rtc_time(struct rtc_time *);
-
#define RTC_CAP_4_DIGIT_YEAR (1 << 0)
struct sh_rtc_platform_info {
diff --git a/arch/sh/include/asm/spinlock-cas.h b/arch/sh/include/asm/spinlock-cas.h
new file mode 100644
index 000000000000..c46e8cc7b515
--- /dev/null
+++ b/arch/sh/include/asm/spinlock-cas.h
@@ -0,0 +1,117 @@
+/*
+ * include/asm-sh/spinlock-cas.h
+ *
+ * Copyright (C) 2015 SEI
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SPINLOCK_CAS_H
+#define __ASM_SH_SPINLOCK_CAS_H
+
+#include <asm/barrier.h>
+#include <asm/processor.h>
+
+static inline unsigned __sl_cas(volatile unsigned *p, unsigned old, unsigned new)
+{
+ __asm__ __volatile__("cas.l %1,%0,@r0"
+ : "+r"(new)
+ : "r"(old), "z"(p)
+ : "t", "memory" );
+ return new;
+}
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+#define arch_spin_is_locked(x) ((x)->lock <= 0)
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+
+static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
+{
+ smp_cond_load_acquire(&lock->lock, VAL > 0);
+}
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ while (!__sl_cas(&lock->lock, 1, 0));
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ __sl_cas(&lock->lock, 0, 1);
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ return __sl_cas(&lock->lock, 1, 0);
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts but no interrupt
+ * writers. For those circumstances we can "mix" irq-safe locks - any writer
+ * needs to get a irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+
+/**
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_read_can_lock(x) ((x)->lock > 0)
+
+/**
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+ unsigned old;
+ do old = rw->lock;
+ while (!old || __sl_cas(&rw->lock, old, old-1) != old);
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+ unsigned old;
+ do old = rw->lock;
+ while (__sl_cas(&rw->lock, old, old+1) != old);
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ while (__sl_cas(&rw->lock, RW_LOCK_BIAS, 0) != RW_LOCK_BIAS);
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+ __sl_cas(&rw->lock, 0, RW_LOCK_BIAS);
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+ unsigned old;
+ do old = rw->lock;
+ while (old && __sl_cas(&rw->lock, old, old-1) != old);
+ return !!old;
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ return __sl_cas(&rw->lock, RW_LOCK_BIAS, 0) == RW_LOCK_BIAS;
+}
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#define arch_spin_relax(lock) cpu_relax()
+#define arch_read_relax(lock) cpu_relax()
+#define arch_write_relax(lock) cpu_relax()
+
+#endif /* __ASM_SH_SPINLOCK_CAS_H */
diff --git a/arch/sh/include/asm/spinlock-llsc.h b/arch/sh/include/asm/spinlock-llsc.h
new file mode 100644
index 000000000000..cec78143fa83
--- /dev/null
+++ b/arch/sh/include/asm/spinlock-llsc.h
@@ -0,0 +1,224 @@
+/*
+ * include/asm-sh/spinlock-llsc.h
+ *
+ * Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2006, 2007 Akio Idehara
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_SH_SPINLOCK_LLSC_H
+#define __ASM_SH_SPINLOCK_LLSC_H
+
+#include <asm/barrier.h>
+#include <asm/processor.h>
+
+/*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+ */
+
+#define arch_spin_is_locked(x) ((x)->lock <= 0)
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+
+static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
+{
+ smp_cond_load_acquire(&lock->lock, VAL > 0);
+}
+
+/*
+ * Simple spin lock operations. There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ unsigned long tmp;
+ unsigned long oldval;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%2, %0 ! arch_spin_lock \n\t"
+ "mov %0, %1 \n\t"
+ "mov #0, %0 \n\t"
+ "movco.l %0, @%2 \n\t"
+ "bf 1b \n\t"
+ "cmp/pl %1 \n\t"
+ "bf 1b \n\t"
+ : "=&z" (tmp), "=&r" (oldval)
+ : "r" (&lock->lock)
+ : "t", "memory"
+ );
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+ "mov #1, %0 ! arch_spin_unlock \n\t"
+ "mov.l %0, @%1 \n\t"
+ : "=&z" (tmp)
+ : "r" (&lock->lock)
+ : "t", "memory"
+ );
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ unsigned long tmp, oldval;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%2, %0 ! arch_spin_trylock \n\t"
+ "mov %0, %1 \n\t"
+ "mov #0, %0 \n\t"
+ "movco.l %0, @%2 \n\t"
+ "bf 1b \n\t"
+ "synco \n\t"
+ : "=&z" (tmp), "=&r" (oldval)
+ : "r" (&lock->lock)
+ : "t", "memory"
+ );
+
+ return oldval;
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts but no interrupt
+ * writers. For those circumstances we can "mix" irq-safe locks - any writer
+ * needs to get a irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+
+/**
+ * read_can_lock - would read_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_read_can_lock(x) ((x)->lock > 0)
+
+/**
+ * write_can_lock - would write_trylock() succeed?
+ * @lock: the rwlock in question.
+ */
+#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%1, %0 ! arch_read_lock \n\t"
+ "cmp/pl %0 \n\t"
+ "bf 1b \n\t"
+ "add #-1, %0 \n\t"
+ "movco.l %0, @%1 \n\t"
+ "bf 1b \n\t"
+ : "=&z" (tmp)
+ : "r" (&rw->lock)
+ : "t", "memory"
+ );
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%1, %0 ! arch_read_unlock \n\t"
+ "add #1, %0 \n\t"
+ "movco.l %0, @%1 \n\t"
+ "bf 1b \n\t"
+ : "=&z" (tmp)
+ : "r" (&rw->lock)
+ : "t", "memory"
+ );
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%1, %0 ! arch_write_lock \n\t"
+ "cmp/hs %2, %0 \n\t"
+ "bf 1b \n\t"
+ "sub %2, %0 \n\t"
+ "movco.l %0, @%1 \n\t"
+ "bf 1b \n\t"
+ : "=&z" (tmp)
+ : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
+ : "t", "memory"
+ );
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+ __asm__ __volatile__ (
+ "mov.l %1, @%0 ! arch_write_unlock \n\t"
+ :
+ : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
+ : "t", "memory"
+ );
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+ unsigned long tmp, oldval;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%2, %0 ! arch_read_trylock \n\t"
+ "mov %0, %1 \n\t"
+ "cmp/pl %0 \n\t"
+ "bf 2f \n\t"
+ "add #-1, %0 \n\t"
+ "movco.l %0, @%2 \n\t"
+ "bf 1b \n\t"
+ "2: \n\t"
+ "synco \n\t"
+ : "=&z" (tmp), "=&r" (oldval)
+ : "r" (&rw->lock)
+ : "t", "memory"
+ );
+
+ return (oldval > 0);
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ unsigned long tmp, oldval;
+
+ __asm__ __volatile__ (
+ "1: \n\t"
+ "movli.l @%2, %0 ! arch_write_trylock \n\t"
+ "mov %0, %1 \n\t"
+ "cmp/hs %3, %0 \n\t"
+ "bf 2f \n\t"
+ "sub %3, %0 \n\t"
+ "2: \n\t"
+ "movco.l %0, @%2 \n\t"
+ "bf 1b \n\t"
+ "synco \n\t"
+ : "=&z" (tmp), "=&r" (oldval)
+ : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
+ : "t", "memory"
+ );
+
+ return (oldval > (RW_LOCK_BIAS - 1));
+}
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#define arch_spin_relax(lock) cpu_relax()
+#define arch_read_relax(lock) cpu_relax()
+#define arch_write_relax(lock) cpu_relax()
+
+#endif /* __ASM_SH_SPINLOCK_LLSC_H */
diff --git a/arch/sh/include/asm/spinlock.h b/arch/sh/include/asm/spinlock.h
index 416834b60ad0..c2c61ea6a8e2 100644
--- a/arch/sh/include/asm/spinlock.h
+++ b/arch/sh/include/asm/spinlock.h
@@ -11,222 +11,12 @@
#ifndef __ASM_SH_SPINLOCK_H
#define __ASM_SH_SPINLOCK_H
-/*
- * The only locking implemented here uses SH-4A opcodes. For others,
- * split this out as per atomic-*.h.
- */
-#ifndef CONFIG_CPU_SH4A
-#error "Need movli.l/movco.l for spinlocks"
+#if defined(CONFIG_CPU_SH4A)
+#include <asm/spinlock-llsc.h>
+#elif defined(CONFIG_CPU_J2)
+#include <asm/spinlock-cas.h>
+#else
+#error "The configured cpu type does not support spinlocks"
#endif
-#include <asm/barrier.h>
-#include <asm/processor.h>
-
-/*
- * Your basic SMP spinlocks, allowing only a single CPU anywhere
- */
-
-#define arch_spin_is_locked(x) ((x)->lock <= 0)
-#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
-
-static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
-{
- smp_cond_load_acquire(&lock->lock, VAL > 0);
-}
-
-/*
- * Simple spin lock operations. There are two variants, one clears IRQ's
- * on the local processor, one does not.
- *
- * We make no fairness assumptions. They have a cost.
- */
-static inline void arch_spin_lock(arch_spinlock_t *lock)
-{
- unsigned long tmp;
- unsigned long oldval;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%2, %0 ! arch_spin_lock \n\t"
- "mov %0, %1 \n\t"
- "mov #0, %0 \n\t"
- "movco.l %0, @%2 \n\t"
- "bf 1b \n\t"
- "cmp/pl %1 \n\t"
- "bf 1b \n\t"
- : "=&z" (tmp), "=&r" (oldval)
- : "r" (&lock->lock)
- : "t", "memory"
- );
-}
-
-static inline void arch_spin_unlock(arch_spinlock_t *lock)
-{
- unsigned long tmp;
-
- __asm__ __volatile__ (
- "mov #1, %0 ! arch_spin_unlock \n\t"
- "mov.l %0, @%1 \n\t"
- : "=&z" (tmp)
- : "r" (&lock->lock)
- : "t", "memory"
- );
-}
-
-static inline int arch_spin_trylock(arch_spinlock_t *lock)
-{
- unsigned long tmp, oldval;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%2, %0 ! arch_spin_trylock \n\t"
- "mov %0, %1 \n\t"
- "mov #0, %0 \n\t"
- "movco.l %0, @%2 \n\t"
- "bf 1b \n\t"
- "synco \n\t"
- : "=&z" (tmp), "=&r" (oldval)
- : "r" (&lock->lock)
- : "t", "memory"
- );
-
- return oldval;
-}
-
-/*
- * Read-write spinlocks, allowing multiple readers but only one writer.
- *
- * NOTE! it is quite common to have readers in interrupts but no interrupt
- * writers. For those circumstances we can "mix" irq-safe locks - any writer
- * needs to get a irq-safe write-lock, but readers can get non-irqsafe
- * read-locks.
- */
-
-/**
- * read_can_lock - would read_trylock() succeed?
- * @lock: the rwlock in question.
- */
-#define arch_read_can_lock(x) ((x)->lock > 0)
-
-/**
- * write_can_lock - would write_trylock() succeed?
- * @lock: the rwlock in question.
- */
-#define arch_write_can_lock(x) ((x)->lock == RW_LOCK_BIAS)
-
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
- unsigned long tmp;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%1, %0 ! arch_read_lock \n\t"
- "cmp/pl %0 \n\t"
- "bf 1b \n\t"
- "add #-1, %0 \n\t"
- "movco.l %0, @%1 \n\t"
- "bf 1b \n\t"
- : "=&z" (tmp)
- : "r" (&rw->lock)
- : "t", "memory"
- );
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
- unsigned long tmp;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%1, %0 ! arch_read_unlock \n\t"
- "add #1, %0 \n\t"
- "movco.l %0, @%1 \n\t"
- "bf 1b \n\t"
- : "=&z" (tmp)
- : "r" (&rw->lock)
- : "t", "memory"
- );
-}
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
- unsigned long tmp;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%1, %0 ! arch_write_lock \n\t"
- "cmp/hs %2, %0 \n\t"
- "bf 1b \n\t"
- "sub %2, %0 \n\t"
- "movco.l %0, @%1 \n\t"
- "bf 1b \n\t"
- : "=&z" (tmp)
- : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
- : "t", "memory"
- );
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
- __asm__ __volatile__ (
- "mov.l %1, @%0 ! arch_write_unlock \n\t"
- :
- : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
- : "t", "memory"
- );
-}
-
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
- unsigned long tmp, oldval;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%2, %0 ! arch_read_trylock \n\t"
- "mov %0, %1 \n\t"
- "cmp/pl %0 \n\t"
- "bf 2f \n\t"
- "add #-1, %0 \n\t"
- "movco.l %0, @%2 \n\t"
- "bf 1b \n\t"
- "2: \n\t"
- "synco \n\t"
- : "=&z" (tmp), "=&r" (oldval)
- : "r" (&rw->lock)
- : "t", "memory"
- );
-
- return (oldval > 0);
-}
-
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
- unsigned long tmp, oldval;
-
- __asm__ __volatile__ (
- "1: \n\t"
- "movli.l @%2, %0 ! arch_write_trylock \n\t"
- "mov %0, %1 \n\t"
- "cmp/hs %3, %0 \n\t"
- "bf 2f \n\t"
- "sub %3, %0 \n\t"
- "2: \n\t"
- "movco.l %0, @%2 \n\t"
- "bf 1b \n\t"
- "synco \n\t"
- : "=&z" (tmp), "=&r" (oldval)
- : "r" (&rw->lock), "r" (RW_LOCK_BIAS)
- : "t", "memory"
- );
-
- return (oldval > (RW_LOCK_BIAS - 1));
-}
-
-#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
-#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
-
-#define arch_spin_relax(lock) cpu_relax()
-#define arch_read_relax(lock) cpu_relax()
-#define arch_write_relax(lock) cpu_relax()
-
#endif /* __ASM_SH_SPINLOCK_H */
diff --git a/arch/sh/include/uapi/asm/cpu-features.h b/arch/sh/include/uapi/asm/cpu-features.h
index 694abe490edb..2f1bc851042a 100644
--- a/arch/sh/include/uapi/asm/cpu-features.h
+++ b/arch/sh/include/uapi/asm/cpu-features.h
@@ -22,5 +22,6 @@
#define CPU_HAS_L2_CACHE 0x0080 /* Secondary cache / URAM */
#define CPU_HAS_OP32 0x0100 /* 32-bit instruction support */
#define CPU_HAS_PTEAEX 0x0200 /* PTE ASID Extension support */
+#define CPU_HAS_CAS_L 0x0400 /* cas.l atomic compare-and-swap */
#endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/arch/sh/include/uapi/asm/sigcontext.h b/arch/sh/include/uapi/asm/sigcontext.h
index 8ce1435bc0bf..faa5d0833412 100644
--- a/arch/sh/include/uapi/asm/sigcontext.h
+++ b/arch/sh/include/uapi/asm/sigcontext.h
@@ -25,8 +25,6 @@ struct sigcontext {
unsigned long sc_mach;
unsigned long sc_macl;
-#if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \
- defined(__SH2A__) || defined(CONFIG_CPU_SH2A)
/* FPU registers */
unsigned long sc_fpregs[16];
unsigned long sc_xfpregs[16];
@@ -34,7 +32,6 @@ struct sigcontext {
unsigned int sc_fpul;
unsigned int sc_ownedfp;
#endif
-#endif
};
#endif /* __ASM_SH_SIGCONTEXT_H */
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h
index d13a1d623736..c801bde9e6f5 100644
--- a/arch/sh/include/uapi/asm/unistd_32.h
+++ b/arch/sh/include/uapi/asm/unistd_32.h
@@ -380,7 +380,21 @@
#define __NR_process_vm_writev 366
#define __NR_kcmp 367
#define __NR_finit_module 368
+#define __NR_sched_getattr 369
+#define __NR_sched_setattr 370
+#define __NR_renameat2 371
+#define __NR_seccomp 372
+#define __NR_getrandom 373
+#define __NR_memfd_create 374
+#define __NR_bpf 375
+#define __NR_execveat 376
+#define __NR_userfaultfd 377
+#define __NR_membarrier 378
+#define __NR_mlock2 379
+#define __NR_copy_file_range 380
+#define __NR_preadv2 381
+#define __NR_pwritev2 382
-#define NR_syscalls 369
+#define NR_syscalls 383
#endif /* __ASM_SH_UNISTD_32_H */
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
index 47ebd5b5ed55..ce0cb3598b62 100644
--- a/arch/sh/include/uapi/asm/unistd_64.h
+++ b/arch/sh/include/uapi/asm/unistd_64.h
@@ -400,7 +400,21 @@
#define __NR_process_vm_writev 377
#define __NR_kcmp 378
#define __NR_finit_module 379
+#define __NR_sched_getattr 380
+#define __NR_sched_setattr 381
+#define __NR_renameat2 382
+#define __NR_seccomp 383
+#define __NR_getrandom 384
+#define __NR_memfd_create 385
+#define __NR_bpf 386
+#define __NR_execveat 387
+#define __NR_userfaultfd 388
+#define __NR_membarrier 389
+#define __NR_mlock2 390
+#define __NR_copy_file_range 391
+#define __NR_preadv2 392
+#define __NR_pwritev2 393
-#define NR_syscalls 380
+#define NR_syscalls 394
#endif /* __ASM_SH_UNISTD_64_H */
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 4187cf4fe185..fca9b1e78a63 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -24,11 +24,13 @@ int __init clk_init(void)
{
int ret;
+#ifndef CONFIG_COMMON_CLK
ret = arch_clk_init();
if (unlikely(ret)) {
pr_err("%s: CPU clock registration failed.\n", __func__);
return ret;
}
+#endif
if (sh_mv.mv_clk_init) {
ret = sh_mv.mv_clk_init();
@@ -39,11 +41,13 @@ int __init clk_init(void)
}
}
+#ifndef CONFIG_COMMON_CLK
/* Kick the child clocks.. */
recalculate_root_clocks();
/* Enable the necessary init clocks */
clk_enable_init_clocks();
+#endif
return ret;
}
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 0d7360d549c1..c8b3be1b54e6 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -106,7 +106,7 @@ void __attribute__ ((weak)) l2_cache_init(void)
/*
* Generic first-level cache init
*/
-#ifdef CONFIG_SUPERH32
+#if defined(CONFIG_SUPERH32) && !defined(CONFIG_CPU_J2)
static void cache_init(void)
{
unsigned long ccr, flags;
@@ -323,9 +323,13 @@ asmlinkage void cpu_init(void)
cache_init();
if (raw_smp_processor_id() == 0) {
+#ifdef CONFIG_MMU
shm_align_mask = max_t(unsigned long,
current_cpu_data.dcache.way_size - 1,
PAGE_SIZE - 1);
+#else
+ shm_align_mask = PAGE_SIZE - 1;
+#endif
/* Boot CPU sets the cache shape */
detect_cache_shape();
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
index 9e6624c9108b..4df4b284f591 100644
--- a/arch/sh/kernel/cpu/proc.c
+++ b/arch/sh/kernel/cpu/proc.c
@@ -27,6 +27,7 @@ static const char *cpu_name[] = {
[CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
[CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
[CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
+ [CPU_J2] = "J2",
[CPU_SH_NONE] = "Unknown"
};
diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile
index f0f059acfcfb..904c4283d923 100644
--- a/arch/sh/kernel/cpu/sh2/Makefile
+++ b/arch/sh/kernel/cpu/sh2/Makefile
@@ -5,3 +5,7 @@
obj-y := ex.o probe.o entry.o
obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
+
+# SMP setup
+smp-$(CONFIG_CPU_J2) := smp-j2.o
+obj-$(CONFIG_SMP) += $(smp-y)
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index a1505956ef28..1ee0a6e774c6 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -47,6 +47,13 @@ ENTRY(exception_handler)
mov.l r3,@-sp
cli
mov.l $cpu_mode,r2
+#ifdef CONFIG_SMP
+ mov.l $cpuid,r3
+ mov.l @r3,r3
+ mov.l @r3,r3
+ shll2 r3
+ add r3,r2
+#endif
mov.l @r2,r0
mov.l @(5*4,r15),r3 ! previous SR
or r0,r3 ! set MD
@@ -57,6 +64,13 @@ ENTRY(exception_handler)
mov.l __md_bit,r0
mov.l r0,@r2 ! enter kernel mode
mov.l $current_thread_info,r2
+#ifdef CONFIG_SMP
+ mov.l $cpuid,r0
+ mov.l @r0,r0
+ mov.l @r0,r0
+ shll2 r0
+ add r0,r2
+#endif
mov.l @r2,r2
mov #(THREAD_SIZE >> 8),r0
shll8 r0
@@ -147,6 +161,11 @@ ENTRY(exception_handler)
mov #31,r8
cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 31 is trap
+#ifdef CONFIG_CPU_J2
+ mov #16,r8
+ cmp/hs r8,r9
+ bt interrupt_entry ! 31 > vec >= 16 is interrupt
+#endif
mov.l 4f,r8
mov r9,r4
@@ -260,6 +279,13 @@ restore_all:
lds.l @r0+,macl
mov r15,r0
mov.l $cpu_mode,r2
+#ifdef CONFIG_SMP
+ mov.l $cpuid,r3
+ mov.l @r3,r3
+ mov.l @r3,r3
+ shll2 r3
+ add r3,r2
+#endif
mov #OFF_SR,r3
mov.l @(r0,r3),r1
mov.l __md_bit,r3
@@ -276,6 +302,13 @@ restore_all:
mov.l r1,@r2 ! set pc
get_current_thread_info r0, r1
mov.l $current_thread_info,r1
+#ifdef CONFIG_SMP
+ mov.l $cpuid,r3
+ mov.l @r3,r3
+ mov.l @r3,r3
+ shll2 r3
+ add r3,r1
+#endif
mov.l r0,@r1
mov.l @r15+,r0
mov.l @r15+,r1
@@ -303,19 +336,41 @@ $current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
+#ifdef CONFIG_SMP
+$cpuid:
+ .long sh2_cpuid_addr
+#endif
! common exception handler
#include "../../entry-common.S"
+
+#ifdef CONFIG_NR_CPUS
+#define NR_CPUS CONFIG_NR_CPUS
+#else
+#define NR_CPUS 1
+#endif
.data
! cpu operation mode
! bit30 = MD (compatible SH3/4)
__cpu_mode:
+ .rept NR_CPUS
.long 0x40000000
+ .endr
+
+#ifdef CONFIG_SMP
+.global sh2_cpuid_addr
+sh2_cpuid_addr:
+ .long dummy_cpuid
+dummy_cpuid:
+ .long 0
+#endif
.section .bss
__current_thread_info:
+ .rept NR_CPUS
.long 0
+ .endr
ENTRY(exception_handling_table)
.space 4*32
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 6c687ae812ef..4205f6d42b69 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -10,10 +10,27 @@
* for more details.
*/
#include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/smp.h>
+#include <linux/io.h>
#include <asm/processor.h>
#include <asm/cache.h>
-void cpu_probe(void)
+#if defined(CONFIG_CPU_J2)
+extern u32 __iomem *j2_ccr_base;
+static int __init scan_cache(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ if (!of_flat_dt_is_compatible(node, "jcore,cache"))
+ return 0;
+
+ j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node);
+
+ return 1;
+}
+#endif
+
+void __ref cpu_probe(void)
{
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
boot_cpu_data.type = CPU_SH7619;
@@ -24,10 +41,30 @@ void cpu_probe(void)
boot_cpu_data.dcache.linesz = L1_CACHE_BYTES;
boot_cpu_data.dcache.flags = 0;
#endif
+
+#if defined(CONFIG_CPU_J2)
+ unsigned cpu = hard_smp_processor_id();
+ if (cpu == 0) of_scan_flat_dt(scan_cache, NULL);
+ if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu);
+ if (cpu != 0) return;
+ boot_cpu_data.type = CPU_J2;
+
+ /* These defaults are appropriate for the original/current
+ * J2 cache. Once there is a proper framework for getting cache
+ * info from device tree, we should switch to that. */
+ boot_cpu_data.dcache.ways = 1;
+ boot_cpu_data.dcache.sets = 256;
+ boot_cpu_data.dcache.entry_shift = 5;
+ boot_cpu_data.dcache.linesz = 32;
+ boot_cpu_data.dcache.flags = 0;
+
+ boot_cpu_data.flags |= CPU_HAS_CAS_L;
+#else
/*
* SH-2 doesn't have separate caches
*/
boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
+#endif
boot_cpu_data.icache = boot_cpu_data.dcache;
boot_cpu_data.family = CPU_FAMILY_SH2;
}
diff --git a/arch/sh/kernel/cpu/sh2/smp-j2.c b/arch/sh/kernel/cpu/sh2/smp-j2.c
new file mode 100644
index 000000000000..6ccd7e4dc008
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/smp-j2.c
@@ -0,0 +1,139 @@
+/*
+ * SMP support for J2 processor
+ *
+ * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/cmpxchg.h>
+
+DEFINE_PER_CPU(unsigned, j2_ipi_messages);
+
+extern u32 *sh2_cpuid_addr;
+static u32 *j2_ipi_trigger;
+static int j2_ipi_irq;
+
+static irqreturn_t j2_ipi_interrupt_handler(int irq, void *arg)
+{
+ unsigned cpu = hard_smp_processor_id();
+ volatile unsigned *pmsg = &per_cpu(j2_ipi_messages, cpu);
+ unsigned messages, i;
+
+ do messages = *pmsg;
+ while (cmpxchg(pmsg, messages, 0) != messages);
+
+ if (!messages) return IRQ_NONE;
+
+ for (i=0; i<SMP_MSG_NR; i++)
+ if (messages & (1U<<i))
+ smp_message_recv(i);
+
+ return IRQ_HANDLED;
+}
+
+static void j2_smp_setup(void)
+{
+}
+
+static void j2_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *np;
+ unsigned i, max = 1;
+
+ np = of_find_compatible_node(NULL, NULL, "jcore,ipi-controller");
+ if (!np)
+ goto out;
+
+ j2_ipi_irq = irq_of_parse_and_map(np, 0);
+ j2_ipi_trigger = of_iomap(np, 0);
+ if (!j2_ipi_irq || !j2_ipi_trigger)
+ goto out;
+
+ np = of_find_compatible_node(NULL, NULL, "jcore,cpuid-mmio");
+ if (!np)
+ goto out;
+
+ sh2_cpuid_addr = of_iomap(np, 0);
+ if (!sh2_cpuid_addr)
+ goto out;
+
+ if (request_irq(j2_ipi_irq, j2_ipi_interrupt_handler, IRQF_PERCPU,
+ "ipi", (void *)j2_ipi_interrupt_handler) != 0)
+ goto out;
+
+ max = max_cpus;
+out:
+ /* Disable any cpus past max_cpus, or all secondaries if we didn't
+ * get the necessary resources to support SMP. */
+ for (i=max; i<NR_CPUS; i++) {
+ set_cpu_possible(i, false);
+ set_cpu_present(i, false);
+ }
+}
+
+static void j2_start_cpu(unsigned int cpu, unsigned long entry_point)
+{
+ struct device_node *np;
+ u32 regs[2];
+ void __iomem *release, *initpc;
+
+ if (!cpu) return;
+
+ np = of_get_cpu_node(cpu, NULL);
+ if (!np) return;
+
+ if (of_property_read_u32_array(np, "cpu-release-addr", regs, 2)) return;
+ release = ioremap_nocache(regs[0], sizeof(u32));
+ initpc = ioremap_nocache(regs[1], sizeof(u32));
+
+ __raw_writel(entry_point, initpc);
+ __raw_writel(1, release);
+
+ iounmap(initpc);
+ iounmap(release);
+
+ pr_info("J2 SMP: requested start of cpu %u\n", cpu);
+}
+
+static unsigned int j2_smp_processor_id(void)
+{
+ return __raw_readl(sh2_cpuid_addr);
+}
+
+static void j2_send_ipi(unsigned int cpu, unsigned int message)
+{
+ volatile unsigned *pmsg;
+ unsigned old;
+ unsigned long val;
+
+ /* There is only one IPI interrupt shared by all messages, so
+ * we keep a separate interrupt flag per message type in sw. */
+ pmsg = &per_cpu(j2_ipi_messages, cpu);
+ do old = *pmsg;
+ while (cmpxchg(pmsg, old, old|(1U<<message)) != old);
+
+ /* Generate the actual interrupt by writing to CCRn bit 28. */
+ val = __raw_readl(j2_ipi_trigger + cpu);
+ __raw_writel(val | (1U<<28), j2_ipi_trigger + cpu);
+}
+
+static struct plat_smp_ops j2_smp_ops = {
+ .smp_setup = j2_smp_setup,
+ .prepare_cpus = j2_prepare_cpus,
+ .start_cpu = j2_start_cpu,
+ .smp_processor_id = j2_smp_processor_id,
+ .send_ipi = j2_send_ipi,
+ .cpu_die = native_cpu_die,
+ .cpu_disable = native_cpu_disable,
+ .play_dead = native_play_dead,
+};
+
+CPU_METHOD_OF_DECLARE(j2_cpu_method, "jcore,spin-table", &j2_smp_ops);
diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c
index 5b0bfcda6d0b..eadb669a7329 100644
--- a/arch/sh/kernel/dma-nommu.c
+++ b/arch/sh/kernel/dma-nommu.c
@@ -13,7 +13,7 @@
static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t addr = page_to_phys(page) + offset;
@@ -25,7 +25,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
static int nommu_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 9d209a07235e..e1d751ae2498 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -1009,10 +1009,8 @@ static void __init dwarf_unwinder_cleanup(void)
rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node)
kfree(cie);
- if (dwarf_reg_pool)
- mempool_destroy(dwarf_reg_pool);
- if (dwarf_frame_pool)
- mempool_destroy(dwarf_frame_pool);
+ mempool_destroy(dwarf_reg_pool);
+ mempool_destroy(dwarf_frame_pool);
kmem_cache_destroy(dwarf_reg_cachep);
kmem_cache_destroy(dwarf_frame_cachep);
}
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S
index 974bc152cc84..4e352c3f79e6 100644
--- a/arch/sh/kernel/head_32.S
+++ b/arch/sh/kernel/head_32.S
@@ -67,7 +67,7 @@ ENTRY(_stext)
ldc r0, r6_bank
#endif
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_FLATTREE
mov r4, r12 ! Store device tree blob pointer in r12
#endif
@@ -318,7 +318,7 @@ ENTRY(_stext)
10:
#endif
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_FLATTREE
mov.l 8f, r0 ! Make flat device tree available early.
jsr @r0
mov r12, r4
@@ -349,7 +349,7 @@ ENTRY(stack_start)
5: .long start_kernel
6: .long cpu_init
7: .long init_thread_union
-#if defined(CONFIG_OF)
+#if defined(CONFIG_OF_FLATTREE)
8: .long sh_fdt_init
#endif
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 5d34605b58b5..e7b49d81053e 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -242,7 +242,7 @@ void __init __weak plat_early_device_setup(void)
{
}
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_FLATTREE
void __ref sh_fdt_init(phys_addr_t dt_phys)
{
static int done = 0;
@@ -251,7 +251,11 @@ void __ref sh_fdt_init(phys_addr_t dt_phys)
/* Avoid calling an __init function on secondary cpus. */
if (done) return;
+#ifdef CONFIG_USE_BUILTIN_DTB
+ dt_virt = __dtb_start;
+#else
dt_virt = phys_to_virt(dt_phys);
+#endif
if (!dt_virt || !early_init_dt_scan(dt_virt)) {
pr_crit("Error: invalid device tree blob"
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 734234be2f01..254bc22ee57d 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -386,3 +386,17 @@ ENTRY(sys_call_table)
.long sys_process_vm_writev
.long sys_kcmp
.long sys_finit_module
+ .long sys_sched_getattr
+ .long sys_sched_setattr /* 370 */
+ .long sys_renameat2
+ .long sys_seccomp
+ .long sys_getrandom
+ .long sys_memfd_create
+ .long sys_bpf /* 375 */
+ .long sys_execveat
+ .long sys_userfaultfd
+ .long sys_membarrier
+ .long sys_mlock2
+ .long sys_copy_file_range /* 380 */
+ .long sys_preadv2
+ .long sys_pwritev2
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 579fcb9a896b..d6a27f7a4c54 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -406,3 +406,17 @@ sys_call_table:
.long sys_process_vm_writev
.long sys_kcmp
.long sys_finit_module
+ .long sys_sched_getattr /* 380 */
+ .long sys_sched_setattr
+ .long sys_renameat2
+ .long sys_seccomp
+ .long sys_getrandom
+ .long sys_memfd_create /* 385 */
+ .long sys_bpf
+ .long sys_execveat
+ .long sys_userfaultfd
+ .long sys_membarrier
+ .long sys_mlock2 /* 390 */
+ .long sys_copy_file_range
+ .long sys_preadv2
+ .long sys_pwritev2
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index d6d0a986c6e9..fcd5e41977d1 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -11,7 +11,6 @@
* for more details.
*/
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/profile.h>
#include <linux/timex.h>
@@ -50,27 +49,31 @@ int update_persistent_clock(struct timespec now)
}
#endif
-unsigned int get_rtc_time(struct rtc_time *tm)
+static int rtc_generic_get_time(struct device *dev, struct rtc_time *tm)
{
- if (rtc_sh_get_time != null_rtc_get_time) {
- struct timespec tv;
+ struct timespec tv;
- rtc_sh_get_time(&tv);
- rtc_time_to_tm(tv.tv_sec, tm);
- }
-
- return RTC_24H;
+ rtc_sh_get_time(&tv);
+ rtc_time_to_tm(tv.tv_sec, tm);
+ return 0;
}
-EXPORT_SYMBOL(get_rtc_time);
-int set_rtc_time(struct rtc_time *tm)
+static int rtc_generic_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned long secs;
rtc_tm_to_time(tm, &secs);
- return rtc_sh_set_time(secs);
+ if ((rtc_sh_set_time == null_rtc_set_time) ||
+ (rtc_sh_set_time(secs) < 0))
+ return -EOPNOTSUPP;
+
+ return 0;
}
-EXPORT_SYMBOL(set_rtc_time);
+
+static const struct rtc_class_ops rtc_generic_ops = {
+ .read_time = rtc_generic_get_time,
+ .set_time = rtc_generic_set_time,
+};
static int __init rtc_generic_init(void)
{
@@ -79,11 +82,14 @@ static int __init rtc_generic_init(void)
if (rtc_sh_get_time == null_rtc_get_time)
return -ENODEV;
- pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
+ pdev = platform_device_register_data(NULL, "rtc-generic", -1,
+ &rtc_generic_ops,
+ sizeof(rtc_generic_ops));
+
return PTR_ERR_OR_ZERO(pdev);
}
-module_init(rtc_generic_init);
+device_initcall(rtc_generic_init);
void (*board_time_init)(void);
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index cee6b9999d86..92c3bd96aee5 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -4,7 +4,8 @@
obj-y := alignment.o cache.o init.o consistent.o mmap.o
-cacheops-$(CONFIG_CPU_SH2) := cache-sh2.o
+cacheops-$(CONFIG_CPU_J2) := cache-j2.o
+cacheops-$(CONFIG_CPU_SUBTYPE_SH7619) := cache-sh2.o
cacheops-$(CONFIG_CPU_SH2A) := cache-sh2a.o
cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o
cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o
diff --git a/arch/sh/mm/asids-debugfs.c b/arch/sh/mm/asids-debugfs.c
index ecfc6b0c1da1..bf95fdaedd0c 100644
--- a/arch/sh/mm/asids-debugfs.c
+++ b/arch/sh/mm/asids-debugfs.c
@@ -17,7 +17,6 @@
* for more details.
*/
#include <linux/init.h>
-#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
@@ -70,6 +69,4 @@ static int __init asids_debugfs_init(void)
return PTR_ERR_OR_ZERO(asids_dentry);
}
-module_init(asids_debugfs_init);
-
-MODULE_LICENSE("GPL v2");
+device_initcall(asids_debugfs_init);
diff --git a/arch/sh/mm/cache-j2.c b/arch/sh/mm/cache-j2.c
new file mode 100644
index 000000000000..391698bcac5b
--- /dev/null
+++ b/arch/sh/mm/cache-j2.c
@@ -0,0 +1,65 @@
+/*
+ * arch/sh/mm/cache-j2.c
+ *
+ * Copyright (C) 2015-2016 Smart Energy Instruments, Inc.
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/cpumask.h>
+
+#include <asm/cache.h>
+#include <asm/addrspace.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+
+#define ICACHE_ENABLE 0x1
+#define DCACHE_ENABLE 0x2
+#define CACHE_ENABLE (ICACHE_ENABLE | DCACHE_ENABLE)
+#define ICACHE_FLUSH 0x100
+#define DCACHE_FLUSH 0x200
+#define CACHE_FLUSH (ICACHE_FLUSH | DCACHE_FLUSH)
+
+u32 __iomem *j2_ccr_base;
+
+static void j2_flush_icache(void *args)
+{
+ unsigned cpu;
+ for_each_possible_cpu(cpu)
+ __raw_writel(CACHE_ENABLE | ICACHE_FLUSH, j2_ccr_base + cpu);
+}
+
+static void j2_flush_dcache(void *args)
+{
+ unsigned cpu;
+ for_each_possible_cpu(cpu)
+ __raw_writel(CACHE_ENABLE | DCACHE_FLUSH, j2_ccr_base + cpu);
+}
+
+static void j2_flush_both(void *args)
+{
+ unsigned cpu;
+ for_each_possible_cpu(cpu)
+ __raw_writel(CACHE_ENABLE | CACHE_FLUSH, j2_ccr_base + cpu);
+}
+
+void __init j2_cache_init(void)
+{
+ if (!j2_ccr_base)
+ return;
+
+ local_flush_cache_all = j2_flush_both;
+ local_flush_cache_mm = j2_flush_both;
+ local_flush_cache_dup_mm = j2_flush_both;
+ local_flush_cache_page = j2_flush_both;
+ local_flush_cache_range = j2_flush_both;
+ local_flush_dcache_page = j2_flush_dcache;
+ local_flush_icache_range = j2_flush_icache;
+ local_flush_icache_page = j2_flush_icache;
+ local_flush_cache_sigtramp = j2_flush_icache;
+
+ pr_info("Initial J2 CCR is %.8x\n", __raw_readl(j2_ccr_base));
+}
diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
index e58cfbf45150..36554a9ea99b 100644
--- a/arch/sh/mm/cache.c
+++ b/arch/sh/mm/cache.c
@@ -42,6 +42,8 @@ static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
{
preempt_disable();
+ /* Needing IPI for cross-core flush is SHX3-specific. */
+#ifdef CONFIG_CPU_SHX3
/*
* It's possible that this gets called early on when IRQs are
* still disabled due to ioremapping by the boot CPU, so don't
@@ -49,6 +51,7 @@ static inline void cacheop_on_each_cpu(void (*func) (void *info), void *info,
*/
if (num_online_cpus() > 1)
smp_call_function(func, info, wait);
+#endif
func(info);
@@ -244,7 +247,11 @@ void flush_cache_sigtramp(unsigned long address)
static void compute_alias(struct cache_info *c)
{
+#ifdef CONFIG_MMU
c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
+#else
+ c->alias_mask = 0;
+#endif
c->n_aliases = c->alias_mask ? (c->alias_mask >> PAGE_SHIFT) + 1 : 0;
}
@@ -305,7 +312,11 @@ void __init cpu_cache_init(void)
if (unlikely(cache_disabled))
goto skip;
- if (boot_cpu_data.family == CPU_FAMILY_SH2) {
+ if (boot_cpu_data.type == CPU_J2) {
+ extern void __weak j2_cache_init(void);
+
+ j2_cache_init();
+ } else if (boot_cpu_data.family == CPU_FAMILY_SH2) {
extern void __weak sh2_cache_init(void);
sh2_cache_init();
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index b81d9dbf9fef..92b6976fde59 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -34,7 +34,7 @@ fs_initcall(dma_init);
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret, *ret_nocache;
int order = get_order(size);
@@ -66,7 +66,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
void dma_generic_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int order = get_order(size);
unsigned long pfn = dma_handle >> PAGE_SHIFT;
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 546293d9e6c5..59b09600dd32 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -43,6 +43,7 @@ config SPARC
select OLD_SIGSUSPEND
select ARCH_HAS_SG_CHAIN
select CPU_NO_EFFICIENT_FFS
+ select HAVE_ARCH_HARDENED_USERCOPY
config SPARC32
def_bool !64BIT
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index 57f26c398dc9..4dd268a3a8b0 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -140,16 +140,6 @@ void ioport_unmap(void __iomem *);
struct pci_dev;
void pci_iounmap(struct pci_dev *dev, void __iomem *);
-
-
-/*
- * At the moment, we do not use CMOS_READ anywhere outside of rtc.c,
- * so rtc_port is static in it. This should not change unless a new
- * hardware pops up.
- */
-#define RTC_PORT(x) (rtc_port + (x))
-#define RTC_ALWAYS_BCD 0
-
static inline int sbus_can_dma_64bit(void)
{
return 0; /* actually, sparc_cpu_model==sun4d */
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
index 57aca2792d29..341a5a133f48 100644
--- a/arch/sparc/include/asm/uaccess_32.h
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -248,22 +248,28 @@ unsigned long __copy_user(void __user *to, const void __user *from, unsigned lon
static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
{
- if (n && __access_ok((unsigned long) to, n))
+ if (n && __access_ok((unsigned long) to, n)) {
+ if (!__builtin_constant_p(n))
+ check_object_size(from, n, true);
return __copy_user(to, (__force void __user *) from, n);
- else
+ } else
return n;
}
static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
{
+ if (!__builtin_constant_p(n))
+ check_object_size(from, n, true);
return __copy_user(to, (__force void __user *) from, n);
}
static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
{
- if (n && __access_ok((unsigned long) from, n))
+ if (n && __access_ok((unsigned long) from, n)) {
+ if (!__builtin_constant_p(n))
+ check_object_size(to, n, false);
return __copy_user((__force void __user *) to, from, n);
- else
+ } else
return n;
}
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
index e9a51d64974d..8bda94fab8e8 100644
--- a/arch/sparc/include/asm/uaccess_64.h
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -210,8 +210,12 @@ unsigned long copy_from_user_fixup(void *to, const void __user *from,
static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long size)
{
- unsigned long ret = ___copy_from_user(to, from, size);
+ unsigned long ret;
+ if (!__builtin_constant_p(size))
+ check_object_size(to, size, false);
+
+ ret = ___copy_from_user(to, from, size);
if (unlikely(ret))
ret = copy_from_user_fixup(to, from, size);
@@ -227,8 +231,11 @@ unsigned long copy_to_user_fixup(void __user *to, const void *from,
static inline unsigned long __must_check
copy_to_user(void __user *to, const void *from, unsigned long size)
{
- unsigned long ret = ___copy_to_user(to, from, size);
+ unsigned long ret;
+ if (!__builtin_constant_p(size))
+ check_object_size(from, size, true);
+ ret = ___copy_to_user(to, from, size);
if (unlikely(ret))
ret = copy_to_user_fixup(to, from, size);
return ret;
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 37686828c3d9..5c615abff030 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -196,7 +196,7 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long order, first_page;
struct iommu *iommu;
@@ -245,7 +245,7 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
static void dma_4u_free_coherent(struct device *dev, size_t size,
void *cpu, dma_addr_t dvma,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu *iommu;
unsigned long order, npages;
@@ -263,7 +263,7 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t sz,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu *iommu;
struct strbuf *strbuf;
@@ -385,7 +385,7 @@ do_flush_sync:
static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
size_t sz, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu *iommu;
struct strbuf *strbuf;
@@ -431,7 +431,7 @@ static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s, *outs, *segstart;
unsigned long flags, handle, prot, ctx;
@@ -607,7 +607,7 @@ static unsigned long fetch_sg_ctx(struct iommu *iommu, struct scatterlist *sg)
static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long flags, ctx;
struct scatterlist *sg;
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index ffd5ff4678cf..2344103414d1 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -260,7 +260,7 @@ EXPORT_SYMBOL(sbus_set_sbus64);
*/
static void *sbus_alloc_coherent(struct device *dev, size_t len,
dma_addr_t *dma_addrp, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct platform_device *op = to_platform_device(dev);
unsigned long len_total = PAGE_ALIGN(len);
@@ -315,7 +315,7 @@ err_nopages:
}
static void sbus_free_coherent(struct device *dev, size_t n, void *p,
- dma_addr_t ba, struct dma_attrs *attrs)
+ dma_addr_t ba, unsigned long attrs)
{
struct resource *res;
struct page *pgv;
@@ -355,7 +355,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
static dma_addr_t sbus_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t len,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *va = page_address(page) + offset;
@@ -371,20 +371,20 @@ static dma_addr_t sbus_map_page(struct device *dev, struct page *page,
}
static void sbus_unmap_page(struct device *dev, dma_addr_t ba, size_t n,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
mmu_release_scsi_one(dev, ba, n);
}
static int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
mmu_get_scsi_sgl(dev, sg, n);
return n;
}
static void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
mmu_release_scsi_sgl(dev, sg, n);
}
@@ -429,7 +429,7 @@ arch_initcall(sparc_register_ioport);
*/
static void *pci32_alloc_coherent(struct device *dev, size_t len,
dma_addr_t *pba, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long len_total = PAGE_ALIGN(len);
void *va;
@@ -482,7 +482,7 @@ err_nopages:
* past this call are illegal.
*/
static void pci32_free_coherent(struct device *dev, size_t n, void *p,
- dma_addr_t ba, struct dma_attrs *attrs)
+ dma_addr_t ba, unsigned long attrs)
{
struct resource *res;
@@ -518,14 +518,14 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
/* IIep is write-through, not flushing. */
return page_to_phys(page) + offset;
}
static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
if (dir != PCI_DMA_TODEVICE)
dma_make_coherent(ba, PAGE_ALIGN(size));
@@ -548,7 +548,7 @@ static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
*/
static int pci32_map_sg(struct device *device, struct scatterlist *sgl,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int n;
@@ -567,7 +567,7 @@ static int pci32_map_sg(struct device *device, struct scatterlist *sgl,
*/
static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int n;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 836e8cef47e2..61c6f935accc 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -130,7 +130,7 @@ static inline long iommu_batch_end(void)
static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long flags, order, first_page, npages, n;
struct iommu *iommu;
@@ -213,7 +213,7 @@ static void dma_4v_iommu_demap(void *demap_arg, unsigned long entry,
}
static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
- dma_addr_t dvma, struct dma_attrs *attrs)
+ dma_addr_t dvma, unsigned long attrs)
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
@@ -235,7 +235,7 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t sz,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu *iommu;
unsigned long flags, npages, oaddr;
@@ -294,7 +294,7 @@ iommu_map_fail:
static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
size_t sz, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
@@ -322,7 +322,7 @@ static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s, *outs, *segstart;
unsigned long flags, handle, prot;
@@ -466,7 +466,7 @@ iommu_map_failed:
static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct pci_pbm_info *pbm;
struct scatterlist *sg;
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 7d02b1fef025..d79b3b734245 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -150,6 +150,13 @@ SECTIONS
}
PERCPU_SECTION(SMP_CACHE_BYTES)
+#ifdef CONFIG_JUMP_LABEL
+ . = ALIGN(PAGE_SIZE);
+ .exit.text : {
+ EXIT_TEXT
+ }
+#endif
+
. = ALIGN(PAGE_SIZE);
__init_end = .;
BSS_SECTION(0, 0, 0)
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index b6bc0547a4f6..09bb774b39cd 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -34,7 +34,7 @@
static void *tile_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 dma_mask = (dev && dev->coherent_dma_mask) ?
dev->coherent_dma_mask : DMA_BIT_MASK(32);
@@ -78,7 +78,7 @@ static void *tile_dma_alloc_coherent(struct device *dev, size_t size,
*/
static void tile_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
homecache_free_pages((unsigned long)vaddr, get_order(size));
}
@@ -202,7 +202,7 @@ static void __dma_complete_pa_range(dma_addr_t dma_addr, size_t size,
static int tile_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -224,7 +224,7 @@ static int tile_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static void tile_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -240,7 +240,7 @@ static void tile_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
static dma_addr_t tile_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(!valid_dma_direction(direction));
@@ -252,7 +252,7 @@ static dma_addr_t tile_dma_map_page(struct device *dev, struct page *page,
static void tile_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(!valid_dma_direction(direction));
@@ -343,7 +343,7 @@ EXPORT_SYMBOL(tile_dma_map_ops);
static void *tile_pci_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int node = dev_to_node(dev);
int order = get_order(size);
@@ -368,14 +368,14 @@ static void *tile_pci_dma_alloc_coherent(struct device *dev, size_t size,
*/
static void tile_pci_dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
homecache_free_pages((unsigned long)vaddr, get_order(size));
}
static int tile_pci_dma_map_sg(struct device *dev, struct scatterlist *sglist,
int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -400,7 +400,7 @@ static int tile_pci_dma_map_sg(struct device *dev, struct scatterlist *sglist,
static void tile_pci_dma_unmap_sg(struct device *dev,
struct scatterlist *sglist, int nents,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -416,7 +416,7 @@ static void tile_pci_dma_unmap_sg(struct device *dev,
static dma_addr_t tile_pci_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(!valid_dma_direction(direction));
@@ -429,7 +429,7 @@ static dma_addr_t tile_pci_dma_map_page(struct device *dev, struct page *page,
static void tile_pci_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
BUG_ON(!valid_dma_direction(direction));
@@ -531,7 +531,7 @@ EXPORT_SYMBOL(gx_pci_dma_map_ops);
#ifdef CONFIG_SWIOTLB
static void *tile_swiotlb_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
gfp |= GFP_DMA;
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
@@ -539,7 +539,7 @@ static void *tile_swiotlb_alloc_coherent(struct device *dev, size_t size,
static void tile_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
}
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 378f5d8d1ec8..9d449caf8910 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -60,6 +60,18 @@ SECTIONS
/* "Init" is divided into two areas with very different virtual addresses. */
INIT_TEXT_SECTION(PAGE_SIZE)
+ /*
+ * Some things, like the __jump_table, may contain symbol references
+ * to __exit text, so include such text in the final image if so.
+ * In that case we also override the _einittext from INIT_TEXT_SECTION.
+ */
+#ifdef CONFIG_JUMP_LABEL
+ .exit.text : {
+ EXIT_TEXT
+ _einittext = .;
+ }
+#endif
+
/* Now we skip back to PAGE_OFFSET for the data. */
. = (. - TEXT_OFFSET + PAGE_OFFSET);
#undef LOAD_OFFSET
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index 58650d098fb4..fd443852103c 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -1,10 +1,12 @@
config UML
bool
default y
+ select ARCH_HAS_KCOV
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_UID16
select HAVE_FUTEX_CMPXCHG if FUTEX
+ select HAVE_DEBUG_KMEMLEAK
select GENERIC_IRQ_SHOW
select GENERIC_CPU_DEVICES
select GENERIC_IO
@@ -31,10 +33,9 @@ config PCI
config PCMCIA
bool
-# Yet to do!
config TRACE_IRQFLAGS_SUPPORT
bool
- default n
+ default y
config LOCKDEP_SUPPORT
bool
diff --git a/arch/um/include/asm/irqflags.h b/arch/um/include/asm/irqflags.h
index c780d8a16773..3bb221e1d5a4 100644
--- a/arch/um/include/asm/irqflags.h
+++ b/arch/um/include/asm/irqflags.h
@@ -6,37 +6,33 @@ extern int set_signals(int enable);
extern void block_signals(void);
extern void unblock_signals(void);
+#define arch_local_save_flags arch_local_save_flags
static inline unsigned long arch_local_save_flags(void)
{
return get_signals();
}
+#define arch_local_irq_restore arch_local_irq_restore
static inline void arch_local_irq_restore(unsigned long flags)
{
set_signals(flags);
}
+#define arch_local_irq_enable arch_local_irq_enable
static inline void arch_local_irq_enable(void)
{
unblock_signals();
}
+#define arch_local_irq_disable arch_local_irq_disable
static inline void arch_local_irq_disable(void)
{
block_signals();
}
-static inline unsigned long arch_local_irq_save(void)
-{
- unsigned long flags;
- flags = arch_local_save_flags();
- arch_local_irq_disable();
- return flags;
-}
+#define ARCH_IRQ_DISABLED 0
+#define ARCh_IRQ_ENABLED (SIGIO|SIGVTALRM)
-static inline bool arch_irqs_disabled(void)
-{
- return arch_local_save_flags() == 0;
-}
+#include <asm-generic/irqflags.h>
#endif
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index a6a5e42caaef..2f36d515762e 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -3,6 +3,11 @@
# Licensed under the GPL
#
+# Don't instrument UML-specific code; without this, we may crash when
+# accessing the instrumentation buffer for the first time from the
+# kernel.
+KCOV_INSTRUMENT := n
+
CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
-DELF_ARCH=$(LDS_ELF_ARCH) \
-DELF_FORMAT=$(LDS_ELF_FORMAT) \
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 55cead809b18..48bae81f8dca 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -37,8 +37,6 @@ static int __init read_initrd(void)
}
area = alloc_bootmem(size);
- if (area == NULL)
- return 0;
if (load_initrd(initrd, area, size) == -1)
return 0;
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 16630e75f056..e8175a8aa22c 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -319,9 +319,6 @@ int __init linux_main(int argc, char **argv)
start_vm = VMALLOC_START;
- setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
- mem_total_pages(physmem_size, iomem_size, highmem);
-
virtmem_size = physmem_size;
stack = (unsigned long) argv;
stack &= ~(1024 * 1024 - 1);
@@ -334,7 +331,6 @@ int __init linux_main(int argc, char **argv)
printf("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
- stack_protections((unsigned long) &init_thread_info);
os_flush_stdout();
return start_uml();
@@ -342,6 +338,10 @@ int __init linux_main(int argc, char **argv)
void __init setup_arch(char **cmdline_p)
{
+ stack_protections((unsigned long) &init_thread_info);
+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
+ mem_total_pages(physmem_size, iomem_size, highmem);
+
paging_init();
strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 08ff5094fcdd..ada473bf6f46 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,6 +3,9 @@
# Licensed under the GPL
#
+# Don't instrument UML-specific code
+KCOV_INSTRUMENT := n
+
obj-y = aio.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
registers.o sigio.o signal.o start_up.o time.o tty.o \
umid.o user_syms.o util.o drivers/ skas/
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 8acaf4e384c0..a86d7cc2c2d8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,6 +15,7 @@
#include <kern_util.h>
#include <os.h>
#include <sysdep/mcontext.h>
+#include <um_malloc.h>
void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
[SIGTRAP] = relay_signal,
@@ -32,7 +33,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
struct uml_pt_regs *r;
int save_errno = errno;
- r = malloc(sizeof(struct uml_pt_regs));
+ r = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC);
if (!r)
panic("out of memory");
@@ -91,7 +92,7 @@ static void timer_real_alarm_handler(mcontext_t *mc)
{
struct uml_pt_regs *regs;
- regs = malloc(sizeof(struct uml_pt_regs));
+ regs = uml_kmalloc(sizeof(struct uml_pt_regs), UM_GFP_ATOMIC);
if (!regs)
panic("out of memory");
diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h
index e35632ef23c7..62dfc644c908 100644
--- a/arch/unicore32/include/asm/mmu_context.h
+++ b/arch/unicore32/include/asm/mmu_context.h
@@ -98,7 +98,7 @@ static inline void arch_bprm_mm_init(struct mm_struct *mm,
}
static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
- bool write, bool foreign)
+ bool write, bool execute, bool foreign)
{
/* by default, allow everything */
return true;
diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c
index 16c08b2143a7..3e9f6489ba38 100644
--- a/arch/unicore32/mm/dma-swiotlb.c
+++ b/arch/unicore32/mm/dma-swiotlb.c
@@ -19,14 +19,14 @@
static void *unicore_swiotlb_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
}
static void unicore_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3a9add58d794..c580d8c33562 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -80,6 +80,7 @@ config X86
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_AOUT if X86_32
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_HARDENED_USERCOPY
select HAVE_ARCH_HUGE_VMAP if X86_64 || X86_PAE
select HAVE_ARCH_JUMP_LABEL
select HAVE_ARCH_KASAN if X86_64 && SPARSEMEM_VMEMMAP
@@ -91,6 +92,7 @@ config X86
select HAVE_ARCH_SOFT_DIRTY if X86_64
select HAVE_ARCH_TRACEHOOK
select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+ select HAVE_ARCH_WITHIN_STACK_FRAMES
select HAVE_EBPF_JIT if X86_64
select HAVE_CC_STACKPROTECTOR
select HAVE_CMPXCHG_DOUBLE
@@ -152,6 +154,7 @@ config X86
select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
select PERF_EVENTS
select RTC_LIB
+ select RTC_MC146818_LIB
select SPARSE_IRQ
select SRCU
select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/x86/entry/Makefile b/arch/x86/entry/Makefile
index fe91c25092da..77f28ce9c646 100644
--- a/arch/x86/entry/Makefile
+++ b/arch/x86/entry/Makefile
@@ -5,6 +5,8 @@
OBJECT_FILES_NON_STANDARD_entry_$(BITS).o := y
OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y
+CFLAGS_syscall_64.o += -Wno-override-init
+CFLAGS_syscall_32.o += -Wno-override-init
obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
obj-y += common.o
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index a1e71d431fed..1433f6b4607d 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -204,8 +204,12 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
* handling, because syscall restart has a fixup for compat
* syscalls. The fixup is exercised by the ptrace_syscall_32
* selftest.
+ *
+ * We also need to clear TS_REGS_POKED_I386: the 32-bit tracer
+ * special case only applies after poking regs and before the
+ * very next return to user mode.
*/
- ti->status &= ~TS_COMPAT;
+ ti->status &= ~(TS_COMPAT|TS_I386_REGS_POKED);
#endif
user_enter_irqoff();
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index b846875aeea6..d172c619c449 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -288,11 +288,15 @@ return_from_SYSCALL_64:
jne opportunistic_sysret_failed
/*
- * SYSRET can't restore RF. SYSRET can restore TF, but unlike IRET,
- * restoring TF results in a trap from userspace immediately after
- * SYSRET. This would cause an infinite loop whenever #DB happens
- * with register state that satisfies the opportunistic SYSRET
- * conditions. For example, single-stepping this user code:
+ * SYSCALL clears RF when it saves RFLAGS in R11 and SYSRET cannot
+ * restore RF properly. If the slowpath sets it for whatever reason, we
+ * need to restore it correctly.
+ *
+ * SYSRET can restore TF, but unlike IRET, restoring TF results in a
+ * trap from userspace immediately after SYSRET. This would cause an
+ * infinite loop whenever #DB happens with register state that satisfies
+ * the opportunistic SYSRET conditions. For example, single-stepping
+ * this user code:
*
* movq $stuck_here, %rcx
* pushfq
@@ -601,9 +605,20 @@ apicinterrupt3 \num trace(\sym) smp_trace(\sym)
.endm
#endif
+/* Make sure APIC interrupt handlers end up in the irqentry section: */
+#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
+# define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax"
+# define POP_SECTION_IRQENTRY .popsection
+#else
+# define PUSH_SECTION_IRQENTRY
+# define POP_SECTION_IRQENTRY
+#endif
+
.macro apicinterrupt num sym do_sym
+PUSH_SECTION_IRQENTRY
apicinterrupt3 \num \sym \do_sym
trace_apicinterrupt \num \sym
+POP_SECTION_IRQENTRY
.endm
#ifdef CONFIG_SMP
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index 4cddd17153fb..f848572169ea 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -294,7 +294,7 @@
# 285 sys_setaltroot
286 i386 add_key sys_add_key
287 i386 request_key sys_request_key
-288 i386 keyctl sys_keyctl
+288 i386 keyctl sys_keyctl compat_sys_keyctl
289 i386 ioprio_set sys_ioprio_set
290 i386 ioprio_get sys_ioprio_get
291 i386 inotify_init sys_inotify_init
diff --git a/arch/x86/entry/vdso/vclock_gettime.c b/arch/x86/entry/vdso/vclock_gettime.c
index 2f02d23a05ef..94d54d0defa7 100644
--- a/arch/x86/entry/vdso/vclock_gettime.c
+++ b/arch/x86/entry/vdso/vclock_gettime.c
@@ -96,9 +96,8 @@ static notrace cycle_t vread_pvclock(int *mode)
{
const struct pvclock_vcpu_time_info *pvti = &get_pvti0()->pvti;
cycle_t ret;
- u64 tsc, pvti_tsc;
- u64 last, delta, pvti_system_time;
- u32 version, pvti_tsc_to_system_mul, pvti_tsc_shift;
+ u64 last;
+ u32 version;
/*
* Note: The kernel and hypervisor must guarantee that cpu ID
@@ -123,29 +122,15 @@ static notrace cycle_t vread_pvclock(int *mode)
*/
do {
- version = pvti->version;
-
- smp_rmb();
+ version = pvclock_read_begin(pvti);
if (unlikely(!(pvti->flags & PVCLOCK_TSC_STABLE_BIT))) {
*mode = VCLOCK_NONE;
return 0;
}
- tsc = rdtsc_ordered();
- pvti_tsc_to_system_mul = pvti->tsc_to_system_mul;
- pvti_tsc_shift = pvti->tsc_shift;
- pvti_system_time = pvti->system_time;
- pvti_tsc = pvti->tsc_timestamp;
-
- /* Make sure that the version double-check is last. */
- smp_rmb();
- } while (unlikely((version & 1) || version != pvti->version));
-
- delta = tsc - pvti_tsc;
- ret = pvti_system_time +
- pvclock_scale_delta(delta, pvti_tsc_to_system_mul,
- pvti_tsc_shift);
+ ret = __pvclock_read_cycles(pvti);
+ } while (pvclock_read_retry(pvti, version));
/* refer to vread_tsc() comment for rationale */
last = gtod->cycle_last;
diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h
index 63a03bb91497..4f741192846d 100644
--- a/arch/x86/entry/vdso/vdso2c.h
+++ b/arch/x86/entry/vdso/vdso2c.h
@@ -22,6 +22,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_LE(&hdr->e_phoff));
+ if (hdr->e_type != ET_DYN)
+ fail("input is not a shared object\n");
+
/* Walk the segment table. */
for (i = 0; i < GET_LE(&hdr->e_phnum); i++) {
if (GET_LE(&pt[i].p_type) == PT_LOAD) {
@@ -49,6 +52,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
if (stripped_len < load_size)
fail("stripped input is too short\n");
+ if (!dyn)
+ fail("input has no PT_DYNAMIC section -- your toolchain is buggy\n");
+
/* Walk the dynamic table */
for (i = 0; dyn + i < dyn_end &&
GET_LE(&dyn[i].d_tag) != DT_NULL; i++) {
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index fad97886d8b1..d0efb5cb1b00 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -263,10 +263,13 @@ static bool check_hw_exists(void)
return true;
msr_fail:
- pr_cont("Broken PMU hardware detected, using software events only.\n");
- printk("%sFailed to access perfctr msr (MSR %x is %Lx)\n",
- boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR,
- reg, val_new);
+ if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+ pr_cont("PMU not available due to virtualization, using software events only.\n");
+ } else {
+ pr_cont("Broken PMU hardware detected, using software events only.\n");
+ pr_err("Failed to access perfctr msr (MSR %x is %Lx)\n",
+ reg, val_new);
+ }
return false;
}
diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c
index 97a69dbba649..9d35ec0cb8fc 100644
--- a/arch/x86/events/intel/uncore_snb.c
+++ b/arch/x86/events/intel/uncore_snb.c
@@ -100,6 +100,12 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
}
}
+static void snb_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+ wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
+ SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
+}
+
static void snb_uncore_msr_exit_box(struct intel_uncore_box *box)
{
if (box->pmu->pmu_idx == 0)
@@ -127,6 +133,7 @@ static struct attribute_group snb_uncore_format_group = {
static struct intel_uncore_ops snb_uncore_msr_ops = {
.init_box = snb_uncore_msr_init_box,
+ .enable_box = snb_uncore_msr_enable_box,
.exit_box = snb_uncore_msr_exit_box,
.disable_event = snb_uncore_msr_disable_event,
.enable_event = snb_uncore_msr_enable_event,
@@ -192,6 +199,12 @@ static void skl_uncore_msr_init_box(struct intel_uncore_box *box)
}
}
+static void skl_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+ wrmsrl(SKL_UNC_PERF_GLOBAL_CTL,
+ SNB_UNC_GLOBAL_CTL_EN | SKL_UNC_GLOBAL_CTL_CORE_ALL);
+}
+
static void skl_uncore_msr_exit_box(struct intel_uncore_box *box)
{
if (box->pmu->pmu_idx == 0)
@@ -200,6 +213,7 @@ static void skl_uncore_msr_exit_box(struct intel_uncore_box *box)
static struct intel_uncore_ops skl_uncore_msr_ops = {
.init_box = skl_uncore_msr_init_box,
+ .enable_box = skl_uncore_msr_enable_box,
.exit_box = skl_uncore_msr_exit_box,
.disable_event = snb_uncore_msr_disable_event,
.enable_event = snb_uncore_msr_enable_event,
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 824e54086e07..8aee83bcf71f 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -2626,7 +2626,7 @@ void hswep_uncore_cpu_init(void)
static struct intel_uncore_type hswep_uncore_ha = {
.name = "ha",
- .num_counters = 5,
+ .num_counters = 4,
.num_boxes = 2,
.perf_ctr_bits = 48,
SNBEP_UNCORE_PCI_COMMON_INIT(),
@@ -2645,7 +2645,7 @@ static struct uncore_event_desc hswep_uncore_imc_events[] = {
static struct intel_uncore_type hswep_uncore_imc = {
.name = "imc",
- .num_counters = 5,
+ .num_counters = 4,
.num_boxes = 8,
.perf_ctr_bits = 48,
.fixed_ctr_bits = 48,
@@ -2691,7 +2691,7 @@ static struct intel_uncore_type hswep_uncore_irp = {
static struct intel_uncore_type hswep_uncore_qpi = {
.name = "qpi",
- .num_counters = 5,
+ .num_counters = 4,
.num_boxes = 3,
.perf_ctr_bits = 48,
.perf_ctr = SNBEP_PCI_PMON_CTR0,
@@ -2773,7 +2773,7 @@ static struct event_constraint hswep_uncore_r3qpi_constraints[] = {
static struct intel_uncore_type hswep_uncore_r3qpi = {
.name = "r3qpi",
- .num_counters = 4,
+ .num_counters = 3,
.num_boxes = 3,
.perf_ctr_bits = 44,
.constraints = hswep_uncore_r3qpi_constraints,
@@ -2972,7 +2972,7 @@ static struct intel_uncore_type bdx_uncore_ha = {
static struct intel_uncore_type bdx_uncore_imc = {
.name = "imc",
- .num_counters = 5,
+ .num_counters = 4,
.num_boxes = 8,
.perf_ctr_bits = 48,
.fixed_ctr_bits = 48,
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f5befd4945f2..124357773ffa 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -135,6 +135,7 @@ extern void init_apic_mappings(void);
void register_lapic_address(unsigned long address);
extern void setup_boot_APIC_clock(void);
extern void setup_secondary_APIC_clock(void);
+extern void lapic_update_tsc_freq(void);
extern int APIC_init_uniprocessor(void);
#ifdef CONFIG_X86_64
@@ -170,6 +171,7 @@ static inline void init_apic_mappings(void) { }
static inline void disable_local_APIC(void) { }
# define setup_boot_APIC_clock x86_init_noop
# define setup_secondary_APIC_clock x86_init_noop
+static inline void lapic_update_tsc_freq(void) { }
#endif /* !CONFIG_X86_LOCAL_APIC */
#ifdef CONFIG_X86_X2APIC
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 3a27b93e6261..44461626830e 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -9,7 +9,6 @@
#include <linux/kmemcheck.h>
#include <linux/scatterlist.h>
#include <linux/dma-debug.h>
-#include <linux/dma-attrs.h>
#include <asm/io.h>
#include <asm/swiotlb.h>
#include <linux/dma-contiguous.h>
@@ -48,11 +47,11 @@ extern int dma_supported(struct device *hwdev, u64 mask);
extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void dma_generic_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs);
+ unsigned long attrs);
#ifdef CONFIG_X86_DMA_REMAP /* Platform code defines bridge-specific code */
extern bool dma_capable(struct device *dev, dma_addr_t addr, size_t size);
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index fea7724141a0..e7f155c3045e 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -344,8 +344,8 @@ extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
*/
static inline int mmap_is_ia32(void)
{
- return config_enabled(CONFIG_X86_32) ||
- (config_enabled(CONFIG_COMPAT) &&
+ return IS_ENABLED(CONFIG_X86_32) ||
+ (IS_ENABLED(CONFIG_COMPAT) &&
test_thread_flag(TIF_ADDR32));
}
diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h
index 116b58347501..2737366ea583 100644
--- a/arch/x86/include/asm/fpu/internal.h
+++ b/arch/x86/include/asm/fpu/internal.h
@@ -137,9 +137,9 @@ static inline int copy_fregs_to_user(struct fregs_state __user *fx)
static inline int copy_fxregs_to_user(struct fxregs_state __user *fx)
{
- if (config_enabled(CONFIG_X86_32))
+ if (IS_ENABLED(CONFIG_X86_32))
return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
- else if (config_enabled(CONFIG_AS_FXSAVEQ))
+ else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
/* See comment in copy_fxregs_to_kernel() below. */
@@ -150,10 +150,10 @@ static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
{
int err;
- if (config_enabled(CONFIG_X86_32)) {
+ if (IS_ENABLED(CONFIG_X86_32)) {
err = check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
} else {
- if (config_enabled(CONFIG_AS_FXSAVEQ)) {
+ if (IS_ENABLED(CONFIG_AS_FXSAVEQ)) {
err = check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
} else {
/* See comment in copy_fxregs_to_kernel() below. */
@@ -166,9 +166,9 @@ static inline void copy_kernel_to_fxregs(struct fxregs_state *fx)
static inline int copy_user_to_fxregs(struct fxregs_state __user *fx)
{
- if (config_enabled(CONFIG_X86_32))
+ if (IS_ENABLED(CONFIG_X86_32))
return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
- else if (config_enabled(CONFIG_AS_FXSAVEQ))
+ else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
/* See comment in copy_fxregs_to_kernel() below. */
@@ -190,9 +190,9 @@ static inline int copy_user_to_fregs(struct fregs_state __user *fx)
static inline void copy_fxregs_to_kernel(struct fpu *fpu)
{
- if (config_enabled(CONFIG_X86_32))
+ if (IS_ENABLED(CONFIG_X86_32))
asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state.fxsave));
- else if (config_enabled(CONFIG_AS_FXSAVEQ))
+ else if (IS_ENABLED(CONFIG_AS_FXSAVEQ))
asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave));
else {
/* Using "rex64; fxsave %0" is broken because, if the memory
diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h
index 7178043b0e1d..59405a248fc2 100644
--- a/arch/x86/include/asm/hardirq.h
+++ b/arch/x86/include/asm/hardirq.h
@@ -22,10 +22,6 @@ typedef struct {
#ifdef CONFIG_SMP
unsigned int irq_resched_count;
unsigned int irq_call_count;
- /*
- * irq_tlb_count is double-counted in irq_call_count, so it must be
- * subtracted from irq_call_count when displaying irq_call_count
- */
unsigned int irq_tlb_count;
#endif
#ifdef CONFIG_X86_THERMAL_VECTOR
diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h
index 223042086f4e..737da62bfeb0 100644
--- a/arch/x86/include/asm/init.h
+++ b/arch/x86/include/asm/init.h
@@ -5,10 +5,10 @@ struct x86_mapping_info {
void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
void *context; /* context for alloc_pgt_page */
unsigned long pmd_flag; /* page flag for PMD entry */
- bool kernel_mapping; /* kernel mapping or ident mapping */
+ unsigned long offset; /* ident mapping offset */
};
int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
- unsigned long addr, unsigned long end);
+ unsigned long pstart, unsigned long pend);
#endif /* _ASM_X86_INIT_H */
diff --git a/arch/x86/include/asm/mc146818rtc.h b/arch/x86/include/asm/mc146818rtc.h
index 0f555cc31984..24acd9ba7837 100644
--- a/arch/x86/include/asm/mc146818rtc.h
+++ b/arch/x86/include/asm/mc146818rtc.h
@@ -6,7 +6,6 @@
#include <asm/io.h>
#include <asm/processor.h>
-#include <linux/mc146818rtc.h>
#ifndef RTC_PORT
#define RTC_PORT(x) (0x70 + (x))
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 396348196aa7..d8abfcf524d1 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -155,7 +155,7 @@ static inline void arch_exit_mmap(struct mm_struct *mm)
#ifdef CONFIG_X86_64
static inline bool is_64bit_mm(struct mm_struct *mm)
{
- return !config_enabled(CONFIG_IA32_EMULATION) ||
+ return !IS_ENABLED(CONFIG_IA32_EMULATION) ||
!(mm->context.ia32_compat == TIF_IA32);
}
#else
diff --git a/arch/x86/include/asm/pgtable_64.h b/arch/x86/include/asm/pgtable_64.h
index 7e8ec7ae10fa..1cc82ece9ac1 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -145,7 +145,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
*
* | ... | 11| 10| 9|8|7|6|5| 4| 3|2|1|0| <- bit number
* | ... |SW3|SW2|SW1|G|L|D|A|CD|WT|U|W|P| <- bit names
- * | OFFSET (14->63) | TYPE (10-13) |0|X|X|X| X| X|X|X|0| <- swp entry
+ * | OFFSET (14->63) | TYPE (9-13) |0|X|X|X| X| X|X|X|0| <- swp entry
*
* G (8) is aliased and used as a PROT_NONE indicator for
* !present ptes. We need to start storing swap entries above
@@ -156,7 +156,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
#define SWP_TYPE_FIRST_BIT (_PAGE_BIT_PROTNONE + 1)
#define SWP_TYPE_BITS 5
/* Place the offset above the type: */
-#define SWP_OFFSET_FIRST_BIT (SWP_TYPE_FIRST_BIT + SWP_TYPE_BITS + 1)
+#define SWP_OFFSET_FIRST_BIT (SWP_TYPE_FIRST_BIT + SWP_TYPE_BITS)
#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
index 7c1c89598688..d019f0cc80ec 100644
--- a/arch/x86/include/asm/pvclock.h
+++ b/arch/x86/include/asm/pvclock.h
@@ -25,6 +25,24 @@ void pvclock_resume(void);
void pvclock_touch_watchdogs(void);
+static __always_inline
+unsigned pvclock_read_begin(const struct pvclock_vcpu_time_info *src)
+{
+ unsigned version = src->version & ~1;
+ /* Make sure that the version is read before the data. */
+ virt_rmb();
+ return version;
+}
+
+static __always_inline
+bool pvclock_read_retry(const struct pvclock_vcpu_time_info *src,
+ unsigned version)
+{
+ /* Make sure that the version is re-read after the data. */
+ virt_rmb();
+ return unlikely(version != src->version);
+}
+
/*
* Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction,
* yielding a 64-bit result.
@@ -69,23 +87,12 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
}
static __always_inline
-unsigned __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
- cycle_t *cycles, u8 *flags)
+cycle_t __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src)
{
- unsigned version;
- cycle_t offset;
- u64 delta;
-
- version = src->version;
- /* Make the latest version visible */
- smp_rmb();
-
- delta = rdtsc_ordered() - src->tsc_timestamp;
- offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
- src->tsc_shift);
- *cycles = src->system_time + offset;
- *flags = src->flags;
- return version;
+ u64 delta = rdtsc_ordered() - src->tsc_timestamp;
+ cycle_t offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
+ src->tsc_shift);
+ return src->system_time + offset;
}
struct pvclock_vsyscall_time_info {
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index 9c6b890d5e7a..b2988c0ed829 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -58,7 +58,15 @@ extern unsigned char boot_gdt[];
extern unsigned char secondary_startup_64[];
#endif
+static inline size_t real_mode_size_needed(void)
+{
+ if (real_mode_header)
+ return 0; /* already allocated. */
+
+ return ALIGN(real_mode_blob_end - real_mode_blob, PAGE_SIZE);
+}
+
+void set_real_mode_mem(phys_addr_t mem, size_t size);
void reserve_real_mode(void);
-void setup_real_mode(void);
#endif /* _ARCH_X86_REALMODE_H */
diff --git a/arch/x86/include/asm/rtc.h b/arch/x86/include/asm/rtc.h
deleted file mode 100644
index f71c3b0ed360..000000000000
--- a/arch/x86/include/asm/rtc.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/rtc.h>
diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h
index ab05d73e2bb7..d2f69b9ff732 100644
--- a/arch/x86/include/asm/swiotlb.h
+++ b/arch/x86/include/asm/swiotlb.h
@@ -31,9 +31,9 @@ static inline void dma_mark_clean(void *addr, size_t size) {}
extern void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs);
+ unsigned long attrs);
#endif /* _ASM_X86_SWIOTLB_H */
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
index 999b7cd2e78c..4e23dd15c661 100644
--- a/arch/x86/include/asm/syscall.h
+++ b/arch/x86/include/asm/syscall.h
@@ -60,7 +60,7 @@ static inline long syscall_get_error(struct task_struct *task,
* TS_COMPAT is set for 32-bit syscall entries and then
* remains set until we return to user mode.
*/
- if (task_thread_info(task)->status & TS_COMPAT)
+ if (task_thread_info(task)->status & (TS_COMPAT|TS_I386_REGS_POKED))
/*
* Sign-extend the value so (int)-EFOO becomes (long)-EFOO
* and will match correctly in comparisons.
@@ -239,9 +239,6 @@ static inline int syscall_get_arch(void)
* TS_COMPAT is set for 32-bit syscall entry and then
* remains set until we return to user mode.
*
- * TIF_IA32 tasks should always have TS_COMPAT set at
- * system call time.
- *
* x32 tasks should be considered AUDIT_ARCH_X86_64.
*/
if (task_thread_info(current)->status & TS_COMPAT)
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index b45ffdda3549..8b7c8d8e0852 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -176,6 +176,50 @@ static inline unsigned long current_stack_pointer(void)
return sp;
}
+/*
+ * Walks up the stack frames to make sure that the specified object is
+ * entirely contained by a single stack frame.
+ *
+ * Returns:
+ * 1 if within a frame
+ * -1 if placed across a frame boundary (or outside stack)
+ * 0 unable to determine (no frame pointers, etc)
+ */
+static inline int arch_within_stack_frames(const void * const stack,
+ const void * const stackend,
+ const void *obj, unsigned long len)
+{
+#if defined(CONFIG_FRAME_POINTER)
+ const void *frame = NULL;
+ const void *oldframe;
+
+ oldframe = __builtin_frame_address(1);
+ if (oldframe)
+ frame = __builtin_frame_address(2);
+ /*
+ * low ----------------------------------------------> high
+ * [saved bp][saved ip][args][local vars][saved bp][saved ip]
+ * ^----------------^
+ * allow copies only within here
+ */
+ while (stack <= frame && frame < stackend) {
+ /*
+ * If obj + len extends past the last frame, this
+ * check won't pass and the next frame will be 0,
+ * causing us to bail out and correctly report
+ * the copy as invalid.
+ */
+ if (obj + len <= frame)
+ return obj >= oldframe + 2 * sizeof(void *) ? 1 : -1;
+ oldframe = frame;
+ frame = *(const void * const *)frame;
+ }
+ return -1;
+#else
+ return 0;
+#endif
+}
+
#else /* !__ASSEMBLY__ */
#ifdef CONFIG_X86_64
@@ -219,6 +263,9 @@ static inline unsigned long current_stack_pointer(void)
* have to worry about atomic accesses.
*/
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
+#ifdef CONFIG_COMPAT
+#define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */
+#endif
#ifndef __ASSEMBLY__
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 4e5be94e079a..6fa85944af83 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -135,7 +135,14 @@ static inline void cr4_set_bits_and_update_boot(unsigned long mask)
static inline void __native_flush_tlb(void)
{
+ /*
+ * If current->mm == NULL then we borrow a mm which may change during a
+ * task switch and therefore we must not be preempted while we write CR3
+ * back:
+ */
+ preempt_disable();
native_write_cr3(native_read_cr3());
+ preempt_enable();
}
static inline void __native_flush_tlb_global_irq_disabled(void)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index c03bfb68c503..a0ae610b9280 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -761,9 +761,10 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
* case, and do only runtime checking for non-constant sizes.
*/
- if (likely(sz < 0 || sz >= n))
+ if (likely(sz < 0 || sz >= n)) {
+ check_object_size(to, n, false);
n = _copy_from_user(to, from, n);
- else if(__builtin_constant_p(n))
+ } else if (__builtin_constant_p(n))
copy_from_user_overflow();
else
__copy_from_user_overflow(sz, n);
@@ -781,9 +782,10 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
might_fault();
/* See the comment in copy_from_user() above. */
- if (likely(sz < 0 || sz >= n))
+ if (likely(sz < 0 || sz >= n)) {
+ check_object_size(from, n, true);
n = _copy_to_user(to, from, n);
- else if(__builtin_constant_p(n))
+ } else if (__builtin_constant_p(n))
copy_to_user_overflow();
else
__copy_to_user_overflow(sz, n);
@@ -812,21 +814,21 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
#define user_access_begin() __uaccess_begin()
#define user_access_end() __uaccess_end()
-#define unsafe_put_user(x, ptr) \
-({ \
+#define unsafe_put_user(x, ptr, err_label) \
+do { \
int __pu_err; \
__put_user_size((x), (ptr), sizeof(*(ptr)), __pu_err, -EFAULT); \
- __builtin_expect(__pu_err, 0); \
-})
+ if (unlikely(__pu_err)) goto err_label; \
+} while (0)
-#define unsafe_get_user(x, ptr) \
-({ \
+#define unsafe_get_user(x, ptr, err_label) \
+do { \
int __gu_err; \
unsigned long __gu_val; \
__get_user_size(__gu_val, (ptr), sizeof(*(ptr)), __gu_err, -EFAULT); \
(x) = (__force __typeof__(*(ptr)))__gu_val; \
- __builtin_expect(__gu_err, 0); \
-})
+ if (unlikely(__gu_err)) goto err_label; \
+} while (0)
#endif /* _ASM_X86_UACCESS_H */
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 4b32da24faaf..7d3bdd1ed697 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -37,6 +37,7 @@ unsigned long __must_check __copy_from_user_ll_nocache_nozero
static __always_inline unsigned long __must_check
__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
{
+ check_object_size(from, n, true);
return __copy_to_user_ll(to, from, n);
}
@@ -95,6 +96,7 @@ static __always_inline unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
might_fault();
+ check_object_size(to, n, false);
if (__builtin_constant_p(n)) {
unsigned long ret;
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 2eac2aa3e37f..673059a109fe 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -54,6 +54,7 @@ int __copy_from_user_nocheck(void *dst, const void __user *src, unsigned size)
{
int ret = 0;
+ check_object_size(dst, size, false);
if (!__builtin_constant_p(size))
return copy_user_generic(dst, (__force void *)src, size);
switch (size) {
@@ -119,6 +120,7 @@ int __copy_to_user_nocheck(void __user *dst, const void *src, unsigned size)
{
int ret = 0;
+ check_object_size(src, size, true);
if (!__builtin_constant_p(size))
return copy_user_generic((__force void *)dst, src, size);
switch (size) {
diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index c852590254d5..e652a7cc6186 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -79,7 +79,7 @@ struct uv_gam_range_entry {
u16 nasid; /* HNasid */
u16 sockid; /* Socket ID, high bits of APIC ID */
u16 pnode; /* Index to MMR and GRU spaces */
- u32 pxm; /* ACPI proximity domain number */
+ u32 unused2;
u32 limit; /* PA bits 56:26 (UV_GAM_RANGE_SHFT) */
};
@@ -88,7 +88,8 @@ struct uv_gam_range_entry {
#define UV_SYSTAB_VERSION_UV4 0x400 /* UV4 BIOS base version */
#define UV_SYSTAB_VERSION_UV4_1 0x401 /* + gpa_shift */
#define UV_SYSTAB_VERSION_UV4_2 0x402 /* + TYPE_NVRAM/WINDOW/MBOX */
-#define UV_SYSTAB_VERSION_UV4_LATEST UV_SYSTAB_VERSION_UV4_2
+#define UV_SYSTAB_VERSION_UV4_3 0x403 /* - GAM Range PXM Value */
+#define UV_SYSTAB_VERSION_UV4_LATEST UV_SYSTAB_VERSION_UV4_3
#define UV_SYSTAB_TYPE_UNUSED 0 /* End of table (offset == 0) */
#define UV_SYSTAB_TYPE_GAM_PARAMS 1 /* GAM PARAM conversions */
diff --git a/arch/x86/include/asm/xen/page-coherent.h b/arch/x86/include/asm/xen/page-coherent.h
index acd844c017d3..f02f025ff988 100644
--- a/arch/x86/include/asm/xen/page-coherent.h
+++ b/arch/x86/include/asm/xen/page-coherent.h
@@ -2,12 +2,11 @@
#define _ASM_X86_XEN_PAGE_COHERENT_H
#include <asm/page.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-mapping.h>
static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *vstart = (void*)__get_free_pages(flags, get_order(size));
*dma_handle = virt_to_phys(vstart);
@@ -16,18 +15,18 @@ static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
void *cpu_addr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
free_pages((unsigned long) cpu_addr, get_order(size));
}
static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
dma_addr_t dev_addr, unsigned long offset, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs) { }
+ enum dma_data_direction dir, unsigned long attrs) { }
static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs) { }
+ unsigned long attrs) { }
static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
dma_addr_t handle, size_t size, enum dma_data_direction dir) { }
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index 42d27a62a404..63ff468a7986 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -241,7 +241,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
static dma_addr_t gart_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long bus;
phys_addr_t paddr = page_to_phys(page) + offset;
@@ -263,7 +263,7 @@ static dma_addr_t gart_map_page(struct device *dev, struct page *page,
*/
static void gart_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long iommu_page;
int npages;
@@ -285,7 +285,7 @@ static void gart_unmap_page(struct device *dev, dma_addr_t dma_addr,
* Wrapper for pci_unmap_single working with scatterlists.
*/
static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *s;
int i;
@@ -293,7 +293,7 @@ static void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
for_each_sg(sg, s, nents, i) {
if (!s->dma_length || !s->length)
break;
- gart_unmap_page(dev, s->dma_address, s->dma_length, dir, NULL);
+ gart_unmap_page(dev, s->dma_address, s->dma_length, dir, 0);
}
}
@@ -315,7 +315,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
addr = dma_map_area(dev, addr, s->length, dir, 0);
if (addr == bad_dma_addr) {
if (i > 0)
- gart_unmap_sg(dev, sg, i, dir, NULL);
+ gart_unmap_sg(dev, sg, i, dir, 0);
nents = 0;
sg[0].dma_length = 0;
break;
@@ -386,7 +386,7 @@ dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
* Merge chunks that have page aligned sizes into a continuous mapping.
*/
static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *s, *ps, *start_sg, *sgmap;
int need = 0, nextneed, i, out, start;
@@ -456,7 +456,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
error:
flush_gart();
- gart_unmap_sg(dev, sg, out, dir, NULL);
+ gart_unmap_sg(dev, sg, out, dir, 0);
/* When it was forced or merged try again in a dumb way */
if (force_iommu || iommu_merge) {
@@ -476,7 +476,7 @@ error:
/* allocate and map a coherent mapping */
static void *
gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
- gfp_t flag, struct dma_attrs *attrs)
+ gfp_t flag, unsigned long attrs)
{
dma_addr_t paddr;
unsigned long align_mask;
@@ -508,9 +508,9 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
/* free a coherent mapping */
static void
gart_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, unsigned long attrs)
{
- gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, NULL);
+ gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, 0);
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
}
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 7943d38c57ca..cea4fc19e844 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -147,7 +147,7 @@ static int force_enable_local_apic __initdata;
*/
static int __init parse_lapic(char *arg)
{
- if (config_enabled(CONFIG_X86_32) && !arg)
+ if (IS_ENABLED(CONFIG_X86_32) && !arg)
force_enable_local_apic = 1;
else if (arg && !strncmp(arg, "notscdeadline", 13))
setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
@@ -313,7 +313,7 @@ int lapic_get_maxlvt(void)
/* Clock divisor */
#define APIC_DIVISOR 16
-#define TSC_DIVISOR 32
+#define TSC_DIVISOR 8
/*
* This function sets up the local APIC timer, with a timeout of
@@ -565,13 +565,37 @@ static void setup_APIC_timer(void)
CLOCK_EVT_FEAT_DUMMY);
levt->set_next_event = lapic_next_deadline;
clockevents_config_and_register(levt,
- (tsc_khz / TSC_DIVISOR) * 1000,
+ tsc_khz * (1000 / TSC_DIVISOR),
0xF, ~0UL);
} else
clockevents_register_device(levt);
}
/*
+ * Install the updated TSC frequency from recalibration at the TSC
+ * deadline clockevent devices.
+ */
+static void __lapic_update_tsc_freq(void *info)
+{
+ struct clock_event_device *levt = this_cpu_ptr(&lapic_events);
+
+ if (!this_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+ return;
+
+ clockevents_update_freq(levt, tsc_khz * (1000 / TSC_DIVISOR));
+}
+
+void lapic_update_tsc_freq(void)
+{
+ /*
+ * The clockevent device's ->mult and ->shift can both be
+ * changed. In order to avoid races, schedule the frequency
+ * update code on each CPU.
+ */
+ on_each_cpu(__lapic_update_tsc_freq, NULL, 0);
+}
+
+/*
* In this functions we calibrate APIC bus clocks to the external timer.
*
* We want to do the calibration only once since we want to have local timer
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index a5e400afc563..6066d945c40e 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -523,7 +523,7 @@ static int apic_set_affinity(struct irq_data *irq_data,
struct apic_chip_data *data = irq_data->chip_data;
int err, irq = irq_data->irq;
- if (!config_enabled(CONFIG_SMP))
+ if (!IS_ENABLED(CONFIG_SMP))
return -EPERM;
if (!cpumask_intersects(dest, cpu_online_mask))
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 6368fa69d2af..54f35d988025 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -155,7 +155,7 @@ static void init_x2apic_ldr(void)
/*
* At CPU state changes, update the x2apic cluster sibling info.
*/
-int x2apic_prepare_cpu(unsigned int cpu)
+static int x2apic_prepare_cpu(unsigned int cpu)
{
if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL))
return -ENOMEM;
@@ -168,7 +168,7 @@ int x2apic_prepare_cpu(unsigned int cpu)
return 0;
}
-int x2apic_dead_cpu(unsigned int this_cpu)
+static int x2apic_dead_cpu(unsigned int this_cpu)
{
int cpu;
@@ -186,13 +186,18 @@ int x2apic_dead_cpu(unsigned int this_cpu)
static int x2apic_cluster_probe(void)
{
int cpu = smp_processor_id();
+ int ret;
if (!x2apic_mode)
return 0;
+ ret = cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE",
+ x2apic_prepare_cpu, x2apic_dead_cpu);
+ if (ret < 0) {
+ pr_err("Failed to register X2APIC_PREPARE\n");
+ return 0;
+ }
cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu));
- cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE",
- x2apic_prepare_cpu, x2apic_dead_cpu);
return 1;
}
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 09b59adaea3f..cb0673c1e940 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -223,6 +223,11 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
if (strncmp(oem_id, "SGI", 3) != 0)
return 0;
+ if (numa_off) {
+ pr_err("UV: NUMA is off, disabling UV support\n");
+ return 0;
+ }
+
/* Setup early hub type field in uv_hub_info for Node 0 */
uv_cpu_info->p_uv_hub_info = &uv_hub_info_node0;
@@ -325,7 +330,7 @@ static __init void build_uv_gr_table(void)
struct uv_gam_range_entry *gre = uv_gre_table;
struct uv_gam_range_s *grt;
unsigned long last_limit = 0, ram_limit = 0;
- int bytes, i, sid, lsid = -1;
+ int bytes, i, sid, lsid = -1, indx = 0, lindx = -1;
if (!gre)
return;
@@ -356,11 +361,12 @@ static __init void build_uv_gr_table(void)
}
sid = gre->sockid - _min_socket;
if (lsid < sid) { /* new range */
- grt = &_gr_table[sid];
- grt->base = lsid;
+ grt = &_gr_table[indx];
+ grt->base = lindx;
grt->nasid = gre->nasid;
grt->limit = last_limit = gre->limit;
lsid = sid;
+ lindx = indx++;
continue;
}
if (lsid == sid && !ram_limit) { /* update range */
@@ -371,7 +377,7 @@ static __init void build_uv_gr_table(void)
}
if (!ram_limit) { /* non-contiguous ram range */
grt++;
- grt->base = sid - 1;
+ grt->base = lindx;
grt->nasid = gre->nasid;
grt->limit = last_limit = gre->limit;
continue;
@@ -1155,19 +1161,18 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) {
if (!index) {
pr_info("UV: GAM Range Table...\n");
- pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s %3s\n",
+ pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s\n",
"Range", "", "Size", "Type", "NASID",
- "SID", "PN", "PXM");
+ "SID", "PN");
}
pr_info(
- "UV: %2d: 0x%014lx-0x%014lx %5luG %3d %04x %02x %02x %3d\n",
+ "UV: %2d: 0x%014lx-0x%014lx %5luG %3d %04x %02x %02x\n",
index++,
(unsigned long)lgre << UV_GAM_RANGE_SHFT,
(unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
((unsigned long)(gre->limit - lgre)) >>
(30 - UV_GAM_RANGE_SHFT), /* 64M -> 1G */
- gre->type, gre->nasid, gre->sockid,
- gre->pnode, gre->pxm);
+ gre->type, gre->nasid, gre->sockid, gre->pnode);
lgre = gre->limit;
if (sock_min > gre->sockid)
@@ -1286,7 +1291,7 @@ static void __init build_socket_tables(void)
_pnode_to_socket[i] = SOCK_EMPTY;
/* fill in pnode/node/addr conversion list values */
- pr_info("UV: GAM Building socket/pnode/pxm conversion tables\n");
+ pr_info("UV: GAM Building socket/pnode conversion tables\n");
for (; gre->type != UV_GAM_RANGE_TYPE_UNUSED; gre++) {
if (gre->type == UV_GAM_RANGE_TYPE_HOLE)
continue;
@@ -1294,20 +1299,18 @@ static void __init build_socket_tables(void)
if (_socket_to_pnode[i] != SOCK_EMPTY)
continue; /* duplicate */
_socket_to_pnode[i] = gre->pnode;
- _socket_to_node[i] = gre->pxm;
i = gre->pnode - minpnode;
_pnode_to_socket[i] = gre->sockid;
pr_info(
- "UV: sid:%02x type:%d nasid:%04x pn:%02x pxm:%2d pn2s:%2x\n",
+ "UV: sid:%02x type:%d nasid:%04x pn:%02x pn2s:%2x\n",
gre->sockid, gre->type, gre->nasid,
_socket_to_pnode[gre->sockid - minsock],
- _socket_to_node[gre->sockid - minsock],
_pnode_to_socket[gre->pnode - minpnode]);
}
- /* check socket -> node values */
+ /* Set socket -> node values */
lnid = -1;
for_each_present_cpu(cpu) {
int nid = cpu_to_node(cpu);
@@ -1318,14 +1321,9 @@ static void __init build_socket_tables(void)
lnid = nid;
apicid = per_cpu(x86_cpu_to_apicid, cpu);
sockid = apicid >> uv_cpuid.socketid_shift;
- i = sockid - minsock;
-
- if (nid != _socket_to_node[i]) {
- pr_warn(
- "UV: %02x: type:%d socket:%02x PXM:%02x != node:%2d\n",
- i, sockid, gre->type, _socket_to_node[i], nid);
- _socket_to_node[i] = nid;
- }
+ _socket_to_node[sockid - minsock] = nid;
+ pr_info("UV: sid:%02x: apicid:%04x node:%2d\n",
+ sockid, apicid, nid);
}
/* Setup physical blade to pnode translation from GAM Range Table */
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 9e231d88bb33..a184c210efba 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -159,8 +159,8 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
struct task_struct *tsk = current;
int ia32_fxstate = (buf != buf_fx);
- ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
- config_enabled(CONFIG_IA32_EMULATION));
+ ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) ||
+ IS_ENABLED(CONFIG_IA32_EMULATION));
if (!access_ok(VERIFY_WRITE, buf, size))
return -EACCES;
@@ -268,8 +268,8 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
u64 xfeatures = 0;
int fx_only = 0;
- ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
- config_enabled(CONFIG_IA32_EMULATION));
+ ia32_fxstate &= (IS_ENABLED(CONFIG_X86_32) ||
+ IS_ENABLED(CONFIG_IA32_EMULATION));
if (!buf) {
fpu__clear(fpu);
@@ -416,8 +416,8 @@ void fpu__init_prepare_fx_sw_frame(void)
fx_sw_reserved.xfeatures = xfeatures_mask;
fx_sw_reserved.xstate_size = fpu_user_xstate_size;
- if (config_enabled(CONFIG_IA32_EMULATION) ||
- config_enabled(CONFIG_X86_32)) {
+ if (IS_ENABLED(CONFIG_IA32_EMULATION) ||
+ IS_ENABLED(CONFIG_X86_32)) {
int fsave_header_size = sizeof(struct fregs_state);
fx_sw_reserved_ia32 = fx_sw_reserved;
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 680049aa4593..01567aa87503 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -866,105 +866,17 @@ const void *get_xsave_field_ptr(int xsave_state)
return get_xsave_addr(&fpu->state.xsave, xsave_state);
}
-
-/*
- * Set xfeatures (aka XSTATE_BV) bit for a feature that we want
- * to take out of its "init state". This will ensure that an
- * XRSTOR actually restores the state.
- */
-static void fpu__xfeature_set_non_init(struct xregs_state *xsave,
- int xstate_feature_mask)
-{
- xsave->header.xfeatures |= xstate_feature_mask;
-}
-
-/*
- * This function is safe to call whether the FPU is in use or not.
- *
- * Note that this only works on the current task.
- *
- * Inputs:
- * @xsave_state: state which is defined in xsave.h (e.g. XFEATURE_MASK_FP,
- * XFEATURE_MASK_SSE, etc...)
- * @xsave_state_ptr: a pointer to a copy of the state that you would
- * like written in to the current task's FPU xsave state. This pointer
- * must not be located in the current tasks's xsave area.
- * Output:
- * address of the state in the xsave area or NULL if the state
- * is not present or is in its 'init state'.
- */
-static void fpu__xfeature_set_state(int xstate_feature_mask,
- void *xstate_feature_src, size_t len)
-{
- struct xregs_state *xsave = &current->thread.fpu.state.xsave;
- struct fpu *fpu = &current->thread.fpu;
- void *dst;
-
- if (!boot_cpu_has(X86_FEATURE_XSAVE)) {
- WARN_ONCE(1, "%s() attempted with no xsave support", __func__);
- return;
- }
-
- /*
- * Tell the FPU code that we need the FPU state to be in
- * 'fpu' (not in the registers), and that we need it to
- * be stable while we write to it.
- */
- fpu__current_fpstate_write_begin();
-
- /*
- * This method *WILL* *NOT* work for compact-format
- * buffers. If the 'xstate_feature_mask' is unset in
- * xcomp_bv then we may need to move other feature state
- * "up" in the buffer.
- */
- if (xsave->header.xcomp_bv & xstate_feature_mask) {
- WARN_ON_ONCE(1);
- goto out;
- }
-
- /* find the location in the xsave buffer of the desired state */
- dst = __raw_xsave_addr(&fpu->state.xsave, xstate_feature_mask);
-
- /*
- * Make sure that the pointer being passed in did not
- * come from the xsave buffer itself.
- */
- WARN_ONCE(xstate_feature_src == dst, "set from xsave buffer itself");
-
- /* put the caller-provided data in the location */
- memcpy(dst, xstate_feature_src, len);
-
- /*
- * Mark the xfeature so that the CPU knows there is state
- * in the buffer now.
- */
- fpu__xfeature_set_non_init(xsave, xstate_feature_mask);
-out:
- /*
- * We are done writing to the 'fpu'. Reenable preeption
- * and (possibly) move the fpstate back in to the fpregs.
- */
- fpu__current_fpstate_write_end();
-}
-
#define NR_VALID_PKRU_BITS (CONFIG_NR_PROTECTION_KEYS * 2)
#define PKRU_VALID_MASK (NR_VALID_PKRU_BITS - 1)
/*
- * This will go out and modify the XSAVE buffer so that PKRU is
- * set to a particular state for access to 'pkey'.
- *
- * PKRU state does affect kernel access to user memory. We do
- * not modfiy PKRU *itself* here, only the XSAVE state that will
- * be restored in to PKRU when we return back to userspace.
+ * This will go out and modify PKRU register to set the access
+ * rights for @pkey to @init_val.
*/
int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
unsigned long init_val)
{
- struct xregs_state *xsave = &tsk->thread.fpu.state.xsave;
- struct pkru_state *old_pkru_state;
- struct pkru_state new_pkru_state;
+ u32 old_pkru;
int pkey_shift = (pkey * PKRU_BITS_PER_PKEY);
u32 new_pkru_bits = 0;
@@ -974,6 +886,15 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
*/
if (!boot_cpu_has(X86_FEATURE_OSPKE))
return -EINVAL;
+ /*
+ * For most XSAVE components, this would be an arduous task:
+ * brining fpstate up to date with fpregs, updating fpstate,
+ * then re-populating fpregs. But, for components that are
+ * never lazily managed, we can just access the fpregs
+ * directly. PKRU is never managed lazily, so we can just
+ * manipulate it directly. Make sure it stays that way.
+ */
+ WARN_ON_ONCE(!use_eager_fpu());
/* Set the bits we need in PKRU: */
if (init_val & PKEY_DISABLE_ACCESS)
@@ -984,37 +905,12 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
/* Shift the bits in to the correct place in PKRU for pkey: */
new_pkru_bits <<= pkey_shift;
- /* Locate old copy of the state in the xsave buffer: */
- old_pkru_state = get_xsave_addr(xsave, XFEATURE_MASK_PKRU);
-
- /*
- * When state is not in the buffer, it is in the init
- * state, set it manually. Otherwise, copy out the old
- * state.
- */
- if (!old_pkru_state)
- new_pkru_state.pkru = 0;
- else
- new_pkru_state.pkru = old_pkru_state->pkru;
-
- /* Mask off any old bits in place: */
- new_pkru_state.pkru &= ~((PKRU_AD_BIT|PKRU_WD_BIT) << pkey_shift);
-
- /* Set the newly-requested bits: */
- new_pkru_state.pkru |= new_pkru_bits;
-
- /*
- * We could theoretically live without zeroing pkru.pad.
- * The current XSAVE feature state definition says that
- * only bytes 0->3 are used. But we do not want to
- * chance leaking kernel stack out to userspace in case a
- * memcpy() of the whole xsave buffer was done.
- *
- * They're in the same cacheline anyway.
- */
- new_pkru_state.pad = 0;
+ /* Get old PKRU and mask off any old bits in place: */
+ old_pkru = read_pkru();
+ old_pkru &= ~((PKRU_AD_BIT|PKRU_WD_BIT) << pkey_shift);
- fpu__xfeature_set_state(XFEATURE_MASK_PKRU, &new_pkru_state, sizeof(new_pkru_state));
+ /* Write old part along with new part: */
+ write_pkru(old_pkru | new_pkru_bits);
return 0;
}
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 2dda0bc4576e..f16c55bfc090 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -25,8 +25,6 @@ static void __init i386_default_early_setup(void)
/* Initialize 32bit specific setup functions */
x86_init.resources.reserve_resources = i386_reserve_resources;
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
-
- reserve_bios_regions();
}
asmlinkage __visible void __init i386_start_kernel(void)
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 99d48e7d2974..54a2372f5dbb 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -183,7 +183,6 @@ void __init x86_64_start_reservations(char *real_mode_data)
copy_bootdata(__va(real_mode_data));
x86_early_init_platform_quirks();
- reserve_bios_regions();
switch (boot_params.hdr.hardware_subarch) {
case X86_SUBARCH_INTEL_MID:
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 3d747070fe67..c6dfd801df97 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -1019,7 +1019,6 @@ void hpet_disable(void)
*/
#include <linux/mc146818rtc.h>
#include <linux/rtc.h>
-#include <asm/rtc.h>
#define DEFAULT_RTC_INT_FREQ 64
#define DEFAULT_RTC_SHIFT 6
@@ -1243,7 +1242,7 @@ irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
memset(&curr_time, 0, sizeof(struct rtc_time));
if (hpet_rtc_flags & (RTC_UIE | RTC_AIE))
- get_rtc_time(&curr_time);
+ mc146818_get_time(&curr_time);
if (hpet_rtc_flags & RTC_UIE &&
curr_time.tm_sec != hpet_prev_update_sec) {
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 61521dc19c10..9f669fdd2010 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -102,8 +102,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_puts(p, " Rescheduling interrupts\n");
seq_printf(p, "%*s: ", prec, "CAL");
for_each_online_cpu(j)
- seq_printf(p, "%10u ", irq_stats(j)->irq_call_count -
- irq_stats(j)->irq_tlb_count);
+ seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
seq_puts(p, " Function call interrupts\n");
seq_printf(p, "%*s: ", prec, "TLB");
for_each_online_cpu(j)
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index 04b132a767f1..bfe4d6c96fbd 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -17,6 +17,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/hardirq.h>
+#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/export.h>
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 833b1d329c47..5d400ba1349d 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -340,7 +340,7 @@ static inline struct iommu_table *find_iommu_table(struct device *dev)
static void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems,enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -364,7 +364,7 @@ static void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist,
static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu_table *tbl = find_iommu_table(dev);
struct scatterlist *s;
@@ -396,7 +396,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
return nelems;
error:
- calgary_unmap_sg(dev, sg, nelems, dir, NULL);
+ calgary_unmap_sg(dev, sg, nelems, dir, 0);
for_each_sg(sg, s, nelems, i) {
sg->dma_address = DMA_ERROR_CODE;
sg->dma_length = 0;
@@ -407,7 +407,7 @@ error:
static dma_addr_t calgary_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *vaddr = page_address(page) + offset;
unsigned long uaddr;
@@ -422,7 +422,7 @@ static dma_addr_t calgary_map_page(struct device *dev, struct page *page,
static void calgary_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct iommu_table *tbl = find_iommu_table(dev);
unsigned int npages;
@@ -432,7 +432,7 @@ static void calgary_unmap_page(struct device *dev, dma_addr_t dma_addr,
}
static void* calgary_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs)
+ dma_addr_t *dma_handle, gfp_t flag, unsigned long attrs)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -466,7 +466,7 @@ error:
static void calgary_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned int npages;
struct iommu_table *tbl = find_iommu_table(dev);
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 6ba014c61d62..d30c37750765 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -77,7 +77,7 @@ void __init pci_iommu_alloc(void)
}
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long dma_mask;
struct page *page;
@@ -120,7 +120,7 @@ again:
}
void dma_generic_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, unsigned long attrs)
{
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page *page = virt_to_page(vaddr);
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index da15918d1c81..00e71ce396a8 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -28,7 +28,7 @@ check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t bus = page_to_phys(page) + offset;
WARN_ON(size == 0);
@@ -55,7 +55,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
*/
static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 5069ef560d83..b47edb8f5256 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -16,7 +16,7 @@ int swiotlb __read_mostly;
void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *vaddr;
@@ -37,7 +37,7 @@ void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
void x86_swiotlb_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 600edd225e81..f79576a541ff 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -923,15 +923,18 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value)
case offsetof(struct user32, regs.orig_eax):
/*
- * A 32-bit debugger setting orig_eax means to restore
- * the state of the task restarting a 32-bit syscall.
- * Make sure we interpret the -ERESTART* codes correctly
- * in case the task is not actually still sitting at the
- * exit from a 32-bit syscall with TS_COMPAT still set.
+ * Warning: bizarre corner case fixup here. A 32-bit
+ * debugger setting orig_eax to -1 wants to disable
+ * syscall restart. Make sure that the syscall
+ * restart code sign-extends orig_ax. Also make sure
+ * we interpret the -ERESTART* codes correctly if
+ * loaded into regs->ax in case the task is not
+ * actually still sitting at the exit from a 32-bit
+ * syscall with TS_COMPAT still set.
*/
regs->orig_ax = value;
if (syscall_get_nr(child, regs) >= 0)
- task_thread_info(child)->status |= TS_COMPAT;
+ task_thread_info(child)->status |= TS_I386_REGS_POKED;
break;
case offsetof(struct user32, regs.eflags):
diff --git a/arch/x86/kernel/pvclock.c b/arch/x86/kernel/pvclock.c
index 06c58ce46762..3599404e3089 100644
--- a/arch/x86/kernel/pvclock.c
+++ b/arch/x86/kernel/pvclock.c
@@ -64,14 +64,9 @@ u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src)
u8 flags;
do {
- version = src->version;
- /* Make the latest version visible */
- smp_rmb();
-
+ version = pvclock_read_begin(src);
flags = src->flags;
- /* Make sure that the version double-check is last. */
- smp_rmb();
- } while ((src->version & 1) || version != src->version);
+ } while (pvclock_read_retry(src, version));
return flags & valid_flags;
}
@@ -84,10 +79,10 @@ cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
u8 flags;
do {
- version = __pvclock_read_cycles(src, &ret, &flags);
- /* Make sure that the version double-check is last. */
- smp_rmb();
- } while ((src->version & 1) || version != src->version);
+ version = pvclock_read_begin(src);
+ ret = __pvclock_read_cycles(src);
+ flags = src->flags;
+ } while (pvclock_read_retry(src, version));
if (unlikely((flags & PVCLOCK_GUEST_STOPPED) != 0)) {
src->flags &= ~PVCLOCK_GUEST_STOPPED;
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index eceaa082ec3f..79c6311cd912 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -13,7 +13,6 @@
#include <asm/x86_init.h>
#include <asm/time.h>
#include <asm/intel-mid.h>
-#include <asm/rtc.h>
#include <asm/setup.h>
#ifdef CONFIG_X86_32
@@ -47,7 +46,7 @@ int mach_set_rtc_mmss(const struct timespec *now)
rtc_time_to_tm(nowtime, &tm);
if (!rtc_valid_tm(&tm)) {
- retval = set_rtc_time(&tm);
+ retval = mc146818_set_time(&tm);
if (retval)
printk(KERN_ERR "%s: RTC write failed with error %d\n",
__func__, retval);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 991b77986d57..0fa60f5f5a16 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -936,8 +936,6 @@ void __init setup_arch(char **cmdline_p)
x86_init.oem.arch_setup();
- kernel_randomize_memory();
-
iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
setup_memory_map();
parse_setup_data();
@@ -1055,6 +1053,12 @@ void __init setup_arch(char **cmdline_p)
max_possible_pfn = max_pfn;
+ /*
+ * Define random base addresses for memory sections after max_pfn is
+ * defined and before each memory section base is used.
+ */
+ kernel_randomize_memory();
+
#ifdef CONFIG_X86_32
/* max_low_pfn get updated here */
find_low_pfn_range();
@@ -1097,6 +1101,8 @@ void __init setup_arch(char **cmdline_p)
efi_find_mirror();
}
+ reserve_bios_regions();
+
/*
* The EFI specification says that boot service code won't be called
* after ExitBootServices(). This is, in fact, a lie.
@@ -1125,7 +1131,15 @@ void __init setup_arch(char **cmdline_p)
early_trap_pf_init();
- setup_real_mode();
+ /*
+ * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features)
+ * with the current CR4 value. This may not be necessary, but
+ * auditing all the early-boot CR4 manipulation would be needed to
+ * rule it out.
+ */
+ if (boot_cpu_data.cpuid_level >= 0)
+ /* A CPU has %cr4 if and only if it has CPUID. */
+ mmu_cr4_features = __read_cr4();
memblock_set_current_limit(get_max_mapped());
@@ -1174,13 +1188,6 @@ void __init setup_arch(char **cmdline_p)
kasan_init();
- if (boot_cpu_data.cpuid_level >= 0) {
- /* A CPU has %cr4 if and only if it has CPUID */
- mmu_cr4_features = __read_cr4();
- if (trampoline_cr4_features)
- *trampoline_cr4_features = mmu_cr4_features;
- }
-
#ifdef CONFIG_X86_32
/* sync back kernel address range */
clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 22cc2f9f8aec..04cb3212db2d 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -146,7 +146,7 @@ static int restore_sigcontext(struct pt_regs *regs,
buf = (void __user *)buf_val;
} get_user_catch(err);
- err |= fpu__restore_sig(buf, config_enabled(CONFIG_X86_32));
+ err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32));
force_iret();
@@ -245,14 +245,14 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
struct fpu *fpu = &current->thread.fpu;
/* redzone */
- if (config_enabled(CONFIG_X86_64))
+ if (IS_ENABLED(CONFIG_X86_64))
sp -= 128;
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
- } else if (config_enabled(CONFIG_X86_32) &&
+ } else if (IS_ENABLED(CONFIG_X86_32) &&
!onsigstack &&
(regs->ss & 0xffff) != __USER_DS &&
!(ka->sa.sa_flags & SA_RESTORER) &&
@@ -262,7 +262,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
}
if (fpu->fpstate_active) {
- sp = fpu__alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
+ sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
&buf_fx, &math_size);
*fpstate = (void __user *)sp;
}
@@ -662,18 +662,18 @@ badframe:
static inline int is_ia32_compat_frame(void)
{
- return config_enabled(CONFIG_IA32_EMULATION) &&
+ return IS_ENABLED(CONFIG_IA32_EMULATION) &&
test_thread_flag(TIF_IA32);
}
static inline int is_ia32_frame(void)
{
- return config_enabled(CONFIG_X86_32) || is_ia32_compat_frame();
+ return IS_ENABLED(CONFIG_X86_32) || is_ia32_compat_frame();
}
static inline int is_x32_frame(void)
{
- return config_enabled(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32);
+ return IS_ENABLED(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32);
}
static int
@@ -760,8 +760,30 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
{
-#ifdef CONFIG_X86_64
- if (in_ia32_syscall())
+ /*
+ * This function is fundamentally broken as currently
+ * implemented.
+ *
+ * The idea is that we want to trigger a call to the
+ * restart_block() syscall and that we want in_ia32_syscall(),
+ * in_x32_syscall(), etc. to match whatever they were in the
+ * syscall being restarted. We assume that the syscall
+ * instruction at (regs->ip - 2) matches whatever syscall
+ * instruction we used to enter in the first place.
+ *
+ * The problem is that we can get here when ptrace pokes
+ * syscall-like values into regs even if we're not in a syscall
+ * at all.
+ *
+ * For now, we maintain historical behavior and guess based on
+ * stored state. We could do better by saving the actual
+ * syscall arch in restart_block or (with caveats on x32) by
+ * checking if regs->ip points to 'int $0x80'. The current
+ * behavior is incorrect if a tracer has a different bitness
+ * than the tracee.
+ */
+#ifdef CONFIG_IA32_EMULATION
+ if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED))
return __NR_ia32_restart_syscall;
#endif
#ifdef CONFIG_X86_X32_ABI
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 1ef87e887051..78b9cb5a26af 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -22,6 +22,7 @@
#include <asm/nmi.h>
#include <asm/x86_init.h>
#include <asm/geode.h>
+#include <asm/apic.h>
unsigned int __read_mostly cpu_khz; /* TSC clocks / usec, not used here */
EXPORT_SYMBOL(cpu_khz);
@@ -1249,6 +1250,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
(unsigned long)tsc_khz / 1000,
(unsigned long)tsc_khz % 1000);
+ /* Inform the TSC deadline clockevent devices about the recalibration */
+ lapic_update_tsc_freq();
+
out:
if (boot_cpu_has(X86_FEATURE_ART))
art_related_clocksource = &clocksource_tsc;
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 6c1ff31d99ff..495c776de4b4 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -357,20 +357,22 @@ static void riprel_analyze(struct arch_uprobe *auprobe, struct insn *insn)
*cursor &= 0xfe;
}
/*
- * Similar treatment for VEX3 prefix.
- * TODO: add XOP/EVEX treatment when insn decoder supports them
+ * Similar treatment for VEX3/EVEX prefix.
+ * TODO: add XOP treatment when insn decoder supports them
*/
- if (insn->vex_prefix.nbytes == 3) {
+ if (insn->vex_prefix.nbytes >= 3) {
/*
* vex2: c5 rvvvvLpp (has no b bit)
* vex3/xop: c4/8f rxbmmmmm wvvvvLpp
* evex: 62 rxbR00mm wvvvv1pp zllBVaaa
- * (evex will need setting of both b and x since
- * in non-sib encoding evex.x is 4th bit of MODRM.rm)
- * Setting VEX3.b (setting because it has inverted meaning):
+ * Setting VEX3.b (setting because it has inverted meaning).
+ * Setting EVEX.x since (in non-SIB encoding) EVEX.x
+ * is the 4th bit of MODRM.rm, and needs the same treatment.
+ * For VEX3-encoded insns, VEX3.x value has no effect in
+ * non-SIB encoding, the change is superfluous but harmless.
*/
cursor = auprobe->insn + insn_offset_vex_prefix(insn) + 1;
- *cursor |= 0x20;
+ *cursor |= 0x60;
}
/*
@@ -415,12 +417,10 @@ static void riprel_analyze(struct arch_uprobe *auprobe, struct insn *insn)
reg = MODRM_REG(insn); /* Fetch modrm.reg */
reg2 = 0xff; /* Fetch vex.vvvv */
- if (insn->vex_prefix.nbytes == 2)
- reg2 = insn->vex_prefix.bytes[1];
- else if (insn->vex_prefix.nbytes == 3)
+ if (insn->vex_prefix.nbytes)
reg2 = insn->vex_prefix.bytes[2];
/*
- * TODO: add XOP, EXEV vvvv reading.
+ * TODO: add XOP vvvv reading.
*
* vex.vvvv field is in bits 6-3, bits are inverted.
* But in 32-bit mode, high-order bit may be ignored.
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 61ebdc13a29a..035731eb3897 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -120,4 +120,7 @@ void __kvm_migrate_timers(struct kvm_vcpu *vcpu);
int apic_has_pending_timer(struct kvm_vcpu *vcpu);
+int kvm_setup_default_irq_routing(struct kvm *kvm);
+int kvm_setup_empty_irq_routing(struct kvm *kvm);
+
#endif
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 730cf174090a..b62c85229711 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1349,6 +1349,9 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic)
bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
{
+ if (!lapic_in_kernel(vcpu))
+ return false;
+
return vcpu->arch.apic->lapic_timer.hv_timer_in_use;
}
EXPORT_SYMBOL_GPL(kvm_lapic_hv_timer_in_use);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index bc354f003ce1..a45d8580f91e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2809,12 +2809,8 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
vmx->nested.nested_vmx_ept_caps |=
VMX_EPT_EXECUTE_ONLY_BIT;
vmx->nested.nested_vmx_ept_caps &= vmx_capability.ept;
- /*
- * For nested guests, we don't do anything specific
- * for single context invalidation. Hence, only advertise
- * support for global context invalidation.
- */
- vmx->nested.nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT;
+ vmx->nested.nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |
+ VMX_EPT_EXTENT_CONTEXT_BIT;
} else
vmx->nested.nested_vmx_ept_caps = 0;
@@ -2945,7 +2941,6 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
vmx->nested.nested_vmx_secondary_ctls_high);
break;
case MSR_IA32_VMX_EPT_VPID_CAP:
- /* Currently, no nested vpid support */
*pdata = vmx->nested.nested_vmx_ept_caps |
((u64)vmx->nested.nested_vmx_vpid_caps << 32);
break;
@@ -7609,12 +7604,16 @@ static int handle_invept(struct kvm_vcpu *vcpu)
switch (type) {
case VMX_EPT_EXTENT_GLOBAL:
+ /*
+ * TODO: track mappings and invalidate
+ * single context requests appropriately
+ */
+ case VMX_EPT_EXTENT_CONTEXT:
kvm_mmu_sync_roots(vcpu);
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
nested_vmx_succeed(vcpu);
break;
default:
- /* Trap single context invalidation invept calls */
BUG_ON(1);
break;
}
diff --git a/arch/x86/lib/hweight.S b/arch/x86/lib/hweight.S
index 02de3d74d2c5..8a602a1e404a 100644
--- a/arch/x86/lib/hweight.S
+++ b/arch/x86/lib/hweight.S
@@ -35,6 +35,7 @@ ENDPROC(__sw_hweight32)
ENTRY(__sw_hweight64)
#ifdef CONFIG_X86_64
+ pushq %rdi
pushq %rdx
movq %rdi, %rdx # w -> t
@@ -60,6 +61,7 @@ ENTRY(__sw_hweight64)
shrq $56, %rax # w = w_tmp >> 56
popq %rdx
+ popq %rdi
ret
#else /* CONFIG_X86_32 */
/* We're getting an u64 arg in (%eax,%edx): unsigned long hweight64(__u64 w) */
diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
index f7dfeda83e5c..121f59c6ee54 100644
--- a/arch/x86/lib/kaslr.c
+++ b/arch/x86/lib/kaslr.c
@@ -19,7 +19,7 @@
#include <asm/cpufeature.h>
#include <asm/setup.h>
-#define debug_putstr(v) early_printk(v)
+#define debug_putstr(v) early_printk("%s", v)
#define has_cpuflag(f) boot_cpu_has(f)
#define get_boot_seed() kaslr_offset()
#endif
diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
index ec21796ac5fd..4473cb4f8b90 100644
--- a/arch/x86/mm/ident_map.c
+++ b/arch/x86/mm/ident_map.c
@@ -3,15 +3,17 @@
* included by both the compressed kernel and the regular kernel.
*/
-static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
+static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
unsigned long addr, unsigned long end)
{
addr &= PMD_MASK;
for (; addr < end; addr += PMD_SIZE) {
pmd_t *pmd = pmd_page + pmd_index(addr);
- if (!pmd_present(*pmd))
- set_pmd(pmd, __pmd(addr | pmd_flag));
+ if (pmd_present(*pmd))
+ continue;
+
+ set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag));
}
}
@@ -30,13 +32,13 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
if (pud_present(*pud)) {
pmd = pmd_offset(pud, 0);
- ident_pmd_init(info->pmd_flag, pmd, addr, next);
+ ident_pmd_init(info, pmd, addr, next);
continue;
}
pmd = (pmd_t *)info->alloc_pgt_page(info->context);
if (!pmd)
return -ENOMEM;
- ident_pmd_init(info->pmd_flag, pmd, addr, next);
+ ident_pmd_init(info, pmd, addr, next);
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
}
@@ -44,14 +46,15 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
}
int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
- unsigned long addr, unsigned long end)
+ unsigned long pstart, unsigned long pend)
{
+ unsigned long addr = pstart + info->offset;
+ unsigned long end = pend + info->offset;
unsigned long next;
int result;
- int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
for (; addr < end; addr = next) {
- pgd_t *pgd = pgd_page + pgd_index(addr) + off;
+ pgd_t *pgd = pgd_page + pgd_index(addr);
pud_t *pud;
next = (addr & PGDIR_MASK) + PGDIR_SIZE;
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 620928903be3..d28a2d741f9e 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -122,8 +122,18 @@ __ref void *alloc_low_pages(unsigned int num)
return __va(pfn << PAGE_SHIFT);
}
-/* need 3 4k for initial PMD_SIZE, 3 4k for 0-ISA_END_ADDRESS */
-#define INIT_PGT_BUF_SIZE (6 * PAGE_SIZE)
+/*
+ * By default need 3 4k for initial PMD_SIZE, 3 4k for 0-ISA_END_ADDRESS.
+ * With KASLR memory randomization, depending on the machine e820 memory
+ * and the PUD alignment. We may need twice more pages when KASLR memory
+ * randomization is enabled.
+ */
+#ifndef CONFIG_RANDOMIZE_MEMORY
+#define INIT_PGD_PAGE_COUNT 6
+#else
+#define INIT_PGD_PAGE_COUNT 12
+#endif
+#define INIT_PGT_BUF_SIZE (INIT_PGD_PAGE_COUNT * PAGE_SIZE)
RESERVE_BRK(early_pgt_alloc, INIT_PGT_BUF_SIZE);
void __init early_alloc_pgt_buf(void)
{
diff --git a/arch/x86/mm/kaslr.c b/arch/x86/mm/kaslr.c
index 26dccd6c0df1..ec8654f117d8 100644
--- a/arch/x86/mm/kaslr.c
+++ b/arch/x86/mm/kaslr.c
@@ -97,7 +97,7 @@ void __init kernel_randomize_memory(void)
* add padding if needed (especially for memory hotplug support).
*/
BUG_ON(kaslr_regions[0].base != &page_offset_base);
- memory_tb = ((max_pfn << PAGE_SHIFT) >> TB_SHIFT) +
+ memory_tb = DIV_ROUND_UP(max_pfn << PAGE_SHIFT, 1UL << TB_SHIFT) +
CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING;
/* Adapt phyiscal memory region size based on available memory */
diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
index 5ceda85b8687..052c1cb76305 100644
--- a/arch/x86/pci/sta2x11-fixup.c
+++ b/arch/x86/pci/sta2x11-fixup.c
@@ -169,7 +169,7 @@ static void *sta2x11_swiotlb_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *vaddr;
diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
index e88b4176260f..b814ca675131 100644
--- a/arch/x86/pci/vmd.c
+++ b/arch/x86/pci/vmd.c
@@ -274,14 +274,14 @@ static struct dma_map_ops *vmd_dma_ops(struct device *dev)
}
static void *vmd_alloc(struct device *dev, size_t size, dma_addr_t *addr,
- gfp_t flag, struct dma_attrs *attrs)
+ gfp_t flag, unsigned long attrs)
{
return vmd_dma_ops(dev)->alloc(to_vmd_dev(dev), size, addr, flag,
attrs);
}
static void vmd_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t addr, struct dma_attrs *attrs)
+ dma_addr_t addr, unsigned long attrs)
{
return vmd_dma_ops(dev)->free(to_vmd_dev(dev), size, vaddr, addr,
attrs);
@@ -289,7 +289,7 @@ static void vmd_free(struct device *dev, size_t size, void *vaddr,
static int vmd_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return vmd_dma_ops(dev)->mmap(to_vmd_dev(dev), vma, cpu_addr, addr,
size, attrs);
@@ -297,7 +297,7 @@ static int vmd_mmap(struct device *dev, struct vm_area_struct *vma,
static int vmd_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t addr, size_t size,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return vmd_dma_ops(dev)->get_sgtable(to_vmd_dev(dev), sgt, cpu_addr,
addr, size, attrs);
@@ -306,26 +306,26 @@ static int vmd_get_sgtable(struct device *dev, struct sg_table *sgt,
static dma_addr_t vmd_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return vmd_dma_ops(dev)->map_page(to_vmd_dev(dev), page, offset, size,
dir, attrs);
}
static void vmd_unmap_page(struct device *dev, dma_addr_t addr, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
vmd_dma_ops(dev)->unmap_page(to_vmd_dev(dev), addr, size, dir, attrs);
}
static int vmd_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
return vmd_dma_ops(dev)->map_sg(to_vmd_dev(dev), sg, nents, dir, attrs);
}
static void vmd_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
vmd_dma_ops(dev)->unmap_sg(to_vmd_dev(dev), sg, nents, dir, attrs);
}
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 17c8bbd4e2f0..1fbb408e2e72 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -51,7 +51,6 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/x86_init.h>
-#include <asm/rtc.h>
#include <asm/uv/uv.h>
static struct efi efi_phys __initdata;
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 04db6fbce96d..677e29e29473 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -25,6 +25,7 @@
#include <linux/bootmem.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/mc146818rtc.h>
#include <linux/efi.h>
#include <linux/uaccess.h>
#include <linux/io.h>
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 4480c06cade7..89d1146f5a6f 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -254,6 +254,7 @@ void __init efi_free_boot_services(void)
for_each_efi_memory_desc(md) {
unsigned long long start = md->phys_addr;
unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+ size_t rm_size;
if (md->type != EFI_BOOT_SERVICES_CODE &&
md->type != EFI_BOOT_SERVICES_DATA)
@@ -263,6 +264,26 @@ void __init efi_free_boot_services(void)
if (md->attribute & EFI_MEMORY_RUNTIME)
continue;
+ /*
+ * Nasty quirk: if all sub-1MB memory is used for boot
+ * services, we can get here without having allocated the
+ * real mode trampoline. It's too late to hand boot services
+ * memory back to the memblock allocator, so instead
+ * try to manually allocate the trampoline if needed.
+ *
+ * I've seen this on a Dell XPS 13 9350 with firmware
+ * 1.4.4 with SGX enabled booting Linux via Fedora 24's
+ * grub2-efi on a hard disk. (And no, I don't know why
+ * this happened, but Linux should still try to boot rather
+ * panicing early.)
+ */
+ rm_size = real_mode_size_needed();
+ if (rm_size && (start + rm_size) < (1<<20) && size >= rm_size) {
+ set_real_mode_mem(start, rm_size);
+ start += rm_size;
+ size -= rm_size;
+ }
+
free_bootmem_late(start, size);
}
diff --git a/arch/x86/platform/intel-mid/intel_mid_vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
index ee40fcb6e54d..58024862a7eb 100644
--- a/arch/x86/platform/intel-mid/intel_mid_vrtc.c
+++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/sfi.h>
#include <linux/platform_device.h>
+#include <linux/mc146818rtc.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 66b2166ea4a1..23f2f3e41c7f 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -187,7 +187,8 @@ EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target);
void uv_bios_init(void)
{
uv_systab = NULL;
- if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab) {
+ if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
+ !efi.uv_systab || efi_runtime_disabled()) {
pr_crit("UV: UVsystab: missing\n");
return;
}
@@ -199,12 +200,14 @@ void uv_bios_init(void)
return;
}
+ /* Starting with UV4 the UV systab size is variable */
if (uv_systab->revision >= UV_SYSTAB_VERSION_UV4) {
+ int size = uv_systab->size;
+
iounmap(uv_systab);
- uv_systab = ioremap(efi.uv_systab, uv_systab->size);
+ uv_systab = ioremap(efi.uv_systab, size);
if (!uv_systab) {
- pr_err("UV: UVsystab: ioremap(%d) failed!\n",
- uv_systab->size);
+ pr_err("UV: UVsystab: ioremap(%d) failed!\n", size);
return;
}
}
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
index f2b5e6a5cf95..a3e3ccc87138 100644
--- a/arch/x86/power/hibernate_64.c
+++ b/arch/x86/power/hibernate_64.c
@@ -37,11 +37,11 @@ unsigned long jump_address_phys;
*/
unsigned long restore_cr3 __visible;
-pgd_t *temp_level4_pgt __visible;
+unsigned long temp_level4_pgt __visible;
unsigned long relocated_restore_code __visible;
-static int set_up_temporary_text_mapping(void)
+static int set_up_temporary_text_mapping(pgd_t *pgd)
{
pmd_t *pmd;
pud_t *pud;
@@ -71,7 +71,7 @@ static int set_up_temporary_text_mapping(void)
__pmd((jump_address_phys & PMD_MASK) | __PAGE_KERNEL_LARGE_EXEC));
set_pud(pud + pud_index(restore_jump_address),
__pud(__pa(pmd) | _KERNPG_TABLE));
- set_pgd(temp_level4_pgt + pgd_index(restore_jump_address),
+ set_pgd(pgd + pgd_index(restore_jump_address),
__pgd(__pa(pud) | _KERNPG_TABLE));
return 0;
@@ -87,18 +87,19 @@ static int set_up_temporary_mappings(void)
struct x86_mapping_info info = {
.alloc_pgt_page = alloc_pgt_page,
.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
- .kernel_mapping = true,
+ .offset = __PAGE_OFFSET,
};
unsigned long mstart, mend;
+ pgd_t *pgd;
int result;
int i;
- temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
- if (!temp_level4_pgt)
+ pgd = (pgd_t *)get_safe_page(GFP_ATOMIC);
+ if (!pgd)
return -ENOMEM;
/* Prepare a temporary mapping for the kernel text */
- result = set_up_temporary_text_mapping();
+ result = set_up_temporary_text_mapping(pgd);
if (result)
return result;
@@ -107,13 +108,12 @@ static int set_up_temporary_mappings(void)
mstart = pfn_mapped[i].start << PAGE_SHIFT;
mend = pfn_mapped[i].end << PAGE_SHIFT;
- result = kernel_ident_mapping_init(&info, temp_level4_pgt,
- mstart, mend);
-
+ result = kernel_ident_mapping_init(&info, pgd, mstart, mend);
if (result)
return result;
}
+ temp_level4_pgt = (unsigned long)pgd - __PAGE_OFFSET;
return 0;
}
diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index 8eee0e9c93f0..ce8da3a0412c 100644
--- a/arch/x86/power/hibernate_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -72,8 +72,6 @@ ENTRY(restore_image)
/* code below has been relocated to a safe page */
ENTRY(core_restore_code)
/* switch to temporary page tables */
- movq $__PAGE_OFFSET, %rcx
- subq %rcx, %rax
movq %rax, %cr3
/* flush TLB */
movq %rbx, %rcx
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 705e3fffb4a1..5db706f14111 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -1,9 +1,11 @@
#include <linux/io.h>
+#include <linux/slab.h>
#include <linux/memblock.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#include <asm/realmode.h>
+#include <asm/tlbflush.h>
struct real_mode_header *real_mode_header;
u32 *trampoline_cr4_features;
@@ -11,25 +13,37 @@ u32 *trampoline_cr4_features;
/* Hold the pgd entry used on booting additional CPUs */
pgd_t trampoline_pgd_entry;
+void __init set_real_mode_mem(phys_addr_t mem, size_t size)
+{
+ void *base = __va(mem);
+
+ real_mode_header = (struct real_mode_header *) base;
+ printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
+ base, (unsigned long long)mem, size);
+}
+
void __init reserve_real_mode(void)
{
phys_addr_t mem;
- unsigned char *base;
- size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
+ size_t size = real_mode_size_needed();
+
+ if (!size)
+ return;
+
+ WARN_ON(slab_is_available());
/* Has to be under 1M so we can execute real-mode AP code. */
mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
- if (!mem)
- panic("Cannot allocate trampoline\n");
+ if (!mem) {
+ pr_info("No sub-1M memory is available for the trampoline\n");
+ return;
+ }
- base = __va(mem);
memblock_reserve(mem, size);
- real_mode_header = (struct real_mode_header *) base;
- printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
- base, (unsigned long long)mem, size);
+ set_real_mode_mem(mem, size);
}
-void __init setup_real_mode(void)
+static void __init setup_real_mode(void)
{
u16 real_mode_seg;
const u32 *rel;
@@ -84,7 +98,7 @@ void __init setup_real_mode(void)
trampoline_header->start = (u64) secondary_startup_64;
trampoline_cr4_features = &trampoline_header->cr4;
- *trampoline_cr4_features = __read_cr4();
+ *trampoline_cr4_features = mmu_cr4_features;
trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
trampoline_pgd[0] = trampoline_pgd_entry.pgd;
@@ -100,7 +114,7 @@ void __init setup_real_mode(void)
* need to mark it executable at do_pre_smp_initcalls() at least,
* thus run it as a early_initcall().
*/
-static int __init set_real_mode_permissions(void)
+static void __init set_real_mode_permissions(void)
{
unsigned char *base = (unsigned char *) real_mode_header;
size_t size = PAGE_ALIGN(real_mode_blob_end - real_mode_blob);
@@ -119,7 +133,16 @@ static int __init set_real_mode_permissions(void)
set_memory_nx((unsigned long) base, size >> PAGE_SHIFT);
set_memory_ro((unsigned long) base, ro_size >> PAGE_SHIFT);
set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);
+}
+
+static int __init init_real_mode(void)
+{
+ if (!real_mode_header)
+ panic("Real mode trampoline was not allocated");
+
+ setup_real_mode();
+ set_real_mode_permissions();
return 0;
}
-early_initcall(set_real_mode_permissions);
+early_initcall(init_real_mode);
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 6c803ca49b5d..d72dec406ccb 100644
--- a/arch/x86/um/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -2,6 +2,9 @@
# Building vDSO images for x86.
#
+# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
+KCOV_INSTRUMENT := n
+
VDSO64-y := y
vdso-install-$(VDSO64-y) += vdso.so
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index cd66698348ca..1e68806d6695 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -142,7 +142,7 @@ static void xtensa_sync_sg_for_device(struct device *dev,
static void *xtensa_dma_alloc(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unsigned long ret;
unsigned long uncached = 0;
@@ -171,7 +171,7 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size,
}
static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
unsigned long addr = (unsigned long)vaddr +
XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
@@ -185,7 +185,7 @@ static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr,
static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t dma_handle = page_to_phys(page) + offset;
@@ -195,14 +195,14 @@ static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
static void xtensa_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
}
static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
@@ -217,7 +217,7 @@ static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
static void xtensa_unmap_sg(struct device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *s;
int i;
diff --git a/block/Kconfig b/block/Kconfig
index 0363cd731320..161491d0a879 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -88,19 +88,6 @@ config BLK_DEV_INTEGRITY
T10/SCSI Data Integrity Field or the T13/ATA External Path
Protection. If in doubt, say N.
-config BLK_DEV_DAX
- bool "Block device DAX support"
- depends on FS_DAX
- depends on BROKEN
- help
- When DAX support is available (CONFIG_FS_DAX) raw block
- devices can also support direct userspace access to the
- storage capacity via MMAP(2) similar to a file on a
- DAX-enabled filesystem. However, the DAX I/O-path disables
- some standard I/O-statistics, and the MMAP(2) path has some
- operational differences due to bypassing the page
- cache. If in doubt, say N.
-
config BLK_DEV_THROTTLING
bool "Block layer bio throttling support"
depends on BLK_CGROUP=y
diff --git a/block/bio-integrity.c b/block/bio-integrity.c
index f70cc3bdfd01..63f72f00c72e 100644
--- a/block/bio-integrity.c
+++ b/block/bio-integrity.c
@@ -86,7 +86,7 @@ struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
bip->bip_bio = bio;
bio->bi_integrity = bip;
- bio->bi_rw |= REQ_INTEGRITY;
+ bio->bi_opf |= REQ_INTEGRITY;
return bip;
err:
diff --git a/block/bio.c b/block/bio.c
index 54ee3846c3a5..f39477538fef 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -580,9 +580,11 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
*/
bio->bi_bdev = bio_src->bi_bdev;
bio_set_flag(bio, BIO_CLONED);
- bio->bi_rw = bio_src->bi_rw;
+ bio->bi_opf = bio_src->bi_opf;
bio->bi_iter = bio_src->bi_iter;
bio->bi_io_vec = bio_src->bi_io_vec;
+
+ bio_clone_blkcg_association(bio, bio_src);
}
EXPORT_SYMBOL(__bio_clone_fast);
@@ -661,7 +663,7 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask,
if (!bio)
return NULL;
bio->bi_bdev = bio_src->bi_bdev;
- bio->bi_rw = bio_src->bi_rw;
+ bio->bi_opf = bio_src->bi_opf;
bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector;
bio->bi_iter.bi_size = bio_src->bi_iter.bi_size;
@@ -687,6 +689,8 @@ integrity_clone:
}
}
+ bio_clone_blkcg_association(bio, bio_src);
+
return bio;
}
EXPORT_SYMBOL(bio_clone_bioset);
@@ -869,7 +873,7 @@ int submit_bio_wait(struct bio *bio)
init_completion(&ret.event);
bio->bi_private = &ret;
bio->bi_end_io = submit_bio_wait_endio;
- bio->bi_rw |= REQ_SYNC;
+ bio->bi_opf |= REQ_SYNC;
submit_bio(bio);
wait_for_completion_io(&ret.event);
@@ -2004,6 +2008,17 @@ void bio_disassociate_task(struct bio *bio)
}
}
+/**
+ * bio_clone_blkcg_association - clone blkcg association from src to dst bio
+ * @dst: destination bio
+ * @src: source bio
+ */
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src)
+{
+ if (src->bi_css)
+ WARN_ON(bio_associate_blkcg(dst, src->bi_css));
+}
+
#endif /* CONFIG_BLK_CGROUP */
static void __init biovec_init_slabs(void)
diff --git a/block/blk-core.c b/block/blk-core.c
index a687e9cc16c2..999442ec4601 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1029,7 +1029,7 @@ static bool blk_rq_should_init_elevator(struct bio *bio)
* Flush requests do not use the elevator so skip initialization.
* This allows a request to share the flush and elevator data.
*/
- if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA))
+ if (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA))
return false;
return true;
@@ -1504,7 +1504,7 @@ EXPORT_SYMBOL_GPL(blk_add_request_payload);
bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
struct bio *bio)
{
- const int ff = bio->bi_rw & REQ_FAILFAST_MASK;
+ const int ff = bio->bi_opf & REQ_FAILFAST_MASK;
if (!ll_back_merge_fn(q, req, bio))
return false;
@@ -1526,7 +1526,7 @@ bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
bool bio_attempt_front_merge(struct request_queue *q, struct request *req,
struct bio *bio)
{
- const int ff = bio->bi_rw & REQ_FAILFAST_MASK;
+ const int ff = bio->bi_opf & REQ_FAILFAST_MASK;
if (!ll_front_merge_fn(q, req, bio))
return false;
@@ -1648,8 +1648,8 @@ void init_request_from_bio(struct request *req, struct bio *bio)
{
req->cmd_type = REQ_TYPE_FS;
- req->cmd_flags |= bio->bi_rw & REQ_COMMON_MASK;
- if (bio->bi_rw & REQ_RAHEAD)
+ req->cmd_flags |= bio->bi_opf & REQ_COMMON_MASK;
+ if (bio->bi_opf & REQ_RAHEAD)
req->cmd_flags |= REQ_FAILFAST_MASK;
req->errors = 0;
@@ -1660,7 +1660,7 @@ void init_request_from_bio(struct request *req, struct bio *bio)
static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
{
- const bool sync = !!(bio->bi_rw & REQ_SYNC);
+ const bool sync = !!(bio->bi_opf & REQ_SYNC);
struct blk_plug *plug;
int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT;
struct request *req;
@@ -1681,7 +1681,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
return BLK_QC_T_NONE;
}
- if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) {
+ if (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA)) {
spin_lock_irq(q->queue_lock);
where = ELEVATOR_INSERT_FLUSH;
goto get_rq;
@@ -1728,7 +1728,7 @@ get_rq:
/*
* Add in META/PRIO flags, if set, before we get to the IO scheduler
*/
- rw_flags |= (bio->bi_rw & (REQ_META | REQ_PRIO));
+ rw_flags |= (bio->bi_opf & (REQ_META | REQ_PRIO));
/*
* Grab a free request. This is might sleep but can not fail.
@@ -1805,7 +1805,7 @@ static void handle_bad_sector(struct bio *bio)
printk(KERN_INFO "attempt to access beyond end of device\n");
printk(KERN_INFO "%s: rw=%d, want=%Lu, limit=%Lu\n",
bdevname(bio->bi_bdev, b),
- bio->bi_rw,
+ bio->bi_opf,
(unsigned long long)bio_end_sector(bio),
(long long)(i_size_read(bio->bi_bdev->bd_inode) >> 9));
}
@@ -1918,9 +1918,9 @@ generic_make_request_checks(struct bio *bio)
* drivers without flush support don't have to worry
* about them.
*/
- if ((bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) &&
+ if ((bio->bi_opf & (REQ_PREFLUSH | REQ_FUA)) &&
!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) {
- bio->bi_rw &= ~(REQ_PREFLUSH | REQ_FUA);
+ bio->bi_opf &= ~(REQ_PREFLUSH | REQ_FUA);
if (!nr_sectors) {
err = 0;
goto end_io;
@@ -2219,7 +2219,7 @@ unsigned int blk_rq_err_bytes(const struct request *rq)
* one.
*/
for (bio = rq->bio; bio; bio = bio->bi_next) {
- if ((bio->bi_rw & ff) != ff)
+ if ((bio->bi_opf & ff) != ff)
break;
bytes += bio->bi_iter.bi_size;
}
@@ -2630,7 +2630,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
/* mixed attributes always follow the first bio */
if (req->cmd_flags & REQ_MIXED_MERGE) {
req->cmd_flags &= ~REQ_FAILFAST_MASK;
- req->cmd_flags |= req->bio->bi_rw & REQ_FAILFAST_MASK;
+ req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK;
}
/*
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 41cbd4878958..3eec75a9e91d 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -186,7 +186,7 @@ void blk_queue_split(struct request_queue *q, struct bio **bio,
if (split) {
/* there isn't chance to merge the splitted bio */
- split->bi_rw |= REQ_NOMERGE;
+ split->bi_opf |= REQ_NOMERGE;
bio_chain(split, *bio);
trace_block_split(q, split, (*bio)->bi_iter.bi_sector);
@@ -616,9 +616,9 @@ void blk_rq_set_mixed_merge(struct request *rq)
* Distributes the attributs to each bio.
*/
for (bio = rq->bio; bio; bio = bio->bi_next) {
- WARN_ON_ONCE((bio->bi_rw & REQ_FAILFAST_MASK) &&
- (bio->bi_rw & REQ_FAILFAST_MASK) != ff);
- bio->bi_rw |= ff;
+ WARN_ON_ONCE((bio->bi_opf & REQ_FAILFAST_MASK) &&
+ (bio->bi_opf & REQ_FAILFAST_MASK) != ff);
+ bio->bi_opf |= ff;
}
rq->cmd_flags |= REQ_MIXED_MERGE;
}
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index 4ea4dd8a1eed..fe822aa5b8e4 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -380,15 +380,13 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
return ret;
}
-void blk_mq_unregister_disk(struct gendisk *disk)
+static void __blk_mq_unregister_disk(struct gendisk *disk)
{
struct request_queue *q = disk->queue;
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx;
int i, j;
- blk_mq_disable_hotplug();
-
queue_for_each_hw_ctx(q, hctx, i) {
blk_mq_unregister_hctx(hctx);
@@ -405,6 +403,12 @@ void blk_mq_unregister_disk(struct gendisk *disk)
kobject_put(&disk_to_dev(disk)->kobj);
q->mq_sysfs_init_done = false;
+}
+
+void blk_mq_unregister_disk(struct gendisk *disk)
+{
+ blk_mq_disable_hotplug();
+ __blk_mq_unregister_disk(disk);
blk_mq_enable_hotplug();
}
@@ -450,7 +454,7 @@ int blk_mq_register_disk(struct gendisk *disk)
}
if (ret)
- blk_mq_unregister_disk(disk);
+ __blk_mq_unregister_disk(disk);
else
q->mq_sysfs_init_done = true;
out:
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 576e7112f807..e931a0e8e73d 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -672,7 +672,20 @@ static void blk_mq_timeout_work(struct work_struct *work)
};
int i;
- if (blk_queue_enter(q, true))
+ /* A deadlock might occur if a request is stuck requiring a
+ * timeout at the same time a queue freeze is waiting
+ * completion, since the timeout code would not be able to
+ * acquire the queue reference here.
+ *
+ * That's why we don't use blk_queue_enter here; instead, we use
+ * percpu_ref_tryget directly, because we need to be able to
+ * obtain a reference even in the short window between the queue
+ * starting to freeze, by dropping the first reference in
+ * blk_mq_freeze_queue_start, and the moment the last request is
+ * consumed, marked by the instant q_usage_counter reaches
+ * zero.
+ */
+ if (!percpu_ref_tryget(&q->q_usage_counter))
return;
blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &data);
@@ -1221,7 +1234,7 @@ static struct request *blk_mq_map_request(struct request_queue *q,
ctx = blk_mq_get_ctx(q);
hctx = q->mq_ops->map_queue(q, ctx->cpu);
- if (rw_is_sync(bio_op(bio), bio->bi_rw))
+ if (rw_is_sync(bio_op(bio), bio->bi_opf))
op_flags |= REQ_SYNC;
trace_block_getrq(q, bio, op);
@@ -1289,8 +1302,8 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
*/
static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
{
- const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw);
- const int is_flush_fua = bio->bi_rw & (REQ_PREFLUSH | REQ_FUA);
+ const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+ const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
struct blk_map_ctx data;
struct request *rq;
unsigned int request_count = 0;
@@ -1383,8 +1396,8 @@ done:
*/
static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
{
- const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw);
- const int is_flush_fua = bio->bi_rw & (REQ_PREFLUSH | REQ_FUA);
+ const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+ const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
struct blk_plug *plug;
unsigned int request_count = 0;
struct blk_map_ctx data;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 47a3e540631a..f1aba26f4719 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -145,11 +145,6 @@ struct throtl_data
/* Total Number of queued bios on READ and WRITE lists */
unsigned int nr_queued[2];
- /*
- * number of total undestroyed groups
- */
- unsigned int nr_undestroyed_grps;
-
/* Work for dispatching throttled bios */
struct work_struct dispatch_work;
};
@@ -826,8 +821,8 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
* second time when it eventually gets issued. Set it when a bio
* is being charged to a tg.
*/
- if (!(bio->bi_rw & REQ_THROTTLED))
- bio->bi_rw |= REQ_THROTTLED;
+ if (!(bio->bi_opf & REQ_THROTTLED))
+ bio->bi_opf |= REQ_THROTTLED;
}
/**
@@ -1404,7 +1399,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg,
WARN_ON_ONCE(!rcu_read_lock_held());
/* see throtl_charge_bio() */
- if ((bio->bi_rw & REQ_THROTTLED) || !tg->has_rules[rw])
+ if ((bio->bi_opf & REQ_THROTTLED) || !tg->has_rules[rw])
goto out;
spin_lock_irq(q->queue_lock);
@@ -1483,7 +1478,7 @@ out:
* being issued.
*/
if (!throttled)
- bio->bi_rw &= ~REQ_THROTTLED;
+ bio->bi_opf &= ~REQ_THROTTLED;
return throttled;
}
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index acabba198de9..cc2f6dbd4303 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -918,7 +918,7 @@ static inline struct cfq_data *cic_to_cfqd(struct cfq_io_cq *cic)
*/
static inline bool cfq_bio_sync(struct bio *bio)
{
- return bio_data_dir(bio) == READ || (bio->bi_rw & REQ_SYNC);
+ return bio_data_dir(bio) == READ || (bio->bi_opf & REQ_SYNC);
}
/*
@@ -2565,7 +2565,7 @@ static void cfq_merged_request(struct request_queue *q, struct request *req,
static void cfq_bio_merged(struct request_queue *q, struct request *req,
struct bio *bio)
{
- cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_rw);
+ cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_opf);
}
static void
diff --git a/block/genhd.c b/block/genhd.c
index 3c9dede4e04f..fcd6d4fae657 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -614,7 +614,7 @@ void device_add_disk(struct device *parent, struct gendisk *disk)
/* Register BDI before referencing it from bdev */
bdi = &disk->queue->backing_dev_info;
- bdi_register_dev(bdi, disk_devt(disk));
+ bdi_register_owner(bdi, disk_to_dev(disk));
blk_register_region(disk_devt(disk), disk->minors, NULL,
exact_match, exact_lock, disk);
@@ -856,6 +856,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v)
if (iter) {
class_dev_iter_exit(iter);
kfree(iter);
+ seqf->private = NULL;
}
}
diff --git a/crypto/Kconfig b/crypto/Kconfig
index a9377bef25e3..84d71482bf08 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -439,7 +439,7 @@ config CRYPTO_CRC32C_INTEL
config CRYPT_CRC32C_VPMSUM
tristate "CRC32c CRC algorithm (powerpc64)"
- depends on PPC64
+ depends on PPC64 && ALTIVEC
select CRYPTO_HASH
select CRC32
help
diff --git a/crypto/sha3_generic.c b/crypto/sha3_generic.c
index 62264397a2d2..7e8ed96236ce 100644
--- a/crypto/sha3_generic.c
+++ b/crypto/sha3_generic.c
@@ -24,14 +24,14 @@
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
static const u64 keccakf_rndc[24] = {
- 0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
- 0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
- 0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
- 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
- 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
- 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
- 0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
- 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
+ 0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
+ 0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
+ 0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
+ 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
+ 0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
+ 0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
+ 0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
+ 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
};
static const int keccakf_rotc[24] = {
diff --git a/drivers/Makefile b/drivers/Makefile
index 954824438fd1..53abb4a5f736 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -138,6 +138,7 @@ obj-$(CONFIG_OF) += of/
obj-$(CONFIG_SSB) += ssb/
obj-$(CONFIG_BCMA) += bcma/
obj-$(CONFIG_VHOST_RING) += vhost/
+obj-$(CONFIG_VHOST) += vhost/
obj-$(CONFIG_VLYNQ) += vlynq/
obj-$(CONFIG_STAGING) += staging/
obj-y += platform/
diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c
index 81dc75033f15..0980a133916f 100644
--- a/drivers/acpi/acpi_cmos_rtc.c
+++ b/drivers/acpi/acpi_cmos_rtc.c
@@ -14,7 +14,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <asm-generic/rtc.h>
+#include <linux/mc146818rtc.h>
#include "internal.h"
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 148f4e5ca104..31abb0bdd4f2 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -232,8 +232,10 @@ remove_dev_dir:
acpi_device_dir(device) = NULL;
remove_lid_dir:
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+ acpi_lid_dir = NULL;
remove_button_dir:
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+ acpi_button_dir = NULL;
goto done;
}
@@ -250,7 +252,9 @@ static int acpi_button_remove_fs(struct acpi_device *device)
acpi_lid_dir);
acpi_device_dir(device) = NULL;
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+ acpi_lid_dir = NULL;
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+ acpi_button_dir = NULL;
return 0;
}
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 999a10914678..e7bd57cc550a 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -101,6 +101,7 @@ enum ec_command {
#define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */
#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
* when trying to clear the EC */
+#define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */
enum {
EC_FLAGS_QUERY_PENDING, /* Query is pending */
@@ -121,6 +122,10 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
module_param(ec_delay, uint, 0644);
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
+static unsigned int ec_max_queries __read_mostly = ACPI_EC_MAX_QUERIES;
+module_param(ec_max_queries, uint, 0644);
+MODULE_PARM_DESC(ec_max_queries, "Maximum parallel _Qxx evaluations");
+
static bool ec_busy_polling __read_mostly;
module_param(ec_busy_polling, bool, 0644);
MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction");
@@ -174,6 +179,7 @@ static void acpi_ec_event_processor(struct work_struct *work);
struct acpi_ec *boot_ec, *first_ec;
EXPORT_SYMBOL(first_ec);
+static struct workqueue_struct *ec_query_wq;
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
@@ -1098,7 +1104,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
* work queue execution.
*/
ec_dbg_evt("Query(0x%02x) scheduled", value);
- if (!schedule_work(&q->work)) {
+ if (!queue_work(ec_query_wq, &q->work)) {
ec_dbg_evt("Query(0x%02x) overlapped", value);
result = -EBUSY;
}
@@ -1660,15 +1666,41 @@ static struct acpi_driver acpi_ec_driver = {
},
};
+static inline int acpi_ec_query_init(void)
+{
+ if (!ec_query_wq) {
+ ec_query_wq = alloc_workqueue("kec_query", 0,
+ ec_max_queries);
+ if (!ec_query_wq)
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static inline void acpi_ec_query_exit(void)
+{
+ if (ec_query_wq) {
+ destroy_workqueue(ec_query_wq);
+ ec_query_wq = NULL;
+ }
+}
+
int __init acpi_ec_init(void)
{
- int result = 0;
+ int result;
+ /* register workqueue for _Qxx evaluations */
+ result = acpi_ec_query_init();
+ if (result)
+ goto err_exit;
/* Now register the driver for the EC */
result = acpi_bus_register_driver(&acpi_ec_driver);
- if (result < 0)
- return -ENODEV;
+ if (result)
+ goto err_exit;
+err_exit:
+ if (result)
+ acpi_ec_query_exit();
return result;
}
@@ -1678,5 +1710,6 @@ static void __exit acpi_ec_exit(void)
{
acpi_bus_unregister_driver(&acpi_ec_driver);
+ acpi_ec_query_exit();
}
#endif /* 0 */
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 8c234dd9b8bc..80cc7c089a15 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1527,11 +1527,12 @@ static u32 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
{
struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
u64 offset = nfit_blk->stat_offset + mmio->size * bw;
+ const u32 STATUS_MASK = 0x80000037;
if (mmio->num_lines)
offset = to_interleave_offset(offset, mmio);
- return readl(mmio->addr.base + offset);
+ return readl(mmio->addr.base + offset) & STATUS_MASK;
}
static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c
index 7c04c87738a6..df0c70963d9e 100644
--- a/drivers/base/power/opp/core.c
+++ b/drivers/base/power/opp/core.c
@@ -402,6 +402,22 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
+static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table,
+ unsigned long *freq)
+{
+ struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+
+ list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
+ if (temp_opp->available && temp_opp->rate >= *freq) {
+ opp = temp_opp;
+ *freq = opp->rate;
+ break;
+ }
+ }
+
+ return opp;
+}
+
/**
* dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq
* @dev: device for which we do this operation
@@ -427,7 +443,6 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
unsigned long *freq)
{
struct opp_table *opp_table;
- struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
opp_rcu_lockdep_assert();
@@ -440,15 +455,7 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
if (IS_ERR(opp_table))
return ERR_CAST(opp_table);
- list_for_each_entry_rcu(temp_opp, &opp_table->opp_list, node) {
- if (temp_opp->available && temp_opp->rate >= *freq) {
- opp = temp_opp;
- *freq = opp->rate;
- break;
- }
- }
-
- return opp;
+ return _find_freq_ceil(opp_table, freq);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
@@ -612,7 +619,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
return PTR_ERR(opp_table);
}
- old_opp = dev_pm_opp_find_freq_ceil(dev, &old_freq);
+ old_opp = _find_freq_ceil(opp_table, &old_freq);
if (!IS_ERR(old_opp)) {
ou_volt = old_opp->u_volt;
ou_volt_min = old_opp->u_volt_min;
@@ -622,7 +629,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
__func__, old_freq, PTR_ERR(old_opp));
}
- opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+ opp = _find_freq_ceil(opp_table, &freq);
if (IS_ERR(opp)) {
ret = PTR_ERR(opp);
dev_err(dev, "%s: failed to find OPP for freq %lu (%d)\n",
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index a6975795e7f3..efec10b49d59 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -11,7 +11,7 @@
#include <linux/export.h>
#include <linux/rtc.h>
-#include <asm/rtc.h>
+#include <linux/mc146818rtc.h>
#include "power.h"
@@ -103,7 +103,7 @@ static int set_magic_time(unsigned int user, unsigned int file, unsigned int dev
n /= 24;
time.tm_min = (n % 20) * 3;
n /= 20;
- set_rtc_time(&time);
+ mc146818_set_time(&time);
return n ? -1 : 0;
}
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
struct rtc_time time;
unsigned int val;
- get_rtc_time(&time);
+ mc146818_get_time(&time);
pr_info("RTC time: %2d:%02d:%02d, date: %02d/%02d/%02d\n",
time.tm_hour, time.tm_min, time.tm_sec,
time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 5fb7718f256c..62e4de2aa8d1 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -334,10 +334,9 @@ void device_wakeup_arm_wake_irqs(void)
struct wakeup_source *ws;
rcu_read_lock();
- list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
- if (ws->wakeirq)
- dev_pm_arm_wake_irq(ws->wakeirq);
- }
+ list_for_each_entry_rcu(ws, &wakeup_sources, entry)
+ dev_pm_arm_wake_irq(ws->wakeirq);
+
rcu_read_unlock();
}
@@ -351,10 +350,9 @@ void device_wakeup_disarm_wake_irqs(void)
struct wakeup_source *ws;
rcu_read_lock();
- list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
- if (ws->wakeirq)
- dev_pm_disarm_wake_irq(ws->wakeirq);
- }
+ list_for_each_entry_rcu(ws, &wakeup_sources, entry)
+ dev_pm_disarm_wake_irq(ws->wakeirq);
+
rcu_read_unlock();
}
@@ -390,9 +388,7 @@ int device_wakeup_disable(struct device *dev)
return -EINVAL;
ws = device_wakeup_detach(dev);
- if (ws)
- wakeup_source_unregister(ws);
-
+ wakeup_source_unregister(ws);
return 0;
}
EXPORT_SYMBOL_GPL(device_wakeup_disable);
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 3022dad24071..0c76d4016eeb 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -300,20 +300,20 @@ static void copy_from_brd(void *dst, struct brd_device *brd,
* Process a single bvec of a bio.
*/
static int brd_do_bvec(struct brd_device *brd, struct page *page,
- unsigned int len, unsigned int off, int rw,
+ unsigned int len, unsigned int off, bool is_write,
sector_t sector)
{
void *mem;
int err = 0;
- if (rw != READ) {
+ if (is_write) {
err = copy_to_brd_setup(brd, sector, len);
if (err)
goto out;
}
mem = kmap_atomic(page);
- if (rw == READ) {
+ if (!is_write) {
copy_from_brd(mem + off, brd, sector, len);
flush_dcache_page(page);
} else {
@@ -330,7 +330,6 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
{
struct block_device *bdev = bio->bi_bdev;
struct brd_device *brd = bdev->bd_disk->private_data;
- int rw;
struct bio_vec bvec;
sector_t sector;
struct bvec_iter iter;
@@ -347,14 +346,12 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
goto out;
}
- rw = bio_data_dir(bio);
-
bio_for_each_segment(bvec, bio, iter) {
unsigned int len = bvec.bv_len;
int err;
- err = brd_do_bvec(brd, bvec.bv_page, len,
- bvec.bv_offset, rw, sector);
+ err = brd_do_bvec(brd, bvec.bv_page, len, bvec.bv_offset,
+ op_is_write(bio_op(bio)), sector);
if (err)
goto io_error;
sector += len >> SECTOR_SHIFT;
@@ -369,11 +366,11 @@ io_error:
}
static int brd_rw_page(struct block_device *bdev, sector_t sector,
- struct page *page, int rw)
+ struct page *page, bool is_write)
{
struct brd_device *brd = bdev->bd_disk->private_data;
- int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, rw, sector);
- page_endio(page, rw & WRITE, err);
+ int err = brd_do_bvec(brd, page, PAGE_SIZE, 0, is_write, sector);
+ page_endio(page, is_write, err);
return err;
}
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 0501ae0c517b..100be556e613 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1663,13 +1663,13 @@ static u32 bio_flags_to_wire(struct drbd_connection *connection,
struct bio *bio)
{
if (connection->agreed_pro_version >= 95)
- return (bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
- (bio->bi_rw & REQ_FUA ? DP_FUA : 0) |
- (bio->bi_rw & REQ_PREFLUSH ? DP_FLUSH : 0) |
+ return (bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0) |
+ (bio->bi_opf & REQ_FUA ? DP_FUA : 0) |
+ (bio->bi_opf & REQ_PREFLUSH ? DP_FLUSH : 0) |
(bio_op(bio) == REQ_OP_WRITE_SAME ? DP_WSAME : 0) |
(bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0);
else
- return bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0;
+ return bio->bi_opf & REQ_SYNC ? DP_RW_SYNC : 0;
}
/* Used to send write or TRIM aka REQ_DISCARD requests
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index df45713dfbe8..942384f34e22 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1564,7 +1564,7 @@ static void drbd_issue_peer_wsame(struct drbd_device *device,
* drbd_submit_peer_request()
* @device: DRBD device.
* @peer_req: peer request
- * @rw: flag field, see bio->bi_rw
+ * @rw: flag field, see bio->bi_opf
*
* May spread the pages to multiple bios,
* depending on bio_add_page restrictions.
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 66b8e4bb74d8..de279fe4e4fd 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -288,7 +288,7 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
*/
if (!ok &&
bio_op(req->master_bio) == REQ_OP_READ &&
- !(req->master_bio->bi_rw & REQ_RAHEAD) &&
+ !(req->master_bio->bi_opf & REQ_RAHEAD) &&
!list_empty(&req->tl_requests))
req->rq_state |= RQ_POSTPONED;
@@ -1137,7 +1137,7 @@ static int drbd_process_write_request(struct drbd_request *req)
* replicating, in which case there is no point. */
if (unlikely(req->i.size == 0)) {
/* The only size==0 bios we expect are empty flushes. */
- D_ASSERT(device, req->master_bio->bi_rw & REQ_PREFLUSH);
+ D_ASSERT(device, req->master_bio->bi_opf & REQ_PREFLUSH);
if (remote)
_req_mod(req, QUEUE_AS_DRBD_BARRIER);
return remote;
@@ -1176,7 +1176,7 @@ drbd_submit_req_private_bio(struct drbd_request *req)
if (bio_op(bio) != REQ_OP_READ)
type = DRBD_FAULT_DT_WR;
- else if (bio->bi_rw & REQ_RAHEAD)
+ else if (bio->bi_opf & REQ_RAHEAD)
type = DRBD_FAULT_DT_RA;
else
type = DRBD_FAULT_DT_RD;
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 35dbb3dca47e..c6755c9a0aea 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -256,7 +256,7 @@ void drbd_request_endio(struct bio *bio)
what = DISCARD_COMPLETED_WITH_ERROR;
break;
case REQ_OP_READ:
- if (bio->bi_rw & REQ_RAHEAD)
+ if (bio->bi_opf & REQ_RAHEAD)
what = READ_AHEAD_COMPLETED_WITH_ERROR;
else
what = READ_COMPLETED_WITH_ERROR;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index c557057fe8ae..b71a9c767009 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3663,11 +3663,6 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
opened_bdev[drive] = bdev;
- if (!(mode & (FMODE_READ|FMODE_WRITE))) {
- res = -EINVAL;
- goto out;
- }
-
res = -ENXIO;
if (!floppy_track_buffer) {
@@ -3711,13 +3706,15 @@ static int floppy_open(struct block_device *bdev, fmode_t mode)
if (UFDCS->rawcmd == 1)
UFDCS->rawcmd = 2;
- UDRS->last_checked = 0;
- clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
- check_disk_change(bdev);
- if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
- goto out;
- if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
- goto out;
+ if (mode & (FMODE_READ|FMODE_WRITE)) {
+ UDRS->last_checked = 0;
+ clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+ check_disk_change(bdev);
+ if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
+ goto out;
+ if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+ goto out;
+ }
res = -EROFS;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 075377eee0c0..c9f2107f7095 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -510,14 +510,10 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
return 0;
}
-
-static inline int lo_rw_simple(struct loop_device *lo,
- struct request *rq, loff_t pos, bool rw)
+static int do_req_filebacked(struct loop_device *lo, struct request *rq)
{
struct loop_cmd *cmd = blk_mq_rq_to_pdu(rq);
-
- if (cmd->use_aio)
- return lo_rw_aio(lo, cmd, pos, rw);
+ loff_t pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;
/*
* lo_write_simple and lo_read_simple should have been covered
@@ -528,37 +524,30 @@ static inline int lo_rw_simple(struct loop_device *lo,
* of the req at one time. And direct read IO doesn't need to
* run flush_dcache_page().
*/
- if (rw == WRITE)
- return lo_write_simple(lo, rq, pos);
- else
- return lo_read_simple(lo, rq, pos);
-}
-
-static int do_req_filebacked(struct loop_device *lo, struct request *rq)
-{
- loff_t pos;
- int ret;
-
- pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset;
-
- if (op_is_write(req_op(rq))) {
- if (req_op(rq) == REQ_OP_FLUSH)
- ret = lo_req_flush(lo, rq);
- else if (req_op(rq) == REQ_OP_DISCARD)
- ret = lo_discard(lo, rq, pos);
- else if (lo->transfer)
- ret = lo_write_transfer(lo, rq, pos);
+ switch (req_op(rq)) {
+ case REQ_OP_FLUSH:
+ return lo_req_flush(lo, rq);
+ case REQ_OP_DISCARD:
+ return lo_discard(lo, rq, pos);
+ case REQ_OP_WRITE:
+ if (lo->transfer)
+ return lo_write_transfer(lo, rq, pos);
+ else if (cmd->use_aio)
+ return lo_rw_aio(lo, cmd, pos, WRITE);
else
- ret = lo_rw_simple(lo, rq, pos, WRITE);
-
- } else {
+ return lo_write_simple(lo, rq, pos);
+ case REQ_OP_READ:
if (lo->transfer)
- ret = lo_read_transfer(lo, rq, pos);
+ return lo_read_transfer(lo, rq, pos);
+ else if (cmd->use_aio)
+ return lo_rw_aio(lo, cmd, pos, READ);
else
- ret = lo_rw_simple(lo, rq, pos, READ);
+ return lo_read_simple(lo, rq, pos);
+ default:
+ WARN_ON_ONCE(1);
+ return -EIO;
+ break;
}
-
- return ret;
}
struct switch_request {
@@ -1659,11 +1648,15 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
if (lo->lo_state != Lo_bound)
return -EIO;
- if (lo->use_dio && (req_op(cmd->rq) != REQ_OP_FLUSH ||
- req_op(cmd->rq) == REQ_OP_DISCARD))
- cmd->use_aio = true;
- else
+ switch (req_op(cmd->rq)) {
+ case REQ_OP_FLUSH:
+ case REQ_OP_DISCARD:
cmd->use_aio = false;
+ break;
+ default:
+ cmd->use_aio = lo->use_dio;
+ break;
+ }
queue_kthread_work(&lo->worker, &cmd->work);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 6f55b262b5ce..a9e398019f38 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -451,14 +451,9 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
sk_set_memalloc(nbd->sock->sk);
- nbd->task_recv = current;
-
ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
if (ret) {
dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
-
- nbd->task_recv = NULL;
-
return ret;
}
@@ -477,9 +472,6 @@ static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
nbd_size_clear(nbd, bdev);
device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
-
- nbd->task_recv = NULL;
-
return ret;
}
@@ -788,6 +780,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
if (!nbd->sock)
return -EINVAL;
+ /* We have to claim the device under the lock */
+ nbd->task_recv = current;
mutex_unlock(&nbd->tx_lock);
nbd_parse_flags(nbd, bdev);
@@ -796,6 +790,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
nbd_name(nbd));
if (IS_ERR(thread)) {
mutex_lock(&nbd->tx_lock);
+ nbd->task_recv = NULL;
return PTR_ERR(thread);
}
@@ -805,6 +800,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
kthread_stop(thread);
mutex_lock(&nbd->tx_lock);
+ nbd->task_recv = NULL;
sock_shutdown(nbd);
nbd_clear_que(nbd);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 9393bc730acf..90fa4ac149db 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1157,7 +1157,7 @@ static int pkt_start_recovery(struct packet_data *pkt)
bio_reset(pkt->bio);
pkt->bio->bi_bdev = pd->bdev;
- pkt->bio->bi_rw = REQ_WRITE;
+ bio_set_op_attrs(pkt->bio, REQ_OP_WRITE, 0);
pkt->bio->bi_iter.bi_sector = new_sector;
pkt->bio->bi_iter.bi_size = pkt->frames * CD_FRAMESIZE;
pkt->bio->bi_vcnt = pkt->frames;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 1a04af6d2421..6c6519f6492a 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -3950,6 +3950,7 @@ static void rbd_dev_release(struct device *dev)
bool need_put = !!rbd_dev->opts;
ceph_oid_destroy(&rbd_dev->header_oid);
+ ceph_oloc_destroy(&rbd_dev->header_oloc);
rbd_put_client(rbd_dev->rbd_client);
rbd_spec_put(rbd_dev->spec);
@@ -5336,15 +5337,6 @@ static ssize_t do_rbd_add(struct bus_type *bus,
}
spec->pool_id = (u64)rc;
- /* The ceph file layout needs to fit pool id in 32 bits */
-
- if (spec->pool_id > (u64)U32_MAX) {
- rbd_warn(NULL, "pool id too large (%llu > %u)",
- (unsigned long long)spec->pool_id, U32_MAX);
- rc = -EIO;
- goto err_out_client;
- }
-
rbd_dev = rbd_dev_create(rbdc, spec, rbd_opts);
if (!rbd_dev) {
rc = -ENOMEM;
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index d0a3e6d4515f..be90e15854ed 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -535,7 +535,7 @@ static blk_qc_t mm_make_request(struct request_queue *q, struct bio *bio)
*card->biotail = bio;
bio->bi_next = NULL;
card->biotail = &bio->bi_next;
- if (bio->bi_rw & REQ_SYNC || !mm_check_plugged(card))
+ if (bio->bi_opf & REQ_SYNC || !mm_check_plugged(card))
activate(card);
spin_unlock_irq(&card->lock);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 1523e05c46fc..93b1aaa5ba3b 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -391,22 +391,16 @@ static int init_vq(struct virtio_blk *vblk)
num_vqs = 1;
vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL);
- if (!vblk->vqs) {
- err = -ENOMEM;
- goto out;
- }
+ if (!vblk->vqs)
+ return -ENOMEM;
names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL);
- if (!names)
- goto err_names;
-
callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL);
- if (!callbacks)
- goto err_callbacks;
-
vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL);
- if (!vqs)
- goto err_vqs;
+ if (!names || !callbacks || !vqs) {
+ err = -ENOMEM;
+ goto out;
+ }
for (i = 0; i < num_vqs; i++) {
callbacks[i] = virtblk_done;
@@ -417,7 +411,7 @@ static int init_vq(struct virtio_blk *vblk)
/* Discover virtqueues and write information to configuration. */
err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names);
if (err)
- goto err_find_vqs;
+ goto out;
for (i = 0; i < num_vqs; i++) {
spin_lock_init(&vblk->vqs[i].lock);
@@ -425,16 +419,12 @@ static int init_vq(struct virtio_blk *vblk)
}
vblk->num_vqs = num_vqs;
- err_find_vqs:
+out:
kfree(vqs);
- err_vqs:
kfree(callbacks);
- err_callbacks:
kfree(names);
- err_names:
if (err)
kfree(vblk->vqs);
- out:
return err;
}
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 7454cf188c8e..04365b17ee67 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -843,15 +843,16 @@ static void zram_bio_discard(struct zram *zram, u32 index,
}
static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
- int offset, int rw)
+ int offset, bool is_write)
{
unsigned long start_time = jiffies;
+ int rw_acct = is_write ? REQ_OP_WRITE : REQ_OP_READ;
int ret;
- generic_start_io_acct(rw, bvec->bv_len >> SECTOR_SHIFT,
+ generic_start_io_acct(rw_acct, bvec->bv_len >> SECTOR_SHIFT,
&zram->disk->part0);
- if (rw == READ) {
+ if (!is_write) {
atomic64_inc(&zram->stats.num_reads);
ret = zram_bvec_read(zram, bvec, index, offset);
} else {
@@ -859,10 +860,10 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
ret = zram_bvec_write(zram, bvec, index, offset);
}
- generic_end_io_acct(rw, &zram->disk->part0, start_time);
+ generic_end_io_acct(rw_acct, &zram->disk->part0, start_time);
if (unlikely(ret)) {
- if (rw == READ)
+ if (!is_write)
atomic64_inc(&zram->stats.failed_reads);
else
atomic64_inc(&zram->stats.failed_writes);
@@ -873,7 +874,7 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
static void __zram_make_request(struct zram *zram, struct bio *bio)
{
- int offset, rw;
+ int offset;
u32 index;
struct bio_vec bvec;
struct bvec_iter iter;
@@ -888,7 +889,6 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
return;
}
- rw = bio_data_dir(bio);
bio_for_each_segment(bvec, bio, iter) {
int max_transfer_size = PAGE_SIZE - offset;
@@ -903,15 +903,18 @@ static void __zram_make_request(struct zram *zram, struct bio *bio)
bv.bv_len = max_transfer_size;
bv.bv_offset = bvec.bv_offset;
- if (zram_bvec_rw(zram, &bv, index, offset, rw) < 0)
+ if (zram_bvec_rw(zram, &bv, index, offset,
+ op_is_write(bio_op(bio))) < 0)
goto out;
bv.bv_len = bvec.bv_len - max_transfer_size;
bv.bv_offset += max_transfer_size;
- if (zram_bvec_rw(zram, &bv, index + 1, 0, rw) < 0)
+ if (zram_bvec_rw(zram, &bv, index + 1, 0,
+ op_is_write(bio_op(bio))) < 0)
goto out;
} else
- if (zram_bvec_rw(zram, &bvec, index, offset, rw) < 0)
+ if (zram_bvec_rw(zram, &bvec, index, offset,
+ op_is_write(bio_op(bio))) < 0)
goto out;
update_position(&index, &offset, &bvec);
@@ -968,7 +971,7 @@ static void zram_slot_free_notify(struct block_device *bdev,
}
static int zram_rw_page(struct block_device *bdev, sector_t sector,
- struct page *page, int rw)
+ struct page *page, bool is_write)
{
int offset, err = -EIO;
u32 index;
@@ -992,7 +995,7 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
bv.bv_len = PAGE_SIZE;
bv.bv_offset = 0;
- err = zram_bvec_rw(zram, &bv, index, offset, rw);
+ err = zram_bvec_rw(zram, &bv, index, offset, is_write);
put_zram:
zram_meta_put(zram);
out:
@@ -1005,7 +1008,7 @@ out:
* (e.g., SetPageError, set_page_dirty and extra works).
*/
if (err == 0)
- page_endio(page, rw, 0);
+ page_endio(page, is_write, 0);
return err;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index fdb8f3e10b6f..dcc09739a54e 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -293,7 +293,7 @@ if RTC_LIB=n
config RTC
tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)"
- depends on ALPHA || (MIPS && MACH_LOONGSON64) || MN10300
+ depends on ALPHA || (MIPS && MACH_LOONGSON64)
---help---
If you say Y here and create a character special file /dev/rtc with
major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -339,32 +339,6 @@ config JS_RTC
To compile this driver as a module, choose M here: the
module will be called js-rtc.
-config GEN_RTC
- tristate "Generic /dev/rtc emulation"
- depends on RTC!=y
- depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86
- ---help---
- If you say Y here and create a character special file /dev/rtc with
- major number 10 and minor number 135 using mknod ("man mknod"), you
- will get access to the real time clock (or hardware clock) built
- into your computer.
-
- It reports status information via the file /proc/driver/rtc and its
- behaviour is set by various ioctls on /dev/rtc. If you enable the
- "extended RTC operation" below it will also provide an emulation
- for RTC_UIE which is required by some programs and may improve
- precision in some cases.
-
- To compile this driver as a module, choose M here: the
- module will be called genrtc.
-
-config GEN_RTC_X
- bool "Extended RTC operation"
- depends on GEN_RTC
- help
- Provides an emulation for RTC_UIE which is required by some programs
- and may improve precision of the generic RTC support in some cases.
-
config EFI_RTC
bool "EFI Real Time Clock Services"
depends on IA64
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 55d16bf3ccc5..6e6c244a66a0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_APPLICOM) += applicom.o
obj-$(CONFIG_SONYPI) += sonypi.o
obj-$(CONFIG_RTC) += rtc.o
obj-$(CONFIG_HPET) += hpet.o
-obj-$(CONFIG_GEN_RTC) += genrtc.o
obj-$(CONFIG_EFI_RTC) += efirtc.o
obj-$(CONFIG_DS1302) += ds1302.o
obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
deleted file mode 100644
index 4f943759d376..000000000000
--- a/drivers/char/genrtc.c
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * Real Time Clock interface for
- * - q40 and other m68k machines,
- * - HP PARISC machines
- * - PowerPC machines
- * emulate some RTC irq capabilities in software
- *
- * Copyright (C) 1999 Richard Zidlicky
- *
- * based on Paul Gortmaker's rtc.c device and
- * Sam Creasey Generic rtc driver
- *
- * This driver allows use of the real time clock (built into
- * nearly all computers) from user space. It exports the /dev/rtc
- * interface supporting various ioctl() and also the /proc/driver/rtc
- * pseudo-file for status information.
- *
- * The ioctls can be used to set the interrupt behaviour where
- * supported.
- *
- * The /dev/rtc interface will block on reads until an interrupt
- * has been received. If a RTC interrupt has already happened,
- * it will output an unsigned long and then block. The output value
- * contains the interrupt status in the low byte and the number of
- * interrupts since the last read in the remaining high bytes. The
- * /dev/rtc interface can also be used with the select(2) call.
- *
- * 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.
- *
-
- * 1.01 fix for 2.3.X rz@linux-m68k.org
- * 1.02 merged with code from genrtc.c rz@linux-m68k.org
- * 1.03 make it more portable zippel@linux-m68k.org
- * 1.04 removed useless timer code rz@linux-m68k.org
- * 1.05 portable RTC_UIE emulation rz@linux-m68k.org
- * 1.06 set_rtc_time can return an error trini@kernel.crashing.org
- * 1.07 ported to HP PARISC (hppa) Helge Deller <deller@gmx.de>
- */
-
-#define RTC_VERSION "1.07"
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-
-#include <linux/rtc.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/rtc.h>
-
-/*
- * We sponge a minor off of the misc major. No need slurping
- * up another valuable major dev number for this. If you add
- * an ioctl, make sure you don't conflict with SPARC's RTC
- * ioctls.
- */
-
-static DEFINE_MUTEX(gen_rtc_mutex);
-static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
-
-/*
- * Bits in gen_rtc_status.
- */
-
-#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
-
-static unsigned char gen_rtc_status; /* bitmapped status byte. */
-static unsigned long gen_rtc_irq_data; /* our output to the world */
-
-/* months start at 0 now */
-static unsigned char days_in_mo[] =
-{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static int irq_active;
-
-#ifdef CONFIG_GEN_RTC_X
-static struct work_struct genrtc_task;
-static struct timer_list timer_task;
-
-static unsigned int oldsecs;
-static int lostint;
-static unsigned long tt_exp;
-
-static void gen_rtc_timer(unsigned long data);
-
-static volatile int stask_active; /* schedule_work */
-static volatile int ttask_active; /* timer_task */
-static int stop_rtc_timers; /* don't requeue tasks */
-static DEFINE_SPINLOCK(gen_rtc_lock);
-
-static void gen_rtc_interrupt(unsigned long arg);
-
-/*
- * Routine to poll RTC seconds field for change as often as possible,
- * after first RTC_UIE use timer to reduce polling
- */
-static void genrtc_troutine(struct work_struct *work)
-{
- unsigned int tmp = get_rtc_ss();
-
- if (stop_rtc_timers) {
- stask_active = 0;
- return;
- }
-
- if (oldsecs != tmp){
- oldsecs = tmp;
-
- timer_task.function = gen_rtc_timer;
- timer_task.expires = jiffies + HZ - (HZ/10);
- tt_exp=timer_task.expires;
- ttask_active=1;
- stask_active=0;
- add_timer(&timer_task);
-
- gen_rtc_interrupt(0);
- } else if (schedule_work(&genrtc_task) == 0)
- stask_active = 0;
-}
-
-static void gen_rtc_timer(unsigned long data)
-{
- lostint = get_rtc_ss() - oldsecs ;
- if (lostint<0)
- lostint = 60 - lostint;
- if (time_after(jiffies, tt_exp))
- printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n",
- jiffies-tt_exp);
- ttask_active=0;
- stask_active=1;
- if ((schedule_work(&genrtc_task) == 0))
- stask_active = 0;
-}
-
-/*
- * call gen_rtc_interrupt function to signal an RTC_UIE,
- * arg is unused.
- * Could be invoked either from a real interrupt handler or
- * from some routine that periodically (eg 100HZ) monitors
- * whether RTC_SECS changed
- */
-static void gen_rtc_interrupt(unsigned long arg)
-{
- /* We store the status in the low byte and the number of
- * interrupts received since the last read in the remainder
- * of rtc_irq_data. */
-
- gen_rtc_irq_data += 0x100;
- gen_rtc_irq_data &= ~0xff;
- gen_rtc_irq_data |= RTC_UIE;
-
- if (lostint){
- printk("genrtc: system delaying clock ticks?\n");
- /* increment count so that userspace knows something is wrong */
- gen_rtc_irq_data += ((lostint-1)<<8);
- lostint = 0;
- }
-
- wake_up_interruptible(&gen_rtc_wait);
-}
-
-/*
- * Now all the various file operations that we export.
- */
-static ssize_t gen_rtc_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long data;
- ssize_t retval;
-
- if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
- return -EINVAL;
-
- if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
- return -EAGAIN;
-
- retval = wait_event_interruptible(gen_rtc_wait,
- (data = xchg(&gen_rtc_irq_data, 0)));
- if (retval)
- goto out;
-
- /* first test allows optimizer to nuke this case for 32-bit machines */
- if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
- unsigned int uidata = data;
- retval = put_user(uidata, (unsigned int __user *)buf) ?:
- sizeof(unsigned int);
- }
- else {
- retval = put_user(data, (unsigned long __user *)buf) ?:
- sizeof(unsigned long);
- }
-out:
- return retval;
-}
-
-static unsigned int gen_rtc_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- poll_wait(file, &gen_rtc_wait, wait);
- if (gen_rtc_irq_data != 0)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-#endif
-
-/*
- * Used to disable/enable interrupts, only RTC_UIE supported
- * We also clear out any old irq data after an ioctl() that
- * meddles with the interrupt enable/disable bits.
- */
-
-static inline void gen_clear_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
- stop_rtc_timers = 1;
- if (ttask_active){
- del_timer_sync(&timer_task);
- ttask_active = 0;
- }
- while (stask_active)
- schedule();
-
- spin_lock(&gen_rtc_lock);
- irq_active = 0;
- spin_unlock(&gen_rtc_lock);
-#endif
-}
-
-static inline int gen_set_rtc_irq_bit(unsigned char bit)
-{
-#ifdef CONFIG_GEN_RTC_X
- spin_lock(&gen_rtc_lock);
- if ( !irq_active ) {
- irq_active = 1;
- stop_rtc_timers = 0;
- lostint = 0;
- INIT_WORK(&genrtc_task, genrtc_troutine);
- oldsecs = get_rtc_ss();
- init_timer(&timer_task);
-
- stask_active = 1;
- if (schedule_work(&genrtc_task) == 0){
- stask_active = 0;
- }
- }
- spin_unlock(&gen_rtc_lock);
- gen_rtc_irq_data = 0;
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static int gen_rtc_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct rtc_time wtime;
- struct rtc_pll_info pll;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
-
- case RTC_PLL_GET:
- if (get_rtc_pll(&pll))
- return -EINVAL;
- else
- return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
-
- case RTC_PLL_SET:
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
- if (copy_from_user(&pll, argp, sizeof(pll)))
- return -EFAULT;
- return set_rtc_pll(&pll);
-
- case RTC_UIE_OFF: /* disable ints from RTC updates. */
- gen_clear_rtc_irq_bit(RTC_UIE);
- return 0;
-
- case RTC_UIE_ON: /* enable ints for RTC updates. */
- return gen_set_rtc_irq_bit(RTC_UIE);
-
- case RTC_RD_TIME: /* Read the time/date from RTC */
- /* this doesn't get week-day, who cares */
- memset(&wtime, 0, sizeof(wtime));
- get_rtc_time(&wtime);
-
- return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
-
- case RTC_SET_TIME: /* Set the RTC */
- {
- int year;
- unsigned char leap_yr;
-
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
- if (copy_from_user(&wtime, argp, sizeof(wtime)))
- return -EFAULT;
-
- year = wtime.tm_year + 1900;
- leap_yr = ((!(year % 4) && (year % 100)) ||
- !(year % 400));
-
- if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
- return -EINVAL;
-
- if (wtime.tm_mday < 0 || wtime.tm_mday >
- (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
- return -EINVAL;
-
- if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
- wtime.tm_min < 0 || wtime.tm_min >= 60 ||
- wtime.tm_sec < 0 || wtime.tm_sec >= 60)
- return -EINVAL;
-
- return set_rtc_time(&wtime);
- }
- }
-
- return -EINVAL;
-}
-
-static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- int ret;
-
- mutex_lock(&gen_rtc_mutex);
- ret = gen_rtc_ioctl(file, cmd, arg);
- mutex_unlock(&gen_rtc_mutex);
-
- return ret;
-}
-
-/*
- * We enforce only one user at a time here with the open/close.
- * Also clear the previous interrupt data on an open, and clean
- * up things on a close.
- */
-
-static int gen_rtc_open(struct inode *inode, struct file *file)
-{
- mutex_lock(&gen_rtc_mutex);
- if (gen_rtc_status & RTC_IS_OPEN) {
- mutex_unlock(&gen_rtc_mutex);
- return -EBUSY;
- }
-
- gen_rtc_status |= RTC_IS_OPEN;
- gen_rtc_irq_data = 0;
- irq_active = 0;
- mutex_unlock(&gen_rtc_mutex);
-
- return 0;
-}
-
-static int gen_rtc_release(struct inode *inode, struct file *file)
-{
- /*
- * Turn off all interrupts once the device is no longer
- * in use and clear the data.
- */
-
- gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
-
- gen_rtc_status &= ~RTC_IS_OPEN;
- return 0;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Info exported via "/proc/driver/rtc".
- */
-
-static int gen_rtc_proc_show(struct seq_file *m, void *v)
-{
- struct rtc_time tm;
- unsigned int flags;
- struct rtc_pll_info pll;
-
- flags = get_rtc_time(&tm);
-
- seq_printf(m,
- "rtc_time\t: %02d:%02d:%02d\n"
- "rtc_date\t: %04d-%02d-%02d\n"
- "rtc_epoch\t: %04u\n",
- tm.tm_hour, tm.tm_min, tm.tm_sec,
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900);
-
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-
- seq_puts(m, "alarm\t\t: ");
- if (tm.tm_hour <= 24)
- seq_printf(m, "%02d:", tm.tm_hour);
- else
- seq_puts(m, "**:");
-
- if (tm.tm_min <= 59)
- seq_printf(m, "%02d:", tm.tm_min);
- else
- seq_puts(m, "**:");
-
- if (tm.tm_sec <= 59)
- seq_printf(m, "%02d\n", tm.tm_sec);
- else
- seq_puts(m, "**\n");
-
- seq_printf(m,
- "DST_enable\t: %s\n"
- "BCD\t\t: %s\n"
- "24hr\t\t: %s\n"
- "square_wave\t: %s\n"
- "alarm_IRQ\t: %s\n"
- "update_IRQ\t: %s\n"
- "periodic_IRQ\t: %s\n"
- "periodic_freq\t: %ld\n"
- "batt_status\t: %s\n",
- (flags & RTC_DST_EN) ? "yes" : "no",
- (flags & RTC_DM_BINARY) ? "no" : "yes",
- (flags & RTC_24H) ? "yes" : "no",
- (flags & RTC_SQWE) ? "yes" : "no",
- (flags & RTC_AIE) ? "yes" : "no",
- irq_active ? "yes" : "no",
- (flags & RTC_PIE) ? "yes" : "no",
- 0L /* freq */,
- (flags & RTC_BATT_BAD) ? "bad" : "okay");
- if (!get_rtc_pll(&pll))
- seq_printf(m,
- "PLL adjustment\t: %d\n"
- "PLL max +ve adjustment\t: %d\n"
- "PLL max -ve adjustment\t: %d\n"
- "PLL +ve adjustment factor\t: %d\n"
- "PLL -ve adjustment factor\t: %d\n"
- "PLL frequency\t: %ld\n",
- pll.pll_value,
- pll.pll_max,
- pll.pll_min,
- pll.pll_posmult,
- pll.pll_negmult,
- pll.pll_clock);
- return 0;
-}
-
-static int gen_rtc_proc_open(struct inode *inode, struct file *file)
-{
- return single_open(file, gen_rtc_proc_show, NULL);
-}
-
-static const struct file_operations gen_rtc_proc_fops = {
- .open = gen_rtc_proc_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init gen_rtc_proc_init(void)
-{
- struct proc_dir_entry *r;
-
- r = proc_create("driver/rtc", 0, NULL, &gen_rtc_proc_fops);
- if (!r)
- return -ENOMEM;
- return 0;
-}
-#else
-static inline int gen_rtc_proc_init(void) { return 0; }
-#endif /* CONFIG_PROC_FS */
-
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations gen_rtc_fops = {
- .owner = THIS_MODULE,
-#ifdef CONFIG_GEN_RTC_X
- .read = gen_rtc_read,
- .poll = gen_rtc_poll,
-#endif
- .unlocked_ioctl = gen_rtc_unlocked_ioctl,
- .open = gen_rtc_open,
- .release = gen_rtc_release,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice rtc_gen_dev =
-{
- .minor = RTC_MINOR,
- .name = "rtc",
- .fops = &gen_rtc_fops,
-};
-
-static int __init rtc_generic_init(void)
-{
- int retval;
-
- printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
-
- retval = misc_register(&rtc_gen_dev);
- if (retval < 0)
- return retval;
-
- retval = gen_rtc_proc_init();
- if (retval) {
- misc_deregister(&rtc_gen_dev);
- return retval;
- }
-
- return 0;
-}
-
-static void __exit rtc_generic_exit(void)
-{
- remove_proc_entry ("driver/rtc", NULL);
- misc_deregister(&rtc_gen_dev);
-}
-
-
-module_init(rtc_generic_init);
-module_exit(rtc_generic_exit);
-
-MODULE_AUTHOR("Richard Zidlicky");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(RTC_MINOR);
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 28bce3f4f81d..57700541f951 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -8,6 +8,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+#define pr_fmt(fmt) "arm_arch_timer: " fmt
+
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
@@ -370,16 +373,33 @@ static bool arch_timer_has_nonsecure_ppi(void)
arch_timer_ppi[PHYS_NONSECURE_PPI]);
}
+static u32 check_ppi_trigger(int irq)
+{
+ u32 flags = irq_get_trigger_type(irq);
+
+ if (flags != IRQF_TRIGGER_HIGH && flags != IRQF_TRIGGER_LOW) {
+ pr_warn("WARNING: Invalid trigger for IRQ%d, assuming level low\n", irq);
+ pr_warn("WARNING: Please fix your firmware\n");
+ flags = IRQF_TRIGGER_LOW;
+ }
+
+ return flags;
+}
+
static int arch_timer_starting_cpu(unsigned int cpu)
{
struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
+ u32 flags;
__arch_timer_setup(ARCH_CP15_TIMER, clk);
- enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0);
+ flags = check_ppi_trigger(arch_timer_ppi[arch_timer_uses_ppi]);
+ enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], flags);
- if (arch_timer_has_nonsecure_ppi())
- enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
+ if (arch_timer_has_nonsecure_ppi()) {
+ flags = check_ppi_trigger(arch_timer_ppi[PHYS_NONSECURE_PPI]);
+ enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], flags);
+ }
arch_counter_set_user_access();
if (evtstrm_enable)
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index c822d72629d5..74919aa81dcb 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -32,7 +32,6 @@ config CPU_FREQ_BOOST_SW
config CPU_FREQ_STAT
bool "CPU frequency transition statistics"
- default y
help
Export CPU frequency statistics information through sysfs.
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 9ec033b4f2d9..be9eade147f2 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1374,6 +1374,8 @@ MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
static const struct x86_cpu_id intel_pstate_cpu_oob_ids[] __initconst = {
ICPU(INTEL_FAM6_BROADWELL_XEON_D, core_params),
+ ICPU(INTEL_FAM6_BROADWELL_X, core_params),
+ ICPU(INTEL_FAM6_SKYLAKE_X, core_params),
{}
};
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 87796e0864e9..d3ffde806629 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -145,11 +145,30 @@ static struct powernv_pstate_info {
/* Use following macros for conversions between pstate_id and index */
static inline int idx_to_pstate(unsigned int i)
{
+ if (unlikely(i >= powernv_pstate_info.nr_pstates)) {
+ pr_warn_once("index %u is out of bound\n", i);
+ return powernv_freqs[powernv_pstate_info.nominal].driver_data;
+ }
+
return powernv_freqs[i].driver_data;
}
static inline unsigned int pstate_to_idx(int pstate)
{
+ int min = powernv_freqs[powernv_pstate_info.min].driver_data;
+ int max = powernv_freqs[powernv_pstate_info.max].driver_data;
+
+ if (min > 0) {
+ if (unlikely((pstate < max) || (pstate > min))) {
+ pr_warn_once("pstate %d is out of bound\n", pstate);
+ return powernv_pstate_info.nominal;
+ }
+ } else {
+ if (unlikely((pstate > max) || (pstate < min))) {
+ pr_warn_once("pstate %d is out of bound\n", pstate);
+ return powernv_pstate_info.nominal;
+ }
+ }
/*
* abs() is deliberately used so that is works with
* both monotonically increasing and decreasing
@@ -593,7 +612,7 @@ void gpstate_timer_handler(unsigned long data)
} else {
gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
gpstates->highest_lpstate_idx,
- freq_data.pstate_id);
+ gpstates->last_lpstate_idx);
}
/*
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index ea8189f4b021..6dc597126b79 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -441,6 +441,9 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
OP_ALG_AAI_CTR_MOD128);
const bool is_rfc3686 = alg->caam.rfc3686;
+ if (!ctx->authsize)
+ return 0;
+
/* NULL encryption / decryption */
if (!ctx->enckeylen)
return aead_null_set_sh_desc(aead);
@@ -614,7 +617,7 @@ skip_enc:
keys_fit_inline = true;
/* aead_givencrypt shared descriptor */
- desc = ctx->sh_desc_givenc;
+ desc = ctx->sh_desc_enc;
/* Note: Context registers are saved. */
init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
@@ -645,13 +648,13 @@ copy_iv:
append_operation(desc, ctx->class2_alg_type |
OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
- /* ivsize + cryptlen = seqoutlen - authsize */
- append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
/* Read and write assoclen bytes */
append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+ /* ivsize + cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
/* Skip assoc data */
append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
@@ -697,7 +700,7 @@ copy_iv:
ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
desc_bytes(desc),
DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, ctx->sh_desc_givenc_dma)) {
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
dev_err(jrdev, "unable to map shared descriptor\n");
return -ENOMEM;
}
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index f1ecc8df8d41..36365b3efdfd 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -1898,6 +1898,7 @@ caam_hash_alloc(struct caam_hash_template *template,
template->name);
snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
template->driver_name);
+ t_alg->ahash_alg.setkey = NULL;
}
alg->cra_module = THIS_MODULE;
alg->cra_init = caam_hash_cra_init;
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 4fb2eb7c800d..ce0067b7a2f6 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -552,9 +552,9 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
/* Knight's Landing Support */
/*
* KNL's memory channels are swizzled between memory controllers.
- * MC0 is mapped to CH3,5,6 and MC1 is mapped to CH0,1,2
+ * MC0 is mapped to CH3,4,5 and MC1 is mapped to CH0,1,2
*/
-#define knl_channel_remap(channel) ((channel + 3) % 6)
+#define knl_channel_remap(mc, chan) ((mc) ? (chan) : (chan) + 3)
/* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */
#define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840
@@ -1286,7 +1286,7 @@ static u32 knl_get_mc_route(int entry, u32 reg)
mc = GET_BITFIELD(reg, entry*3, (entry*3)+2);
chan = GET_BITFIELD(reg, (entry*2) + 18, (entry*2) + 18 + 1);
- return knl_channel_remap(mc*3 + chan);
+ return knl_channel_remap(mc, chan);
}
/*
@@ -2997,8 +2997,15 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
} else {
char A = *("A");
- channel = knl_channel_remap(channel);
+ /*
+ * Reported channel is in range 0-2, so we can't map it
+ * back to mc. To figure out mc we check machine check
+ * bank register that reported this error.
+ * bank15 means mc0 and bank16 means mc1.
+ */
+ channel = knl_channel_remap(m->bank == 16, channel);
channel_mask = 1 << channel;
+
snprintf(msg, sizeof(msg),
"%s%s err_code:%04x:%04x channel:%d (DIMM_%c)",
overflow ? " OVERFLOW" : "",
diff --git a/drivers/firmware/broadcom/bcm47xx_sprom.c b/drivers/firmware/broadcom/bcm47xx_sprom.c
index b6eb875d4af3..62aa3cf09b4d 100644
--- a/drivers/firmware/broadcom/bcm47xx_sprom.c
+++ b/drivers/firmware/broadcom/bcm47xx_sprom.c
@@ -669,7 +669,7 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
case BCMA_HOSTTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
/* On BCM47XX all PCI buses share the same domain */
- if (config_enabled(CONFIG_BCM47XX))
+ if (IS_ENABLED(CONFIG_BCM47XX))
snprintf(buf, sizeof(buf), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c
index c99c24bc79b0..9ae6c116c474 100644
--- a/drivers/firmware/efi/capsule-loader.c
+++ b/drivers/firmware/efi/capsule-loader.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/efi.h>
+#include <linux/vmalloc.h>
#define NO_FURTHER_WRITE_ACTION -1
@@ -108,14 +109,15 @@ static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)
int ret;
void *cap_hdr_temp;
- cap_hdr_temp = kmap(cap_info->pages[0]);
+ cap_hdr_temp = vmap(cap_info->pages, cap_info->index,
+ VM_MAP, PAGE_KERNEL);
if (!cap_hdr_temp) {
- pr_debug("%s: kmap() failed\n", __func__);
+ pr_debug("%s: vmap() failed\n", __func__);
return -EFAULT;
}
ret = efi_capsule_update(cap_hdr_temp, cap_info->pages);
- kunmap(cap_info->pages[0]);
+ vunmap(cap_hdr_temp);
if (ret) {
pr_err("%s: efi_capsule_update() failed\n", __func__);
return ret;
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index 53b9fd2293ee..6eedff45e6d7 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -190,9 +190,9 @@ efi_capsule_update_locked(efi_capsule_header_t *capsule,
* map the capsule described by @capsule with its data in @pages and
* send it to the firmware via the UpdateCapsule() runtime service.
*
- * @capsule must be a virtual mapping of the first page in @pages
- * (@pages[0]) in the kernel address space. That is, a
- * capsule_header_t that describes the entire contents of the capsule
+ * @capsule must be a virtual mapping of the complete capsule update in the
+ * kernel address space, as the capsule can be consumed immediately.
+ * A capsule_header_t that describes the entire contents of the capsule
* must be at the start of the first data page.
*
* Even though this function will validate that the firmware supports
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index c9b9fdf6cfbb..d61410299ec0 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -21,6 +21,7 @@ config FPGA_MGR_SOCFPGA
config FPGA_MGR_ZYNQ_FPGA
tristate "Xilinx Zynq FPGA"
+ depends on HAS_DMA
help
FPGA manager driver support for Xilinx Zynq FPGAs.
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e3dba6f44a79..0238bf8bc8c3 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -24,7 +24,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
- drm_simple_kms_helper.o
+ drm_simple_kms_helper.o drm_blend.o
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index ff63b88b0ffa..5cc7052e391d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -305,7 +305,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;
char *table = NULL;
- int size, i;
+ int size;
if (adev->pp_enabled)
size = amdgpu_dpm_get_pp_table(adev, &table);
@@ -315,10 +315,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev,
if (size >= PAGE_SIZE)
size = PAGE_SIZE - 1;
- for (i = 0; i < size; i++) {
- sprintf(buf + i, "%02x", table[i]);
- }
- sprintf(buf + i, "\n");
+ memcpy(buf, table, size);
return size;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index b7742e62972a..9b61c8ba7aaf 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -335,7 +335,7 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
goto out_cleanup;
}
- r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+ r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
out_cleanup:
ttm_bo_mem_put(bo, &tmp_mem);
return r;
@@ -368,7 +368,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
return r;
}
- r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+ r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
if (unlikely(r)) {
goto out_cleanup;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index e2f0e5d58d5c..a5c94b482459 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -5779,6 +5779,7 @@ static int ci_dpm_init_microcode(struct amdgpu_device *adev)
break;
case CHIP_KAVERI:
case CHIP_KABINI:
+ case CHIP_MULLINS:
default: BUG();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index bff8668e9e6d..b8184617ca25 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -270,7 +270,8 @@ static const u32 tonga_mgcg_cgcg_init[] =
static const u32 golden_settings_polaris11_a11[] =
{
- mmCB_HW_CONTROL, 0xfffdf3cf, 0x00006208,
+ mmCB_HW_CONTROL, 0x0000f3cf, 0x00007208,
+ mmCB_HW_CONTROL_2, 0x0f000000, 0x0f000000,
mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
@@ -279,7 +280,7 @@ static const u32 golden_settings_polaris11_a11[] =
mmPA_SC_RASTER_CONFIG_1, 0x0000003f, 0x00000000,
mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0001003c,
mmRLC_CGCG_CGLS_CTRL_3D, 0xffffffff, 0x0001003c,
- mmSQ_CONFIG, 0x07f80000, 0x07180000,
+ mmSQ_CONFIG, 0x07f80000, 0x01180000,
mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
mmTCC_CTRL, 0x00100000, 0xf31fff7f,
mmTCP_ADDR_CONFIG, 0x000003ff, 0x000000f3,
@@ -301,8 +302,8 @@ static const u32 polaris11_golden_common_all[] =
static const u32 golden_settings_polaris10_a11[] =
{
mmATC_MISC_CG, 0x000c0fc0, 0x000c0200,
- mmCB_HW_CONTROL, 0xfffdf3cf, 0x00007208,
- mmCB_HW_CONTROL_2, 0, 0x0f000000,
+ mmCB_HW_CONTROL, 0x0001f3cf, 0x00007208,
+ mmCB_HW_CONTROL_2, 0x0f000000, 0x0f000000,
mmCB_HW_CONTROL_3, 0x000001ff, 0x00000040,
mmDB_DEBUG2, 0xf00fffff, 0x00000400,
mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
@@ -409,6 +410,7 @@ static const u32 golden_settings_iceland_a11[] =
mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
mmPA_SC_RASTER_CONFIG, 0x3f3fffff, 0x00000002,
mmPA_SC_RASTER_CONFIG_1, 0x0000003f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0000003c,
mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
mmTCC_CTRL, 0x00100000, 0xf31fff7f,
@@ -505,8 +507,10 @@ static const u32 cz_golden_settings_a11[] =
mmGB_GPU_ID, 0x0000000f, 0x00000000,
mmPA_SC_ENHANCE, 0xffffffff, 0x00000001,
mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+ mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0000003c,
mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
mmTA_CNTL_AUX, 0x000f000f, 0x00010000,
+ mmTCC_CTRL, 0x00100000, 0xf31fff7f,
mmTCC_EXE_DISABLE, 0x00000002, 0x00000002,
mmTCP_ADDR_CONFIG, 0x0000000f, 0x000000f3,
mmTCP_CHAN_STEER_LO, 0xffffffff, 0x00001302
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index d24a82bd0c7a..0b0f08641eed 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -144,6 +144,7 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
break;
case CHIP_KAVERI:
case CHIP_KABINI:
+ case CHIP_MULLINS:
return 0;
default: BUG();
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
index 717359d3ba8c..2aee2c6f3cd5 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -103,6 +103,11 @@ static const u32 stoney_mgcg_cgcg_init[] =
mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104
};
+static const u32 golden_settings_stoney_common[] =
+{
+ mmMC_HUB_RDREQ_UVD, MC_HUB_RDREQ_UVD__PRESCALE_MASK, 0x00000004,
+ mmMC_RD_GRP_OTH, MC_RD_GRP_OTH__UVD_MASK, 0x00600000
+};
static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
{
@@ -142,6 +147,9 @@ static void gmc_v8_0_init_golden_registers(struct amdgpu_device *adev)
amdgpu_program_register_sequence(adev,
stoney_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(stoney_mgcg_cgcg_init));
+ amdgpu_program_register_sequence(adev,
+ golden_settings_stoney_common,
+ (const u32)ARRAY_SIZE(golden_settings_stoney_common));
break;
default:
break;
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index 80446e2d3ab6..76bcb43e7c06 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -185,14 +185,23 @@ int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
goto out;
}
+ /*
+ * cirrus_modeset_init() is initializing/registering the emulated fbdev
+ * and DRM internals can access/test some of the fields in
+ * mode_config->funcs as part of the fbdev registration process.
+ * Make sure dev->mode_config.funcs is properly set to avoid
+ * dereferencing a NULL pointer.
+ * FIXME: mode_config.funcs assignment should probably be done in
+ * cirrus_modeset_init() (that's a common pattern seen in other DRM
+ * drivers).
+ */
+ dev->mode_config.funcs = &cirrus_mode_funcs;
r = cirrus_modeset_init(cdev);
if (r) {
dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
goto out;
}
- dev->mode_config.funcs = (void *)&cirrus_mode_funcs;
-
return 0;
out:
cirrus_driver_unload(dev);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 8d2f111fa113..fa3930757972 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -711,6 +711,8 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
state->src_h = val;
} else if (property == config->rotation_property) {
state->rotation = val;
+ } else if (property == plane->zpos_property) {
+ state->zpos = val;
} else if (plane->funcs->atomic_set_property) {
return plane->funcs->atomic_set_property(plane, state,
property, val);
@@ -767,6 +769,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
*val = state->src_h;
} else if (property == config->rotation_property) {
*val = state->rotation;
+ } else if (property == plane->zpos_property) {
+ *val = state->zpos;
} else if (plane->funcs->atomic_get_property) {
return plane->funcs->atomic_get_property(plane, state, property, val);
} else {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index de7fddce3cef..20be86d89a20 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -32,6 +32,8 @@
#include <drm/drm_atomic_helper.h>
#include <linux/fence.h>
+#include "drm_crtc_internal.h"
+
/**
* DOC: overview
*
@@ -592,6 +594,10 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
struct drm_plane_state *plane_state;
int i, ret = 0;
+ ret = drm_atomic_helper_normalize_zpos(dev, state);
+ if (ret)
+ return ret;
+
for_each_plane_in_state(state, plane, plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
@@ -2955,6 +2961,7 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
state->planes_changed = false;
state->connectors_changed = false;
state->color_mgmt_changed = false;
+ state->zpos_changed = false;
state->event = NULL;
}
EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
new file mode 100644
index 000000000000..f3c0942bd756
--- /dev/null
+++ b/drivers/gpu/drm/drm_blend.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2016 Samsung Electronics Co.Ltd
+ * Authors:
+ * Marek Szyprowski <m.szyprowski@samsung.com>
+ *
+ * DRM core plane blending related functions
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_crtc.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+
+#include "drm_internal.h"
+
+/**
+ * drm_plane_create_zpos_property - create mutable zpos property
+ * @plane: drm plane
+ * @zpos: initial value of zpos property
+ * @min: minimal possible value of zpos property
+ * @max: maximal possible value of zpos property
+ *
+ * This function initializes generic mutable zpos property and enables support
+ * for it in drm core. Drivers can then attach this property to planes to enable
+ * support for configurable planes arrangement during blending operation.
+ * Once mutable zpos property has been enabled, the DRM core will automatically
+ * calculate drm_plane_state->normalized_zpos values. Usually min should be set
+ * to 0 and max to maximal number of planes for given crtc - 1.
+ *
+ * If zpos of some planes cannot be changed (like fixed background or
+ * cursor/topmost planes), driver should adjust min/max values and assign those
+ * planes immutable zpos property with lower or higher values (for more
+ * information, see drm_mode_create_zpos_immutable_property() function). In such
+ * case driver should also assign proper initial zpos values for all planes in
+ * its plane_reset() callback, so the planes will be always sorted properly.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_plane_create_zpos_property(struct drm_plane *plane,
+ unsigned int zpos,
+ unsigned int min, unsigned int max)
+{
+ struct drm_property *prop;
+
+ prop = drm_property_create_range(plane->dev, 0, "zpos", min, max);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&plane->base, prop, zpos);
+
+ plane->zpos_property = prop;
+
+ if (plane->state) {
+ plane->state->zpos = zpos;
+ plane->state->normalized_zpos = zpos;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_zpos_property);
+
+/**
+ * drm_plane_create_zpos_immutable_property - create immuttable zpos property
+ * @plane: drm plane
+ * @zpos: value of zpos property
+ *
+ * This function initializes generic immutable zpos property and enables
+ * support for it in drm core. Using this property driver lets userspace
+ * to get the arrangement of the planes for blending operation and notifies
+ * it that the hardware (or driver) doesn't support changing of the planes'
+ * order.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
+ unsigned int zpos)
+{
+ struct drm_property *prop;
+
+ prop = drm_property_create_range(plane->dev, DRM_MODE_PROP_IMMUTABLE,
+ "zpos", zpos, zpos);
+ if (!prop)
+ return -ENOMEM;
+
+ drm_object_attach_property(&plane->base, prop, zpos);
+
+ plane->zpos_property = prop;
+
+ if (plane->state) {
+ plane->state->zpos = zpos;
+ plane->state->normalized_zpos = zpos;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_zpos_immutable_property);
+
+static int drm_atomic_state_zpos_cmp(const void *a, const void *b)
+{
+ const struct drm_plane_state *sa = *(struct drm_plane_state **)a;
+ const struct drm_plane_state *sb = *(struct drm_plane_state **)b;
+
+ if (sa->zpos != sb->zpos)
+ return sa->zpos - sb->zpos;
+ else
+ return sa->plane->base.id - sb->plane->base.id;
+}
+
+/**
+ * drm_atomic_helper_crtc_normalize_zpos - calculate normalized zpos values
+ * @crtc: crtc with planes, which have to be considered for normalization
+ * @crtc_state: new atomic state to apply
+ *
+ * This function checks new states of all planes assigned to given crtc and
+ * calculates normalized zpos value for them. Planes are compared first by their
+ * zpos values, then by plane id (if zpos equals). Plane with lowest zpos value
+ * is at the bottom. The plane_state->normalized_zpos is then filled with unique
+ * values from 0 to number of active planes in crtc minus one.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ struct drm_atomic_state *state = crtc_state->state;
+ struct drm_device *dev = crtc->dev;
+ int total_planes = dev->mode_config.num_total_plane;
+ struct drm_plane_state **states;
+ struct drm_plane *plane;
+ int i, n = 0;
+ int ret = 0;
+
+ DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
+ crtc->base.id, crtc->name);
+
+ states = kmalloc_array(total_planes, sizeof(*states), GFP_TEMPORARY);
+ if (!states)
+ return -ENOMEM;
+
+ /*
+ * Normalization process might create new states for planes which
+ * normalized_zpos has to be recalculated.
+ */
+ drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
+ struct drm_plane_state *plane_state =
+ drm_atomic_get_plane_state(state, plane);
+ if (IS_ERR(plane_state)) {
+ ret = PTR_ERR(plane_state);
+ goto done;
+ }
+ states[n++] = plane_state;
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] processing zpos value %d\n",
+ plane->base.id, plane->name,
+ plane_state->zpos);
+ }
+
+ sort(states, n, sizeof(*states), drm_atomic_state_zpos_cmp, NULL);
+
+ for (i = 0; i < n; i++) {
+ plane = states[i]->plane;
+
+ states[i]->normalized_zpos = i;
+ DRM_DEBUG_ATOMIC("[PLANE:%d:%s] normalized zpos value %d\n",
+ plane->base.id, plane->name, i);
+ }
+ crtc_state->zpos_changed = true;
+
+done:
+ kfree(states);
+ return ret;
+}
+
+/**
+ * drm_atomic_helper_normalize_zpos - calculate normalized zpos values for all
+ * crtcs
+ * @dev: DRM device
+ * @state: atomic state of DRM device
+ *
+ * This function calculates normalized zpos value for all modified planes in
+ * the provided atomic state of DRM device. For more information, see
+ * drm_atomic_helper_crtc_normalize_zpos() function.
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
+ struct drm_atomic_state *state)
+{
+ struct drm_crtc *crtc;
+ struct drm_crtc_state *crtc_state;
+ struct drm_plane *plane;
+ struct drm_plane_state *plane_state;
+ int i, ret = 0;
+
+ for_each_plane_in_state(state, plane, plane_state, i) {
+ crtc = plane_state->crtc;
+ if (!crtc)
+ continue;
+ if (plane->state->zpos != plane_state->zpos) {
+ crtc_state =
+ drm_atomic_get_existing_crtc_state(state, crtc);
+ crtc_state->zpos_changed = true;
+ }
+ }
+
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ if (crtc_state->plane_mask != crtc->state->plane_mask ||
+ crtc_state->zpos_changed) {
+ ret = drm_atomic_helper_crtc_normalize_zpos(crtc,
+ crtc_state);
+ if (ret)
+ return ret;
+ }
+ }
+ return 0;
+}
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f1d9f0569d7f..b1dbb60af99f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1121,16 +1121,14 @@ static int drm_connector_register_all(struct drm_device *dev)
struct drm_connector *connector;
int ret;
- mutex_lock(&dev->mode_config.mutex);
-
- drm_for_each_connector(connector, dev) {
+ /* FIXME: taking the mode config mutex ends up in a clash with
+ * fbcon/backlight registration */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
ret = drm_connector_register(connector);
if (ret)
goto err;
}
- mutex_unlock(&dev->mode_config.mutex);
-
return 0;
err:
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 47a500b90fd7..0c34e6d906d1 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -128,3 +128,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
int drm_modeset_register_all(struct drm_device *dev);
void drm_modeset_unregister_all(struct drm_device *dev);
+
+/* drm_blend.c */
+int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
+ struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 7df26d4b7ad8..637a0aa4d3a0 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -74,6 +74,8 @@
#define EDID_QUIRK_FORCE_8BPC (1 << 8)
/* Force 12bpc */
#define EDID_QUIRK_FORCE_12BPC (1 << 9)
+/* Force 6bpc */
+#define EDID_QUIRK_FORCE_6BPC (1 << 10)
struct detailed_mode_closure {
struct drm_connector *connector;
@@ -100,6 +102,9 @@ static struct edid_quirk {
/* Unknown Acer */
{ "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
+ /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
+ { "AEO", 0, EDID_QUIRK_FORCE_6BPC },
+
/* Belinea 10 15 55 */
{ "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
{ "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
@@ -3862,6 +3867,20 @@ static void drm_add_display_info(struct edid *edid,
/* HDMI deep color modes supported? Assign to info, if so */
drm_assign_hdmi_deep_color_info(edid, info, connector);
+ /*
+ * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
+ *
+ * For such displays, the DFP spec 1.0, section 3.10 "EDID support"
+ * tells us to assume 8 bpc color depth if the EDID doesn't have
+ * extensions which tell otherwise.
+ */
+ if ((info->bpc == 0) && (edid->revision < 4) &&
+ (edid->input & DRM_EDID_DIGITAL_TYPE_DVI)) {
+ info->bpc = 8;
+ DRM_DEBUG("%s: Assigning DFP sink color depth as %d bpc.\n",
+ connector->name, info->bpc);
+ }
+
/* Only defined for 1.4 with digital displays */
if (edid->revision < 4)
return;
@@ -4082,6 +4101,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
drm_add_display_info(edid, &connector->display_info, connector);
+ if (quirks & EDID_QUIRK_FORCE_6BPC)
+ connector->display_info.bpc = 6;
+
if (quirks & EDID_QUIRK_FORCE_8BPC)
connector->display_info.bpc = 8;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index b39d521f093d..7f1a49d5bdbe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -64,7 +64,6 @@ struct exynos_drm_plane_state {
struct exynos_drm_rect src;
unsigned int h_ratio;
unsigned int v_ratio;
- unsigned int zpos;
};
static inline struct exynos_drm_plane_state *
@@ -221,7 +220,6 @@ struct exynos_drm_private {
* this array is used to be aware of which crtc did it request vblank.
*/
struct drm_crtc *crtc[MAX_CRTC];
- struct drm_property *plane_zpos_property;
struct device *dma_dev;
void *mapping;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index fb49443bfd32..4cfb39d543b4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -52,7 +52,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
ret = dma_mmap_attrs(to_dma_dev(helper->dev), vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size,
- &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs);
if (ret < 0) {
DRM_ERROR("failed to mmap.\n");
return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 8564c3da0d22..4bf00f57ffe8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/dma-mapping.h>
-#include <linux/dma-attrs.h>
#include <linux/of.h>
#include <drm/drmP.h>
@@ -235,7 +234,7 @@ struct g2d_data {
struct mutex cmdlist_mutex;
dma_addr_t cmdlist_pool;
void *cmdlist_pool_virt;
- struct dma_attrs cmdlist_dma_attrs;
+ unsigned long cmdlist_dma_attrs;
/* runqueue*/
struct g2d_runqueue_node *runqueue_node;
@@ -256,13 +255,12 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
int ret;
struct g2d_buf_info *buf_info;
- init_dma_attrs(&g2d->cmdlist_dma_attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs);
+ g2d->cmdlist_dma_attrs = DMA_ATTR_WRITE_COMBINE;
g2d->cmdlist_pool_virt = dma_alloc_attrs(to_dma_dev(subdrv->drm_dev),
G2D_CMDLIST_POOL_SIZE,
&g2d->cmdlist_pool, GFP_KERNEL,
- &g2d->cmdlist_dma_attrs);
+ g2d->cmdlist_dma_attrs);
if (!g2d->cmdlist_pool_virt) {
dev_err(dev, "failed to allocate dma memory\n");
return -ENOMEM;
@@ -295,7 +293,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
err:
dma_free_attrs(to_dma_dev(subdrv->drm_dev), G2D_CMDLIST_POOL_SIZE,
g2d->cmdlist_pool_virt,
- g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
+ g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
return ret;
}
@@ -309,7 +307,7 @@ static void g2d_fini_cmdlist(struct g2d_data *g2d)
dma_free_attrs(to_dma_dev(subdrv->drm_dev),
G2D_CMDLIST_POOL_SIZE,
g2d->cmdlist_pool_virt,
- g2d->cmdlist_pool, &g2d->cmdlist_dma_attrs);
+ g2d->cmdlist_pool, g2d->cmdlist_dma_attrs);
}
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index cdf9f1af4347..f2ae72ba7d5a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -24,7 +24,7 @@
static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
{
struct drm_device *dev = exynos_gem->base.dev;
- enum dma_attr attr;
+ unsigned long attr;
unsigned int nr_pages;
struct sg_table sgt;
int ret = -ENOMEM;
@@ -34,7 +34,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
return 0;
}
- init_dma_attrs(&exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs = 0;
/*
* if EXYNOS_BO_CONTIG, fully physically contiguous memory
@@ -42,7 +42,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
* as possible.
*/
if (!(exynos_gem->flags & EXYNOS_BO_NONCONTIG))
- dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
/*
* if EXYNOS_BO_WC or EXYNOS_BO_NONCACHABLE, writecombine mapping
@@ -54,8 +54,8 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
else
attr = DMA_ATTR_NON_CONSISTENT;
- dma_set_attr(attr, &exynos_gem->dma_attrs);
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs |= attr;
+ exynos_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
nr_pages = exynos_gem->size >> PAGE_SHIFT;
@@ -67,7 +67,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
exynos_gem->cookie = dma_alloc_attrs(to_dma_dev(dev), exynos_gem->size,
&exynos_gem->dma_addr, GFP_KERNEL,
- &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs);
if (!exynos_gem->cookie) {
DRM_ERROR("failed to allocate buffer.\n");
goto err_free;
@@ -75,7 +75,7 @@ static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem)
ret = dma_get_sgtable_attrs(to_dma_dev(dev), &sgt, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size,
- &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs);
if (ret < 0) {
DRM_ERROR("failed to get sgtable.\n");
goto err_dma_free;
@@ -99,7 +99,7 @@ err_sgt_free:
sg_free_table(&sgt);
err_dma_free:
dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
- exynos_gem->dma_addr, &exynos_gem->dma_attrs);
+ exynos_gem->dma_addr, exynos_gem->dma_attrs);
err_free:
drm_free_large(exynos_gem->pages);
@@ -120,7 +120,7 @@ static void exynos_drm_free_buf(struct exynos_drm_gem *exynos_gem)
dma_free_attrs(to_dma_dev(dev), exynos_gem->size, exynos_gem->cookie,
(dma_addr_t)exynos_gem->dma_addr,
- &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs);
drm_free_large(exynos_gem->pages);
}
@@ -346,7 +346,7 @@ static int exynos_drm_gem_mmap_buffer(struct exynos_drm_gem *exynos_gem,
ret = dma_mmap_attrs(to_dma_dev(drm_dev), vma, exynos_gem->cookie,
exynos_gem->dma_addr, exynos_gem->size,
- &exynos_gem->dma_attrs);
+ exynos_gem->dma_attrs);
if (ret < 0) {
DRM_ERROR("failed to mmap.\n");
return ret;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index 78100742281d..df7c543d6558 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -50,7 +50,7 @@ struct exynos_drm_gem {
void *cookie;
void __iomem *kvaddr;
dma_addr_t dma_addr;
- struct dma_attrs dma_attrs;
+ unsigned long dma_attrs;
struct page **pages;
struct sg_table *sgt;
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index 77f12c00abf9..7f32419b25ea 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -139,9 +139,9 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
if (exynos_state) {
- exynos_state->zpos = exynos_plane->config->zpos;
plane->state = &exynos_state->base;
plane->state->plane = plane;
+ plane->state->zpos = exynos_plane->config->zpos;
}
}
@@ -157,7 +157,6 @@ exynos_drm_plane_duplicate_state(struct drm_plane *plane)
return NULL;
__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
- copy->zpos = exynos_state->zpos;
return &copy->base;
}
@@ -170,43 +169,6 @@ static void exynos_drm_plane_destroy_state(struct drm_plane *plane,
kfree(old_exynos_state);
}
-static int exynos_drm_plane_atomic_set_property(struct drm_plane *plane,
- struct drm_plane_state *state,
- struct drm_property *property,
- uint64_t val)
-{
- struct exynos_drm_plane *exynos_plane = to_exynos_plane(plane);
- struct exynos_drm_plane_state *exynos_state =
- to_exynos_plane_state(state);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
- const struct exynos_drm_plane_config *config = exynos_plane->config;
-
- if (property == dev_priv->plane_zpos_property &&
- (config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS))
- exynos_state->zpos = val;
- else
- return -EINVAL;
-
- return 0;
-}
-
-static int exynos_drm_plane_atomic_get_property(struct drm_plane *plane,
- const struct drm_plane_state *state,
- struct drm_property *property,
- uint64_t *val)
-{
- const struct exynos_drm_plane_state *exynos_state =
- container_of(state, const struct exynos_drm_plane_state, base);
- struct exynos_drm_private *dev_priv = plane->dev->dev_private;
-
- if (property == dev_priv->plane_zpos_property)
- *val = exynos_state->zpos;
- else
- return -EINVAL;
-
- return 0;
-}
-
static struct drm_plane_funcs exynos_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@@ -215,8 +177,6 @@ static struct drm_plane_funcs exynos_plane_funcs = {
.reset = exynos_drm_plane_reset,
.atomic_duplicate_state = exynos_drm_plane_duplicate_state,
.atomic_destroy_state = exynos_drm_plane_destroy_state,
- .atomic_set_property = exynos_drm_plane_atomic_set_property,
- .atomic_get_property = exynos_drm_plane_atomic_get_property,
};
static int
@@ -304,23 +264,13 @@ static const struct drm_plane_helper_funcs plane_helper_funcs = {
};
static void exynos_plane_attach_zpos_property(struct drm_plane *plane,
- unsigned int zpos)
+ bool immutable)
{
- struct drm_device *dev = plane->dev;
- struct exynos_drm_private *dev_priv = dev->dev_private;
- struct drm_property *prop;
-
- prop = dev_priv->plane_zpos_property;
- if (!prop) {
- prop = drm_property_create_range(dev, 0, "zpos",
- 0, MAX_PLANE - 1);
- if (!prop)
- return;
-
- dev_priv->plane_zpos_property = prop;
- }
-
- drm_object_attach_property(&plane->base, prop, zpos);
+ /* FIXME */
+ if (immutable)
+ drm_plane_create_zpos_immutable_property(plane, 0);
+ else
+ drm_plane_create_zpos_property(plane, 0, 0, MAX_PLANE - 1);
}
int exynos_plane_init(struct drm_device *dev,
@@ -346,7 +296,8 @@ int exynos_plane_init(struct drm_device *dev,
exynos_plane->index = index;
exynos_plane->config = config;
- exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos);
+ exynos_plane_attach_zpos_property(&exynos_plane->base,
+ !(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 74a4269cc1b0..e1d47f9435fc 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -477,6 +477,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
struct mixer_resources *res = &ctx->mixer_res;
struct drm_framebuffer *fb = state->base.fb;
+ unsigned int priority = state->base.normalized_zpos + 1;
unsigned long flags;
dma_addr_t luma_addr[2], chroma_addr[2];
bool tiled_mode = false;
@@ -561,7 +562,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay);
mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, plane->index, state->zpos + 1, true);
+ mixer_cfg_layer(ctx, plane->index, priority, true);
mixer_cfg_vp_blend(ctx);
mixer_run(ctx);
@@ -586,6 +587,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode;
struct mixer_resources *res = &ctx->mixer_res;
struct drm_framebuffer *fb = state->base.fb;
+ unsigned int priority = state->base.normalized_zpos + 1;
unsigned long flags;
unsigned int win = plane->index;
unsigned int x_ratio = 0, y_ratio = 0;
@@ -677,7 +679,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_cfg_scan(ctx, mode->vdisplay);
mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
- mixer_cfg_layer(ctx, win, state->zpos + 1, true);
+ mixer_cfg_layer(ctx, win, priority, true);
mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format));
/* layer update mandatory for mixer 16.0.33.0 */
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 915a3d0acff3..21f939074abc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3651,8 +3651,8 @@ void i915_debugfs_unregister(struct drm_i915_private *dev_priv);
int i915_debugfs_connector_add(struct drm_connector *connector);
void intel_display_crc_init(struct drm_device *dev);
#else
-static inline int i915_debugfs_register(struct drm_i915_private *) {return 0;}
-static inline void i915_debugfs_unregister(struct drm_i915_private *) {}
+static inline int i915_debugfs_register(struct drm_i915_private *dev_priv) {return 0;}
+static inline void i915_debugfs_unregister(struct drm_i915_private *dev_priv) {}
static inline int i915_debugfs_connector_add(struct drm_connector *connector)
{ return 0; }
static inline void intel_display_crc_init(struct drm_device *dev) {}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c457eed76f1f..dcf93b3d4fb6 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5691,15 +5691,7 @@ static bool skl_cdclk_pcu_ready(struct drm_i915_private *dev_priv)
static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
{
- unsigned int i;
-
- for (i = 0; i < 15; i++) {
- if (skl_cdclk_pcu_ready(dev_priv))
- return true;
- udelay(10);
- }
-
- return false;
+ return _wait_for(skl_cdclk_pcu_ready(dev_priv), 3000, 10) == 0;
}
static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
@@ -12114,21 +12106,11 @@ connected_sink_compute_bpp(struct intel_connector *connector,
pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
}
- /* Clamp bpp to default limit on screens without EDID 1.4 */
- if (connector->base.display_info.bpc == 0) {
- int type = connector->base.connector_type;
- int clamp_bpp = 24;
-
- /* Fall back to 18 bpp when DP sink capability is unknown. */
- if (type == DRM_MODE_CONNECTOR_DisplayPort ||
- type == DRM_MODE_CONNECTOR_eDP)
- clamp_bpp = 18;
-
- if (bpp > clamp_bpp) {
- DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
- bpp, clamp_bpp);
- pipe_config->pipe_bpp = clamp_bpp;
- }
+ /* Clamp bpp to 8 on screens without EDID 1.4 */
+ if (connector->base.display_info.bpc == 0 && bpp > 24) {
+ DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
+ bpp);
+ pipe_config->pipe_bpp = 24;
}
}
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 86b00c6db1a6..3e3632c18733 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -782,7 +782,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
struct intel_fbdev *ifbdev = dev_priv->fbdev;
struct fb_info *info;
- if (!ifbdev)
+ if (!ifbdev || !ifbdev->fb)
return;
info = ifbdev->helper.fbdev;
@@ -827,31 +827,28 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
void intel_fbdev_output_poll_changed(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv = to_i915(dev);
- if (dev_priv->fbdev)
- drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
+ struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+
+ if (ifbdev && ifbdev->fb)
+ drm_fb_helper_hotplug_event(&ifbdev->helper);
}
void intel_fbdev_restore_mode(struct drm_device *dev)
{
- int ret;
- struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_fbdev *ifbdev = dev_priv->fbdev;
- struct drm_fb_helper *fb_helper;
+ struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
if (!ifbdev)
return;
intel_fbdev_sync(ifbdev);
+ if (!ifbdev->fb)
+ return;
- fb_helper = &ifbdev->helper;
-
- ret = drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
- if (ret) {
+ if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper)) {
DRM_DEBUG("failed to restore crtc mode\n");
} else {
- mutex_lock(&fb_helper->dev->struct_mutex);
+ mutex_lock(&dev->struct_mutex);
intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT);
- mutex_unlock(&fb_helper->dev->struct_mutex);
+ mutex_unlock(&dev->struct_mutex);
}
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f4f3fcc8b3be..97ba6c8cf907 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4892,7 +4892,8 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
else
gen6_set_rps(dev_priv, dev_priv->rps.idle_freq);
dev_priv->rps.last_adj = 0;
- I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
+ I915_WRITE(GEN6_PMINTRMSK,
+ gen6_sanitize_rps_pm_mask(dev_priv, ~0));
}
mutex_unlock(&dev_priv->rps.hw_lock);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
index fa2ec0cd00e8..7abc550ebc00 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -54,15 +54,14 @@ struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev,
obj = &mtk_gem->base;
- init_dma_attrs(&mtk_gem->dma_attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &mtk_gem->dma_attrs);
+ mtk_gem->dma_attrs = DMA_ATTR_WRITE_COMBINE;
if (!alloc_kmap)
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &mtk_gem->dma_attrs);
+ mtk_gem->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
mtk_gem->cookie = dma_alloc_attrs(priv->dma_dev, obj->size,
&mtk_gem->dma_addr, GFP_KERNEL,
- &mtk_gem->dma_attrs);
+ mtk_gem->dma_attrs);
if (!mtk_gem->cookie) {
DRM_ERROR("failed to allocate %zx byte dma buffer", obj->size);
ret = -ENOMEM;
@@ -93,7 +92,7 @@ void mtk_drm_gem_free_object(struct drm_gem_object *obj)
drm_prime_gem_destroy(obj, mtk_gem->sg);
else
dma_free_attrs(priv->dma_dev, obj->size, mtk_gem->cookie,
- mtk_gem->dma_addr, &mtk_gem->dma_attrs);
+ mtk_gem->dma_addr, mtk_gem->dma_attrs);
/* release file pointer to gem object. */
drm_gem_object_release(obj);
@@ -173,7 +172,7 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj,
vma->vm_pgoff = 0;
ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
- mtk_gem->dma_addr, obj->size, &mtk_gem->dma_attrs);
+ mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
if (ret)
drm_gem_vm_close(vma);
@@ -224,7 +223,7 @@ struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj)
ret = dma_get_sgtable_attrs(priv->dma_dev, sgt, mtk_gem->cookie,
mtk_gem->dma_addr, obj->size,
- &mtk_gem->dma_attrs);
+ mtk_gem->dma_attrs);
if (ret) {
DRM_ERROR("failed to allocate sgt, %d\n", ret);
kfree(sgt);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_drm_gem.h
index 3a2a5624a1cb..2752718fa5b2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.h
@@ -35,7 +35,7 @@ struct mtk_drm_gem_obj {
void *cookie;
void *kvaddr;
dma_addr_t dma_addr;
- struct dma_attrs dma_attrs;
+ unsigned long dma_attrs;
struct sg_table *sg;
};
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 26f859ec24b3..8a0237008f74 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -238,11 +238,10 @@ static int msm_drm_uninit(struct device *dev)
}
if (priv->vram.paddr) {
- DEFINE_DMA_ATTRS(attrs);
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+ unsigned long attrs = DMA_ATTR_NO_KERNEL_MAPPING;
drm_mm_takedown(&priv->vram.mm);
dma_free_attrs(dev, priv->vram.size, NULL,
- priv->vram.paddr, &attrs);
+ priv->vram.paddr, attrs);
}
component_unbind_all(dev, ddev);
@@ -310,21 +309,21 @@ static int msm_init_vram(struct drm_device *dev)
}
if (size) {
- DEFINE_DMA_ATTRS(attrs);
+ unsigned long attrs = 0;
void *p;
priv->vram.size = size;
drm_mm_init(&priv->vram.mm, 0, (size >> PAGE_SHIFT) - 1);
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
+ attrs |= DMA_ATTR_WRITE_COMBINE;
/* note that for no-kernel-mapping, the vaddr returned
* is bogus, but non-null if allocation succeeded:
*/
p = dma_alloc_attrs(dev->dev, size,
- &priv->vram.paddr, GFP_KERNEL, &attrs);
+ &priv->vram.paddr, GFP_KERNEL, attrs);
if (!p) {
dev_err(dev->dev, "failed to allocate VRAM\n");
priv->vram.paddr = 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 528bdeffb339..6190035edfea 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1151,7 +1151,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
if (ret)
goto out;
- ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+ ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, new_mem);
out:
ttm_bo_mem_put(bo, &tmp_mem);
return ret;
@@ -1179,7 +1179,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
if (ret)
return ret;
- ret = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+ ret = ttm_bo_move_ttm(bo, true, intr, no_wait_gpu, &tmp_mem);
if (ret)
goto out;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
index 6b8f2a19b2d9..a6a7fa0d7679 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c
@@ -109,7 +109,7 @@ struct gk20a_instmem {
u16 iommu_bit;
/* Only used by DMA API */
- struct dma_attrs attrs;
+ unsigned long attrs;
};
#define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base)
@@ -293,7 +293,7 @@ gk20a_instobj_dtor_dma(struct nvkm_memory *memory)
goto out;
dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->base.vaddr,
- node->handle, &imem->attrs);
+ node->handle, imem->attrs);
out:
return node;
@@ -386,7 +386,7 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
&node->handle, GFP_KERNEL,
- &imem->attrs);
+ imem->attrs);
if (!node->base.vaddr) {
nvkm_error(subdev, "cannot allocate DMA memory\n");
return -ENOMEM;
@@ -597,10 +597,9 @@ gk20a_instmem_new(struct nvkm_device *device, int index,
nvkm_info(&imem->base.subdev, "using IOMMU\n");
} else {
- init_dma_attrs(&imem->attrs);
- dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs);
- dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs);
+ imem->attrs = DMA_ATTR_NON_CONSISTENT |
+ DMA_ATTR_WEAK_ORDERING |
+ DMA_ATTR_WRITE_COMBINE;
nvkm_info(&imem->base.subdev, "using DMA API\n");
}
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index ffdad81ef964..0c00e192c845 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -346,7 +346,7 @@ static int radeon_move_vram_ram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
goto out_cleanup;
}
- r = ttm_bo_move_ttm(bo, true, no_wait_gpu, new_mem);
+ r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, new_mem);
out_cleanup:
ttm_bo_mem_put(bo, &tmp_mem);
return r;
@@ -379,7 +379,7 @@ static int radeon_move_ram_vram(struct ttm_buffer_object *bo,
if (unlikely(r)) {
return r;
}
- r = ttm_bo_move_ttm(bo, true, no_wait_gpu, &tmp_mem);
+ r = ttm_bo_move_ttm(bo, true, interruptible, no_wait_gpu, &tmp_mem);
if (unlikely(r)) {
goto out_cleanup;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index e39fcef2e033..7316fc7fa0bd 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -196,7 +196,7 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc,
static unsigned int plane_zpos(struct rcar_du_plane *plane)
{
- return to_rcar_plane_state(plane->plane.state)->zpos;
+ return plane->plane.state->normalized_zpos;
}
static const struct rcar_du_format_info *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index ed35467d96cf..c843c3134498 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -92,7 +92,6 @@ struct rcar_du_device {
struct {
struct drm_property *alpha;
struct drm_property *colorkey;
- struct drm_property *zpos;
} props;
unsigned int dpad0_source;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
index 4de3ff0dbebd..e03004f4588d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
@@ -125,6 +125,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
/* Link drm_bridge to encoder */
bridge->encoder = encoder;
+ encoder->bridge = bridge;
ret = drm_bridge_attach(rcdu->ddev, bridge);
if (ret) {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 6bb032d8ac6b..f03eb55318c1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -527,11 +527,6 @@ static int rcar_du_properties_init(struct rcar_du_device *rcdu)
if (rcdu->props.colorkey == NULL)
return -ENOMEM;
- rcdu->props.zpos =
- drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7);
- if (rcdu->props.zpos == NULL)
- return -ENOMEM;
-
return 0;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index bfe31ca870cc..a74f8ed8ca2e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -652,7 +652,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
state->source = RCAR_DU_PLANE_MEMORY;
state->alpha = 255;
state->colorkey = RCAR_DU_COLORKEY_NONE;
- state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
+ state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
plane->state = &state->state;
plane->state->plane = plane;
@@ -670,8 +670,6 @@ static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
rstate->alpha = val;
else if (property == rcdu->props.colorkey)
rstate->colorkey = val;
- else if (property == rcdu->props.zpos)
- rstate->zpos = val;
else
return -EINVAL;
@@ -690,8 +688,6 @@ static int rcar_du_plane_atomic_get_property(struct drm_plane *plane,
*val = rstate->alpha;
else if (property == rcdu->props.colorkey)
*val = rstate->colorkey;
- else if (property == rcdu->props.zpos)
- *val = rstate->zpos;
else
return -EINVAL;
@@ -763,8 +759,7 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
drm_object_attach_property(&plane->plane.base,
rcdu->props.colorkey,
RCAR_DU_COLORKEY_NONE);
- drm_object_attach_property(&plane->plane.base,
- rcdu->props.zpos, 1);
+ drm_plane_create_zpos_property(&plane->plane, 1, 1, 7);
}
return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index b18b7b25dbfa..8b91dd3a46e4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -51,7 +51,6 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
* @hwindex: 0-based hardware plane index, -1 means unused
* @alpha: value of the plane alpha property
* @colorkey: value of the plane colorkey property
- * @zpos: value of the plane zpos property
*/
struct rcar_du_plane_state {
struct drm_plane_state state;
@@ -62,7 +61,6 @@ struct rcar_du_plane_state {
unsigned int alpha;
unsigned int colorkey;
- unsigned int zpos;
};
static inline struct rcar_du_plane_state *
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
index 6ac717f2056f..83ebd162f3ef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -43,12 +43,12 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
.src_y = 0,
.src_w = mode->hdisplay << 16,
.src_h = mode->vdisplay << 16,
+ .zpos = 0,
},
.format = rcar_du_format_info(DRM_FORMAT_ARGB8888),
.source = RCAR_DU_PLANE_VSPD1,
.alpha = 255,
.colorkey = 0,
- .zpos = 0,
};
if (rcdu->info->gen >= 3)
@@ -152,7 +152,7 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
.pixelformat = 0,
.pitch = fb->pitches[0],
.alpha = state->alpha,
- .zpos = state->zpos,
+ .zpos = state->state.zpos,
};
unsigned int i;
@@ -267,7 +267,7 @@ static void rcar_du_vsp_plane_reset(struct drm_plane *plane)
return;
state->alpha = 255;
- state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
+ state->state.zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
plane->state = &state->state;
plane->state->plane = plane;
@@ -282,8 +282,6 @@ static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane,
if (property == rcdu->props.alpha)
rstate->alpha = val;
- else if (property == rcdu->props.zpos)
- rstate->zpos = val;
else
return -EINVAL;
@@ -300,8 +298,6 @@ static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane,
if (property == rcdu->props.alpha)
*val = rstate->alpha;
- else if (property == rcdu->props.zpos)
- *val = rstate->zpos;
else
return -EINVAL;
@@ -381,8 +377,8 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp)
drm_object_attach_property(&plane->plane.base,
rcdu->props.alpha, 255);
- drm_object_attach_property(&plane->plane.base,
- rcdu->props.zpos, 1);
+ drm_plane_create_zpos_property(&plane->plane, 1, 1,
+ vsp->num_planes - 1);
}
return 0;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index 059e902f872d..b70f9423379c 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -17,8 +17,6 @@
#include <drm/drm_gem.h>
#include <drm/drm_vma_manager.h>
-#include <linux/dma-attrs.h>
-
#include "rockchip_drm_drv.h"
#include "rockchip_drm_gem.h"
@@ -28,15 +26,14 @@ static int rockchip_gem_alloc_buf(struct rockchip_gem_object *rk_obj,
struct drm_gem_object *obj = &rk_obj->base;
struct drm_device *drm = obj->dev;
- init_dma_attrs(&rk_obj->dma_attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &rk_obj->dma_attrs);
+ rk_obj->dma_attrs = DMA_ATTR_WRITE_COMBINE;
if (!alloc_kmap)
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs);
+ rk_obj->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
rk_obj->kvaddr = dma_alloc_attrs(drm->dev, obj->size,
&rk_obj->dma_addr, GFP_KERNEL,
- &rk_obj->dma_attrs);
+ rk_obj->dma_attrs);
if (!rk_obj->kvaddr) {
DRM_ERROR("failed to allocate %zu byte dma buffer", obj->size);
return -ENOMEM;
@@ -51,7 +48,7 @@ static void rockchip_gem_free_buf(struct rockchip_gem_object *rk_obj)
struct drm_device *drm = obj->dev;
dma_free_attrs(drm->dev, obj->size, rk_obj->kvaddr, rk_obj->dma_addr,
- &rk_obj->dma_attrs);
+ rk_obj->dma_attrs);
}
static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
@@ -70,7 +67,7 @@ static int rockchip_drm_gem_object_mmap(struct drm_gem_object *obj,
vma->vm_pgoff = 0;
ret = dma_mmap_attrs(drm->dev, vma, rk_obj->kvaddr, rk_obj->dma_addr,
- obj->size, &rk_obj->dma_attrs);
+ obj->size, rk_obj->dma_attrs);
if (ret)
drm_gem_vm_close(vma);
@@ -262,7 +259,7 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj)
ret = dma_get_sgtable_attrs(drm->dev, sgt, rk_obj->kvaddr,
rk_obj->dma_addr, obj->size,
- &rk_obj->dma_attrs);
+ rk_obj->dma_attrs);
if (ret) {
DRM_ERROR("failed to allocate sgt, %d\n", ret);
kfree(sgt);
@@ -276,7 +273,7 @@ void *rockchip_gem_prime_vmap(struct drm_gem_object *obj)
{
struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj);
- if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rk_obj->dma_attrs))
+ if (rk_obj->dma_attrs & DMA_ATTR_NO_KERNEL_MAPPING)
return NULL;
return rk_obj->kvaddr;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
index ad22618473a4..18b3488db4ec 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h
@@ -23,7 +23,7 @@ struct rockchip_gem_object {
void *kvaddr;
dma_addr_t dma_addr;
- struct dma_attrs dma_attrs;
+ unsigned long dma_attrs;
};
struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/sti/sti_cursor.c b/drivers/gpu/drm/sti/sti_cursor.c
index a263bbba4119..3b53f7f2e3fc 100644
--- a/drivers/gpu/drm/sti/sti_cursor.c
+++ b/drivers/gpu/drm/sti/sti_cursor.c
@@ -349,8 +349,8 @@ struct drm_plane_funcs sti_cursor_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = sti_cursor_destroy,
- .set_property = sti_plane_set_property,
- .reset = drm_atomic_helper_plane_reset,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .reset = sti_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_cursor_late_register,
diff --git a/drivers/gpu/drm/sti/sti_gdp.c b/drivers/gpu/drm/sti/sti_gdp.c
index bf63086a3dc8..b8d942ca45e8 100644
--- a/drivers/gpu/drm/sti/sti_gdp.c
+++ b/drivers/gpu/drm/sti/sti_gdp.c
@@ -886,8 +886,8 @@ struct drm_plane_funcs sti_gdp_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = sti_gdp_destroy,
- .set_property = sti_plane_set_property,
- .reset = drm_atomic_helper_plane_reset,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .reset = sti_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_gdp_late_register,
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index b03232247966..b5ee783e3e7c 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1254,8 +1254,8 @@ struct drm_plane_funcs sti_hqvdp_plane_helpers_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = sti_hqvdp_destroy,
- .set_property = sti_plane_set_property,
- .reset = drm_atomic_helper_plane_reset,
+ .set_property = drm_atomic_helper_plane_set_property,
+ .reset = sti_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
.late_register = sti_hqvdp_late_register,
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 1885c7ab5a8b..7d9aea805eab 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -239,13 +239,10 @@ static void sti_mixer_set_background_area(struct sti_mixer *mixer,
int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
{
- int plane_id, depth = plane->zorder;
+ int plane_id, depth = plane->drm_plane.state->normalized_zpos;
unsigned int i;
u32 mask, val;
- if ((depth < 1) || (depth > GAM_MIXER_NB_DEPTH_LEVEL))
- return 1;
-
switch (plane->desc) {
case STI_GDP_0:
plane_id = GAM_DEPTH_GDP0_ID;
@@ -278,8 +275,8 @@ int sti_mixer_set_plane_depth(struct sti_mixer *mixer, struct sti_plane *plane)
break;
}
- mask |= GAM_DEPTH_MASK_ID << (3 * (depth - 1));
- plane_id = plane_id << (3 * (depth - 1));
+ mask |= GAM_DEPTH_MASK_ID << (3 * depth);
+ plane_id = plane_id << (3 * depth);
DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer),
sti_plane_to_str(plane), depth);
diff --git a/drivers/gpu/drm/sti/sti_plane.c b/drivers/gpu/drm/sti/sti_plane.c
index 0cf3335ef37c..ca4b3719a64a 100644
--- a/drivers/gpu/drm/sti/sti_plane.c
+++ b/drivers/gpu/drm/sti/sti_plane.c
@@ -14,15 +14,6 @@
#include "sti_drv.h"
#include "sti_plane.h"
-/* (Background) < GDP0 < GDP1 < HQVDP0 < GDP2 < GDP3 < (ForeGround) */
-enum sti_plane_desc sti_plane_default_zorder[] = {
- STI_GDP_0,
- STI_GDP_1,
- STI_HQVDP_0,
- STI_GDP_2,
- STI_GDP_3,
-};
-
const char *sti_plane_to_str(struct sti_plane *plane)
{
switch (plane->desc) {
@@ -96,59 +87,46 @@ void sti_plane_update_fps(struct sti_plane *plane,
plane->fps_info.fips_str);
}
-int sti_plane_set_property(struct drm_plane *drm_plane,
- struct drm_property *property,
- uint64_t val)
+static int sti_plane_get_default_zpos(enum drm_plane_type type)
{
- struct drm_device *dev = drm_plane->dev;
- struct sti_private *private = dev->dev_private;
- struct sti_plane *plane = to_sti_plane(drm_plane);
-
- DRM_DEBUG_DRIVER("\n");
-
- if (property == private->plane_zorder_property) {
- plane->zorder = val;
+ switch (type) {
+ case DRM_PLANE_TYPE_PRIMARY:
return 0;
+ case DRM_PLANE_TYPE_OVERLAY:
+ return 1;
+ case DRM_PLANE_TYPE_CURSOR:
+ return 7;
}
+ return 0;
+}
- return -EINVAL;
+void sti_plane_reset(struct drm_plane *plane)
+{
+ drm_atomic_helper_plane_reset(plane);
+ plane->state->zpos = sti_plane_get_default_zpos(plane->type);
}
-static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane)
+static void sti_plane_attach_zorder_property(struct drm_plane *drm_plane,
+ enum drm_plane_type type)
{
- struct drm_device *dev = drm_plane->dev;
- struct sti_private *private = dev->dev_private;
- struct sti_plane *plane = to_sti_plane(drm_plane);
- struct drm_property *prop;
-
- prop = private->plane_zorder_property;
- if (!prop) {
- prop = drm_property_create_range(dev, 0, "zpos", 1,
- GAM_MIXER_NB_DEPTH_LEVEL);
- if (!prop)
- return;
-
- private->plane_zorder_property = prop;
+ int zpos = sti_plane_get_default_zpos(type);
+
+ switch (type) {
+ case DRM_PLANE_TYPE_PRIMARY:
+ case DRM_PLANE_TYPE_OVERLAY:
+ drm_plane_create_zpos_property(drm_plane, zpos, 0, 6);
+ break;
+ case DRM_PLANE_TYPE_CURSOR:
+ drm_plane_create_zpos_immutable_property(drm_plane, zpos);
+ break;
}
-
- drm_object_attach_property(&drm_plane->base, prop, plane->zorder);
}
void sti_plane_init_property(struct sti_plane *plane,
enum drm_plane_type type)
{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(sti_plane_default_zorder); i++)
- if (sti_plane_default_zorder[i] == plane->desc)
- break;
-
- plane->zorder = i + 1;
-
- if (type == DRM_PLANE_TYPE_OVERLAY)
- sti_plane_attach_zorder_property(&plane->drm_plane);
+ sti_plane_attach_zorder_property(&plane->drm_plane, type);
- DRM_DEBUG_DRIVER("drm plane:%d mapped to %s with zorder:%d\n",
- plane->drm_plane.base.id,
- sti_plane_to_str(plane), plane->zorder);
+ DRM_DEBUG_DRIVER("drm plane:%d mapped to %s\n",
+ plane->drm_plane.base.id, sti_plane_to_str(plane));
}
diff --git a/drivers/gpu/drm/sti/sti_plane.h b/drivers/gpu/drm/sti/sti_plane.h
index e0ea1dd3bb88..ce3e8d6c88bb 100644
--- a/drivers/gpu/drm/sti/sti_plane.h
+++ b/drivers/gpu/drm/sti/sti_plane.h
@@ -66,14 +66,12 @@ struct sti_fps_info {
* @plane: drm plane it is bound to (if any)
* @desc: plane type & id
* @status: to know the status of the plane
- * @zorder: plane z-order
* @fps_info: frame per second info
*/
struct sti_plane {
struct drm_plane drm_plane;
enum sti_plane_desc desc;
enum sti_plane_status status;
- int zorder;
struct sti_fps_info fps_info;
};
@@ -82,10 +80,7 @@ void sti_plane_update_fps(struct sti_plane *plane,
bool new_frame,
bool new_field);
-int sti_plane_set_property(struct drm_plane *drm_plane,
- struct drm_property *property,
- uint64_t val);
-
void sti_plane_init_property(struct sti_plane *plane,
enum drm_plane_type type);
+void sti_plane_reset(struct drm_plane *plane);
#endif
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 4054d804fe06..42c074a9c955 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -354,7 +354,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
- ret = ttm_bo_move_ttm(bo, evict, no_wait_gpu, mem);
+ ret = ttm_bo_move_ttm(bo, evict, interruptible, no_wait_gpu,
+ mem);
else if (bdev->driver->move)
ret = bdev->driver->move(bo, evict, interruptible,
no_wait_gpu, mem);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 2df602a35f92..f157a9efd220 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -45,7 +45,7 @@ void ttm_bo_free_old_node(struct ttm_buffer_object *bo)
}
int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
- bool evict,
+ bool evict, bool interruptible,
bool no_wait_gpu, struct ttm_mem_reg *new_mem)
{
struct ttm_tt *ttm = bo->ttm;
@@ -53,6 +53,14 @@ int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
int ret;
if (old_mem->mem_type != TTM_PL_SYSTEM) {
+ ret = ttm_bo_wait(bo, interruptible, no_wait_gpu);
+
+ if (unlikely(ret != 0)) {
+ if (ret != -ERESTARTSYS)
+ pr_err("Failed to expire sync object before unbinding TTM\n");
+ return ret;
+ }
+
ttm_tt_unbind(ttm);
ttm_bo_free_old_node(bo);
ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM,
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 2137adfbd8c3..e9b7dc037ff8 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -84,6 +84,7 @@ source "drivers/infiniband/ulp/iser/Kconfig"
source "drivers/infiniband/ulp/isert/Kconfig"
source "drivers/infiniband/sw/rdmavt/Kconfig"
+source "drivers/infiniband/sw/rxe/Kconfig"
source "drivers/infiniband/hw/hfi1/Kconfig"
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index ad1b1adcf6f0..e6dfa1bd3def 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -68,6 +68,7 @@ MODULE_DESCRIPTION("Generic RDMA CM Agent");
MODULE_LICENSE("Dual BSD/GPL");
#define CMA_CM_RESPONSE_TIMEOUT 20
+#define CMA_QUERY_CLASSPORT_INFO_TIMEOUT 3000
#define CMA_MAX_CM_RETRIES 15
#define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
#define CMA_IBOE_PACKET_LIFETIME 18
@@ -162,6 +163,14 @@ struct rdma_bind_list {
unsigned short port;
};
+struct class_port_info_context {
+ struct ib_class_port_info *class_port_info;
+ struct ib_device *device;
+ struct completion done;
+ struct ib_sa_query *sa_query;
+ u8 port_num;
+};
+
static int cma_ps_alloc(struct net *net, enum rdma_port_space ps,
struct rdma_bind_list *bind_list, int snum)
{
@@ -306,6 +315,7 @@ struct cma_multicast {
struct sockaddr_storage addr;
struct kref mcref;
bool igmp_joined;
+ u8 join_state;
};
struct cma_work {
@@ -3752,10 +3762,63 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
}
}
+static void cma_query_sa_classport_info_cb(int status,
+ struct ib_class_port_info *rec,
+ void *context)
+{
+ struct class_port_info_context *cb_ctx = context;
+
+ WARN_ON(!context);
+
+ if (status || !rec) {
+ pr_debug("RDMA CM: %s port %u failed query ClassPortInfo status: %d\n",
+ cb_ctx->device->name, cb_ctx->port_num, status);
+ goto out;
+ }
+
+ memcpy(cb_ctx->class_port_info, rec, sizeof(struct ib_class_port_info));
+
+out:
+ complete(&cb_ctx->done);
+}
+
+static int cma_query_sa_classport_info(struct ib_device *device, u8 port_num,
+ struct ib_class_port_info *class_port_info)
+{
+ struct class_port_info_context *cb_ctx;
+ int ret;
+
+ cb_ctx = kmalloc(sizeof(*cb_ctx), GFP_KERNEL);
+ if (!cb_ctx)
+ return -ENOMEM;
+
+ cb_ctx->device = device;
+ cb_ctx->class_port_info = class_port_info;
+ cb_ctx->port_num = port_num;
+ init_completion(&cb_ctx->done);
+
+ ret = ib_sa_classport_info_rec_query(&sa_client, device, port_num,
+ CMA_QUERY_CLASSPORT_INFO_TIMEOUT,
+ GFP_KERNEL, cma_query_sa_classport_info_cb,
+ cb_ctx, &cb_ctx->sa_query);
+ if (ret < 0) {
+ pr_err("RDMA CM: %s port %u failed to send ClassPortInfo query, ret: %d\n",
+ device->name, port_num, ret);
+ goto out;
+ }
+
+ wait_for_completion(&cb_ctx->done);
+
+out:
+ kfree(cb_ctx);
+ return ret;
+}
+
static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
struct cma_multicast *mc)
{
struct ib_sa_mcmember_rec rec;
+ struct ib_class_port_info class_port_info;
struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
ib_sa_comp_mask comp_mask;
int ret;
@@ -3774,7 +3837,24 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
rec.qkey = cpu_to_be32(id_priv->qkey);
rdma_addr_get_sgid(dev_addr, &rec.port_gid);
rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
- rec.join_state = 1;
+ rec.join_state = mc->join_state;
+
+ if (rec.join_state == BIT(SENDONLY_FULLMEMBER_JOIN)) {
+ ret = cma_query_sa_classport_info(id_priv->id.device,
+ id_priv->id.port_num,
+ &class_port_info);
+
+ if (ret)
+ return ret;
+
+ if (!(ib_get_cpi_capmask2(&class_port_info) &
+ IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT)) {
+ pr_warn("RDMA CM: %s port %u Unable to multicast join\n"
+ "RDMA CM: SM doesn't support Send Only Full Member option\n",
+ id_priv->id.device->name, id_priv->id.port_num);
+ return -EOPNOTSUPP;
+ }
+ }
comp_mask = IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
IB_SA_MCMEMBER_REC_PKEY | IB_SA_MCMEMBER_REC_JOIN_STATE |
@@ -3843,6 +3923,9 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
struct sockaddr *addr = (struct sockaddr *)&mc->addr;
struct net_device *ndev = NULL;
enum ib_gid_type gid_type;
+ bool send_only;
+
+ send_only = mc->join_state == BIT(SENDONLY_FULLMEMBER_JOIN);
if (cma_zero_addr((struct sockaddr *)&mc->addr))
return -EINVAL;
@@ -3878,10 +3961,12 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
if (addr->sa_family == AF_INET) {
if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) {
mc->multicast.ib->rec.hop_limit = IPV6_DEFAULT_HOPLIMIT;
- err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
- true);
- if (!err)
- mc->igmp_joined = true;
+ if (!send_only) {
+ err = cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid,
+ true);
+ if (!err)
+ mc->igmp_joined = true;
+ }
}
} else {
if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
@@ -3911,7 +3996,7 @@ out1:
}
int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
- void *context)
+ u8 join_state, void *context)
{
struct rdma_id_private *id_priv;
struct cma_multicast *mc;
@@ -3930,6 +4015,7 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
mc->context = context;
mc->id_priv = id_priv;
mc->igmp_joined = false;
+ mc->join_state = join_state;
spin_lock(&id_priv->lock);
list_add(&mc->list, &id_priv->mc_list);
spin_unlock(&id_priv->lock);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 5c155fa91eec..760ef603a468 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -311,6 +311,15 @@ static int read_port_immutable(struct ib_device *device)
return 0;
}
+void ib_get_device_fw_str(struct ib_device *dev, char *str, size_t str_len)
+{
+ if (dev->get_dev_fw_str)
+ dev->get_dev_fw_str(dev, str, str_len);
+ else
+ str[0] = '\0';
+}
+EXPORT_SYMBOL(ib_get_device_fw_str);
+
/**
* ib_register_device - Register an IB device with IB core
* @device:Device to register
diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c
index f0572049d291..357624f8b9d3 100644
--- a/drivers/infiniband/core/iwcm.c
+++ b/drivers/infiniband/core/iwcm.c
@@ -183,15 +183,14 @@ static void free_cm_id(struct iwcm_id_private *cm_id_priv)
/*
* Release a reference on cm_id. If the last reference is being
- * released, enable the waiting thread (in iw_destroy_cm_id) to
- * get woken up, and return 1 if a thread is already waiting.
+ * released, free the cm_id and return 1.
*/
static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv)
{
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
if (atomic_dec_and_test(&cm_id_priv->refcount)) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
- complete(&cm_id_priv->destroy_comp);
+ free_cm_id(cm_id_priv);
return 1;
}
@@ -208,19 +207,10 @@ static void add_ref(struct iw_cm_id *cm_id)
static void rem_ref(struct iw_cm_id *cm_id)
{
struct iwcm_id_private *cm_id_priv;
- int cb_destroy;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
- /*
- * Test bit before deref in case the cm_id gets freed on another
- * thread.
- */
- cb_destroy = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
- if (iwcm_deref_id(cm_id_priv) && cb_destroy) {
- BUG_ON(!list_empty(&cm_id_priv->work_list));
- free_cm_id(cm_id_priv);
- }
+ (void)iwcm_deref_id(cm_id_priv);
}
static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event);
@@ -370,6 +360,12 @@ static void destroy_cm_id(struct iw_cm_id *cm_id)
wait_event(cm_id_priv->connect_wait,
!test_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags));
+ /*
+ * Since we're deleting the cm_id, drop any events that
+ * might arrive before the last dereference.
+ */
+ set_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags);
+
spin_lock_irqsave(&cm_id_priv->lock, flags);
switch (cm_id_priv->state) {
case IW_CM_STATE_LISTEN:
@@ -433,13 +429,7 @@ void iw_destroy_cm_id(struct iw_cm_id *cm_id)
struct iwcm_id_private *cm_id_priv;
cm_id_priv = container_of(cm_id, struct iwcm_id_private, id);
- BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags));
-
destroy_cm_id(cm_id);
-
- wait_for_completion(&cm_id_priv->destroy_comp);
-
- free_cm_id(cm_id_priv);
}
EXPORT_SYMBOL(iw_destroy_cm_id);
@@ -809,10 +799,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv,
ret = cm_id->cm_handler(cm_id, iw_event);
if (ret) {
iw_cm_reject(cm_id, NULL, 0);
- set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
- destroy_cm_id(cm_id);
- if (atomic_read(&cm_id_priv->refcount)==0)
- free_cm_id(cm_id_priv);
+ iw_destroy_cm_id(cm_id);
}
out:
@@ -1000,7 +987,6 @@ static void cm_work_handler(struct work_struct *_work)
unsigned long flags;
int empty;
int ret = 0;
- int destroy_id;
spin_lock_irqsave(&cm_id_priv->lock, flags);
empty = list_empty(&cm_id_priv->work_list);
@@ -1013,20 +999,14 @@ static void cm_work_handler(struct work_struct *_work)
put_work(work);
spin_unlock_irqrestore(&cm_id_priv->lock, flags);
- ret = process_event(cm_id_priv, &levent);
- if (ret) {
- set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
- destroy_cm_id(&cm_id_priv->id);
- }
- BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
- destroy_id = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
- if (iwcm_deref_id(cm_id_priv)) {
- if (destroy_id) {
- BUG_ON(!list_empty(&cm_id_priv->work_list));
- free_cm_id(cm_id_priv);
- }
+ if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
+ ret = process_event(cm_id_priv, &levent);
+ if (ret)
+ destroy_cm_id(&cm_id_priv->id);
+ } else
+ pr_debug("dropping event %d\n", levent.event);
+ if (iwcm_deref_id(cm_id_priv))
return;
- }
if (empty)
return;
spin_lock_irqsave(&cm_id_priv->lock, flags);
diff --git a/drivers/infiniband/core/iwcm.h b/drivers/infiniband/core/iwcm.h
index 3f6cc82564c8..82c2cd1b0a80 100644
--- a/drivers/infiniband/core/iwcm.h
+++ b/drivers/infiniband/core/iwcm.h
@@ -56,7 +56,7 @@ struct iwcm_id_private {
struct list_head work_free_list;
};
-#define IWCM_F_CALLBACK_DESTROY 1
+#define IWCM_F_DROP_EVENTS 1
#define IWCM_F_CONNECT_WAIT 2
#endif /* IWCM_H */
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index b65e06c560d7..ade71e7f0131 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -37,6 +37,7 @@
#define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1)
#define IWPM_REMINFO_HASH_SIZE 64
#define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1)
+#define IWPM_MSG_SIZE 512
static LIST_HEAD(iwpm_nlmsg_req_list);
static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
@@ -452,7 +453,7 @@ struct sk_buff *iwpm_create_nlmsg(u32 nl_op, struct nlmsghdr **nlh,
{
struct sk_buff *skb = NULL;
- skb = dev_alloc_skb(NLMSG_GOODSIZE);
+ skb = dev_alloc_skb(IWPM_MSG_SIZE);
if (!skb) {
pr_err("%s Unable to allocate skb\n", __func__);
goto create_nlmsg_exit;
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index a83ec28a147b..3a3c5d73bbfc 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -93,18 +93,6 @@ enum {
struct mcast_member;
-/*
-* There are 4 types of join states:
-* FullMember, NonMember, SendOnlyNonMember, SendOnlyFullMember.
-*/
-enum {
- FULLMEMBER_JOIN,
- NONMEMBER_JOIN,
- SENDONLY_NONMEBER_JOIN,
- SENDONLY_FULLMEMBER_JOIN,
- NUM_JOIN_MEMBERSHIP_TYPES,
-};
-
struct mcast_group {
struct ib_sa_mcmember_rec rec;
struct rb_node node;
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 9b8c20c8209b..10469b0088b5 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -229,7 +229,10 @@ static void ibnl_rcv(struct sk_buff *skb)
int ibnl_unicast(struct sk_buff *skb, struct nlmsghdr *nlh,
__u32 pid)
{
- return nlmsg_unicast(nls, skb, pid);
+ int err;
+
+ err = netlink_unicast(nls, skb, pid, 0);
+ return (err < 0) ? err : 0;
}
EXPORT_SYMBOL(ibnl_unicast);
@@ -252,6 +255,7 @@ int __init ibnl_init(void)
return -ENOMEM;
}
+ nls->sk_sndtimeo = 10 * HZ;
return 0;
}
diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c
index 1eb9b1294a63..dbfd854c32c9 100644
--- a/drivers/infiniband/core/rw.c
+++ b/drivers/infiniband/core/rw.c
@@ -58,19 +58,13 @@ static inline bool rdma_rw_io_needs_mr(struct ib_device *dev, u8 port_num,
return false;
}
-static inline u32 rdma_rw_max_sge(struct ib_device *dev,
- enum dma_data_direction dir)
-{
- return dir == DMA_TO_DEVICE ?
- dev->attrs.max_sge : dev->attrs.max_sge_rd;
-}
-
static inline u32 rdma_rw_fr_page_list_len(struct ib_device *dev)
{
/* arbitrary limit to avoid allocating gigantic resources */
return min_t(u32, dev->attrs.max_fast_reg_page_list_len, 256);
}
+/* Caller must have zero-initialized *reg. */
static int rdma_rw_init_one_mr(struct ib_qp *qp, u8 port_num,
struct rdma_rw_reg_ctx *reg, struct scatterlist *sg,
u32 sg_cnt, u32 offset)
@@ -114,6 +108,7 @@ static int rdma_rw_init_mr_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
u8 port_num, struct scatterlist *sg, u32 sg_cnt, u32 offset,
u64 remote_addr, u32 rkey, enum dma_data_direction dir)
{
+ struct rdma_rw_reg_ctx *prev = NULL;
u32 pages_per_mr = rdma_rw_fr_page_list_len(qp->pd->device);
int i, j, ret = 0, count = 0;
@@ -125,7 +120,6 @@ static int rdma_rw_init_mr_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
}
for (i = 0; i < ctx->nr_ops; i++) {
- struct rdma_rw_reg_ctx *prev = i ? &ctx->reg[i - 1] : NULL;
struct rdma_rw_reg_ctx *reg = &ctx->reg[i];
u32 nents = min(sg_cnt, pages_per_mr);
@@ -162,9 +156,13 @@ static int rdma_rw_init_mr_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
sg_cnt -= nents;
for (j = 0; j < nents; j++)
sg = sg_next(sg);
+ prev = reg;
offset = 0;
}
+ if (prev)
+ prev->wr.wr.next = NULL;
+
ctx->type = RDMA_RW_MR;
return count;
@@ -181,7 +179,8 @@ static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
u64 remote_addr, u32 rkey, enum dma_data_direction dir)
{
struct ib_device *dev = qp->pd->device;
- u32 max_sge = rdma_rw_max_sge(dev, dir);
+ u32 max_sge = dir == DMA_TO_DEVICE ? qp->max_write_sge :
+ qp->max_read_sge;
struct ib_sge *sge;
u32 total_len = 0, i, j;
@@ -205,11 +204,10 @@ static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
rdma_wr->wr.opcode = IB_WR_RDMA_READ;
rdma_wr->remote_addr = remote_addr + total_len;
rdma_wr->rkey = rkey;
+ rdma_wr->wr.num_sge = nr_sge;
rdma_wr->wr.sg_list = sge;
for (j = 0; j < nr_sge; j++, sg = sg_next(sg)) {
- rdma_wr->wr.num_sge++;
-
sge->addr = ib_sg_dma_address(dev, sg) + offset;
sge->length = ib_sg_dma_len(dev, sg) - offset;
sge->lkey = qp->pd->local_dma_lkey;
@@ -220,8 +218,8 @@ static int rdma_rw_init_map_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp,
offset = 0;
}
- if (i + 1 < ctx->nr_ops)
- rdma_wr->wr.next = &ctx->map.wrs[i + 1].wr;
+ rdma_wr->wr.next = i + 1 < ctx->nr_ops ?
+ &ctx->map.wrs[i + 1].wr : NULL;
}
ctx->type = RDMA_RW_MULTI_WR;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index e95538650dc6..b9bf7aa055e7 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -65,10 +65,17 @@ struct ib_sa_sm_ah {
u8 src_path_mask;
};
+struct ib_sa_classport_cache {
+ bool valid;
+ struct ib_class_port_info data;
+};
+
struct ib_sa_port {
struct ib_mad_agent *agent;
struct ib_sa_sm_ah *sm_ah;
struct work_struct update_task;
+ struct ib_sa_classport_cache classport_info;
+ spinlock_t classport_lock; /* protects class port info set */
spinlock_t ah_lock;
u8 port_num;
};
@@ -998,6 +1005,13 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
port->sm_ah = NULL;
spin_unlock_irqrestore(&port->ah_lock, flags);
+ if (event->event == IB_EVENT_SM_CHANGE ||
+ event->event == IB_EVENT_CLIENT_REREGISTER ||
+ event->event == IB_EVENT_LID_CHANGE) {
+ spin_lock_irqsave(&port->classport_lock, flags);
+ port->classport_info.valid = false;
+ spin_unlock_irqrestore(&port->classport_lock, flags);
+ }
queue_work(ib_wq, &sa_dev->port[event->element.port_num -
sa_dev->start_port].update_task);
}
@@ -1719,6 +1733,7 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
int status,
struct ib_sa_mad *mad)
{
+ unsigned long flags;
struct ib_sa_classport_info_query *query =
container_of(sa_query, struct ib_sa_classport_info_query, sa_query);
@@ -1728,6 +1743,16 @@ static void ib_sa_classport_info_rec_callback(struct ib_sa_query *sa_query,
ib_unpack(classport_info_rec_table,
ARRAY_SIZE(classport_info_rec_table),
mad->data, &rec);
+
+ spin_lock_irqsave(&sa_query->port->classport_lock, flags);
+ if (!status && !sa_query->port->classport_info.valid) {
+ memcpy(&sa_query->port->classport_info.data, &rec,
+ sizeof(sa_query->port->classport_info.data));
+
+ sa_query->port->classport_info.valid = true;
+ }
+ spin_unlock_irqrestore(&sa_query->port->classport_lock, flags);
+
query->callback(status, &rec, query->context);
} else {
query->callback(status, NULL, query->context);
@@ -1754,7 +1779,9 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
struct ib_sa_port *port;
struct ib_mad_agent *agent;
struct ib_sa_mad *mad;
+ struct ib_class_port_info cached_class_port_info;
int ret;
+ unsigned long flags;
if (!sa_dev)
return -ENODEV;
@@ -1762,6 +1789,17 @@ int ib_sa_classport_info_rec_query(struct ib_sa_client *client,
port = &sa_dev->port[port_num - sa_dev->start_port];
agent = port->agent;
+ /* Use cached ClassPortInfo attribute if valid instead of sending mad */
+ spin_lock_irqsave(&port->classport_lock, flags);
+ if (port->classport_info.valid && callback) {
+ memcpy(&cached_class_port_info, &port->classport_info.data,
+ sizeof(cached_class_port_info));
+ spin_unlock_irqrestore(&port->classport_lock, flags);
+ callback(0, &cached_class_port_info, context);
+ return 0;
+ }
+ spin_unlock_irqrestore(&port->classport_lock, flags);
+
query = kzalloc(sizeof(*query), gfp_mask);
if (!query)
return -ENOMEM;
@@ -1885,6 +1923,9 @@ static void ib_sa_add_one(struct ib_device *device)
sa_dev->port[i].sm_ah = NULL;
sa_dev->port[i].port_num = i + s;
+ spin_lock_init(&sa_dev->port[i].classport_lock);
+ sa_dev->port[i].classport_info.valid = false;
+
sa_dev->port[i].agent =
ib_register_mad_agent(device, i + s, IB_QPT_GSI,
NULL, 0, send_handler,
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 60df4f8e81be..15defefecb4f 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -38,6 +38,7 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/netdevice.h>
+#include <linux/ethtool.h>
#include <rdma/ib_mad.h>
#include <rdma/ib_pma.h>
@@ -1200,16 +1201,28 @@ static ssize_t set_node_desc(struct device *device,
return count;
}
+static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
+ char *buf)
+{
+ struct ib_device *dev = container_of(device, struct ib_device, dev);
+
+ ib_get_device_fw_str(dev, buf, PAGE_SIZE);
+ strlcat(buf, "\n", PAGE_SIZE);
+ return strlen(buf);
+}
+
static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
+static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static struct device_attribute *ib_class_attributes[] = {
&dev_attr_node_type,
&dev_attr_sys_image_guid,
&dev_attr_node_guid,
- &dev_attr_node_desc
+ &dev_attr_node_desc,
+ &dev_attr_fw_ver,
};
static void free_port_list_attributes(struct ib_device *device)
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index c0f3826abb30..2825ece91d3c 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -106,6 +106,7 @@ struct ucma_multicast {
int events_reported;
u64 uid;
+ u8 join_state;
struct list_head list;
struct sockaddr_storage addr;
};
@@ -1317,12 +1318,20 @@ static ssize_t ucma_process_join(struct ucma_file *file,
struct ucma_multicast *mc;
struct sockaddr *addr;
int ret;
+ u8 join_state;
if (out_len < sizeof(resp))
return -ENOSPC;
addr = (struct sockaddr *) &cmd->addr;
- if (cmd->reserved || !cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
+ if (!cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
+ return -EINVAL;
+
+ if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER)
+ join_state = BIT(FULLMEMBER_JOIN);
+ else if (cmd->join_flags == RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER)
+ join_state = BIT(SENDONLY_FULLMEMBER_JOIN);
+ else
return -EINVAL;
ctx = ucma_get_ctx(file, cmd->id);
@@ -1335,10 +1344,11 @@ static ssize_t ucma_process_join(struct ucma_file *file,
ret = -ENOMEM;
goto err1;
}
-
+ mc->join_state = join_state;
mc->uid = cmd->uid;
memcpy(&mc->addr, addr, cmd->addr_size);
- ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
+ ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr,
+ join_state, mc);
if (ret)
goto err2;
@@ -1382,7 +1392,7 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
join_cmd.uid = cmd.uid;
join_cmd.id = cmd.id;
join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
- join_cmd.reserved = 0;
+ join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER;
memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);
return ucma_process_join(file, &join_cmd, out_len);
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index fe4d2e1a8b58..c68746ce6624 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -37,7 +37,6 @@
#include <linux/sched.h>
#include <linux/export.h>
#include <linux/hugetlb.h>
-#include <linux/dma-attrs.h>
#include <linux/slab.h>
#include <rdma/ib_umem_odp.h>
@@ -92,12 +91,12 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
unsigned long npages;
int ret;
int i;
- DEFINE_DMA_ATTRS(attrs);
+ unsigned long dma_attrs = 0;
struct scatterlist *sg, *sg_list_start;
int need_release = 0;
if (dmasync)
- dma_set_attr(DMA_ATTR_WRITE_BARRIER, &attrs);
+ dma_attrs |= DMA_ATTR_WRITE_BARRIER;
if (!size)
return ERR_PTR(-EINVAL);
@@ -215,7 +214,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr,
umem->sg_head.sgl,
umem->npages,
DMA_BIDIRECTIONAL,
- &attrs);
+ dma_attrs);
if (umem->nmap <= 0) {
ret = -ENOMEM;
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 612ccfd39bf9..df26a741cda6 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -116,6 +116,7 @@ struct ib_uverbs_event_file {
struct ib_uverbs_file {
struct kref ref;
struct mutex mutex;
+ struct mutex cleanup_mutex; /* protect cleanup */
struct ib_uverbs_device *device;
struct ib_ucontext *ucontext;
struct ib_event_handler event_handler;
@@ -162,6 +163,10 @@ struct ib_uqp_object {
struct ib_uxrcd_object *uxrcd;
};
+struct ib_uwq_object {
+ struct ib_uevent_object uevent;
+};
+
struct ib_ucq_object {
struct ib_uobject uobject;
struct ib_uverbs_file *uverbs_file;
@@ -181,6 +186,8 @@ extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
extern struct idr ib_uverbs_xrcd_idr;
extern struct idr ib_uverbs_rule_idr;
+extern struct idr ib_uverbs_wq_idr;
+extern struct idr ib_uverbs_rwq_ind_tbl_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -199,6 +206,7 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
@@ -219,6 +227,7 @@ struct ib_uverbs_flow_spec {
struct ib_uverbs_flow_spec_eth eth;
struct ib_uverbs_flow_spec_ipv4 ipv4;
struct ib_uverbs_flow_spec_tcp_udp tcp_udp;
+ struct ib_uverbs_flow_spec_ipv6 ipv6;
};
};
@@ -275,5 +284,10 @@ IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
IB_UVERBS_DECLARE_EX_CMD(query_device);
IB_UVERBS_DECLARE_EX_CMD(create_cq);
IB_UVERBS_DECLARE_EX_CMD(create_qp);
+IB_UVERBS_DECLARE_EX_CMD(create_wq);
+IB_UVERBS_DECLARE_EX_CMD(modify_wq);
+IB_UVERBS_DECLARE_EX_CMD(destroy_wq);
+IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table);
+IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 825021d1008b..f6647318138d 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -57,6 +57,8 @@ static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
+static struct uverbs_lock_class wq_lock_class = { .name = "WQ-uobj" };
+static struct uverbs_lock_class rwq_ind_table_lock_class = { .name = "IND_TBL-uobj" };
/*
* The ib_uobject locking scheme is as follows:
@@ -243,6 +245,27 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0);
}
+static struct ib_wq *idr_read_wq(int wq_handle, struct ib_ucontext *context)
+{
+ return idr_read_obj(&ib_uverbs_wq_idr, wq_handle, context, 0);
+}
+
+static void put_wq_read(struct ib_wq *wq)
+{
+ put_uobj_read(wq->uobject);
+}
+
+static struct ib_rwq_ind_table *idr_read_rwq_indirection_table(int ind_table_handle,
+ struct ib_ucontext *context)
+{
+ return idr_read_obj(&ib_uverbs_rwq_ind_tbl_idr, ind_table_handle, context, 0);
+}
+
+static void put_rwq_indirection_table_read(struct ib_rwq_ind_table *ind_table)
+{
+ put_uobj_read(ind_table->uobject);
+}
+
static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context)
{
struct ib_uobject *uobj;
@@ -326,6 +349,8 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&ucontext->qp_list);
INIT_LIST_HEAD(&ucontext->srq_list);
INIT_LIST_HEAD(&ucontext->ah_list);
+ INIT_LIST_HEAD(&ucontext->wq_list);
+ INIT_LIST_HEAD(&ucontext->rwq_ind_tbl_list);
INIT_LIST_HEAD(&ucontext->xrcd_list);
INIT_LIST_HEAD(&ucontext->rule_list);
rcu_read_lock();
@@ -1750,6 +1775,8 @@ static int create_qp(struct ib_uverbs_file *file,
struct ib_qp_init_attr attr = {};
struct ib_uverbs_ex_create_qp_resp resp;
int ret;
+ struct ib_rwq_ind_table *ind_tbl = NULL;
+ bool has_sq = true;
if (cmd->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
return -EPERM;
@@ -1761,6 +1788,32 @@ static int create_qp(struct ib_uverbs_file *file,
init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
&qp_lock_class);
down_write(&obj->uevent.uobject.mutex);
+ if (cmd_sz >= offsetof(typeof(*cmd), rwq_ind_tbl_handle) +
+ sizeof(cmd->rwq_ind_tbl_handle) &&
+ (cmd->comp_mask & IB_UVERBS_CREATE_QP_MASK_IND_TABLE)) {
+ ind_tbl = idr_read_rwq_indirection_table(cmd->rwq_ind_tbl_handle,
+ file->ucontext);
+ if (!ind_tbl) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ attr.rwq_ind_tbl = ind_tbl;
+ }
+
+ if ((cmd_sz >= offsetof(typeof(*cmd), reserved1) +
+ sizeof(cmd->reserved1)) && cmd->reserved1) {
+ ret = -EOPNOTSUPP;
+ goto err_put;
+ }
+
+ if (ind_tbl && (cmd->max_recv_wr || cmd->max_recv_sge || cmd->is_srq)) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+
+ if (ind_tbl && !cmd->max_send_wr)
+ has_sq = false;
if (cmd->qp_type == IB_QPT_XRC_TGT) {
xrcd = idr_read_xrcd(cmd->pd_handle, file->ucontext,
@@ -1784,20 +1837,24 @@ static int create_qp(struct ib_uverbs_file *file,
}
}
- if (cmd->recv_cq_handle != cmd->send_cq_handle) {
- rcq = idr_read_cq(cmd->recv_cq_handle,
- file->ucontext, 0);
- if (!rcq) {
- ret = -EINVAL;
- goto err_put;
+ if (!ind_tbl) {
+ if (cmd->recv_cq_handle != cmd->send_cq_handle) {
+ rcq = idr_read_cq(cmd->recv_cq_handle,
+ file->ucontext, 0);
+ if (!rcq) {
+ ret = -EINVAL;
+ goto err_put;
+ }
}
}
}
- scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq);
- rcq = rcq ?: scq;
+ if (has_sq)
+ scq = idr_read_cq(cmd->send_cq_handle, file->ucontext, !!rcq);
+ if (!ind_tbl)
+ rcq = rcq ?: scq;
pd = idr_read_pd(cmd->pd_handle, file->ucontext);
- if (!pd || !scq) {
+ if (!pd || (!scq && has_sq)) {
ret = -EINVAL;
goto err_put;
}
@@ -1864,16 +1921,20 @@ static int create_qp(struct ib_uverbs_file *file,
qp->send_cq = attr.send_cq;
qp->recv_cq = attr.recv_cq;
qp->srq = attr.srq;
+ qp->rwq_ind_tbl = ind_tbl;
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
atomic_set(&qp->usecnt, 0);
atomic_inc(&pd->usecnt);
- atomic_inc(&attr.send_cq->usecnt);
+ if (attr.send_cq)
+ atomic_inc(&attr.send_cq->usecnt);
if (attr.recv_cq)
atomic_inc(&attr.recv_cq->usecnt);
if (attr.srq)
atomic_inc(&attr.srq->usecnt);
+ if (ind_tbl)
+ atomic_inc(&ind_tbl->usecnt);
}
qp->uobject = &obj->uevent.uobject;
@@ -1913,6 +1974,8 @@ static int create_qp(struct ib_uverbs_file *file,
put_cq_read(rcq);
if (srq)
put_srq_read(srq);
+ if (ind_tbl)
+ put_rwq_indirection_table_read(ind_tbl);
mutex_lock(&file->mutex);
list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
@@ -1940,6 +2003,8 @@ err_put:
put_cq_read(rcq);
if (srq)
put_srq_read(srq);
+ if (ind_tbl)
+ put_rwq_indirection_table_read(ind_tbl);
put_uobj_write(&obj->uevent.uobject);
return ret;
@@ -2033,7 +2098,7 @@ int ib_uverbs_ex_create_qp(struct ib_uverbs_file *file,
if (err)
return err;
- if (cmd.comp_mask)
+ if (cmd.comp_mask & ~IB_UVERBS_CREATE_QP_SUP_COMP_MASK)
return -EINVAL;
if (cmd.reserved)
@@ -3040,6 +3105,15 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
memcpy(&ib_spec->ipv4.mask, &kern_spec->ipv4.mask,
sizeof(struct ib_flow_ipv4_filter));
break;
+ case IB_FLOW_SPEC_IPV6:
+ ib_spec->ipv6.size = sizeof(struct ib_flow_spec_ipv6);
+ if (ib_spec->ipv6.size != kern_spec->ipv6.size)
+ return -EINVAL;
+ memcpy(&ib_spec->ipv6.val, &kern_spec->ipv6.val,
+ sizeof(struct ib_flow_ipv6_filter));
+ memcpy(&ib_spec->ipv6.mask, &kern_spec->ipv6.mask,
+ sizeof(struct ib_flow_ipv6_filter));
+ break;
case IB_FLOW_SPEC_TCP:
case IB_FLOW_SPEC_UDP:
ib_spec->tcp_udp.size = sizeof(struct ib_flow_spec_tcp_udp);
@@ -3056,6 +3130,445 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec,
return 0;
}
+int ib_uverbs_ex_create_wq(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_create_wq cmd = {};
+ struct ib_uverbs_ex_create_wq_resp resp = {};
+ struct ib_uwq_object *obj;
+ int err = 0;
+ struct ib_cq *cq;
+ struct ib_pd *pd;
+ struct ib_wq *wq;
+ struct ib_wq_init_attr wq_init_attr = {};
+ size_t required_cmd_sz;
+ size_t required_resp_len;
+
+ required_cmd_sz = offsetof(typeof(cmd), max_sge) + sizeof(cmd.max_sge);
+ required_resp_len = offsetof(typeof(resp), wqn) + sizeof(resp.wqn);
+
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->outlen < required_resp_len)
+ return -ENOSPC;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ err = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EOPNOTSUPP;
+
+ obj = kmalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj)
+ return -ENOMEM;
+
+ init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext,
+ &wq_lock_class);
+ down_write(&obj->uevent.uobject.mutex);
+ pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+ if (!pd) {
+ err = -EINVAL;
+ goto err_uobj;
+ }
+
+ cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0);
+ if (!cq) {
+ err = -EINVAL;
+ goto err_put_pd;
+ }
+
+ wq_init_attr.cq = cq;
+ wq_init_attr.max_sge = cmd.max_sge;
+ wq_init_attr.max_wr = cmd.max_wr;
+ wq_init_attr.wq_context = file;
+ wq_init_attr.wq_type = cmd.wq_type;
+ wq_init_attr.event_handler = ib_uverbs_wq_event_handler;
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
+ wq = pd->device->create_wq(pd, &wq_init_attr, uhw);
+ if (IS_ERR(wq)) {
+ err = PTR_ERR(wq);
+ goto err_put_cq;
+ }
+
+ wq->uobject = &obj->uevent.uobject;
+ obj->uevent.uobject.object = wq;
+ wq->wq_type = wq_init_attr.wq_type;
+ wq->cq = cq;
+ wq->pd = pd;
+ wq->device = pd->device;
+ wq->wq_context = wq_init_attr.wq_context;
+ atomic_set(&wq->usecnt, 0);
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&cq->usecnt);
+ wq->uobject = &obj->uevent.uobject;
+ obj->uevent.uobject.object = wq;
+ err = idr_add_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
+ if (err)
+ goto destroy_wq;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.wq_handle = obj->uevent.uobject.id;
+ resp.max_sge = wq_init_attr.max_sge;
+ resp.max_wr = wq_init_attr.max_wr;
+ resp.wqn = wq->wq_num;
+ resp.response_length = required_resp_len;
+ err = ib_copy_to_udata(ucore,
+ &resp, resp.response_length);
+ if (err)
+ goto err_copy;
+
+ put_pd_read(pd);
+ put_cq_read(cq);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->wq_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uevent.uobject.live = 1;
+ up_write(&obj->uevent.uobject.mutex);
+ return 0;
+
+err_copy:
+ idr_remove_uobj(&ib_uverbs_wq_idr, &obj->uevent.uobject);
+destroy_wq:
+ ib_destroy_wq(wq);
+err_put_cq:
+ put_cq_read(cq);
+err_put_pd:
+ put_pd_read(pd);
+err_uobj:
+ put_uobj_write(&obj->uevent.uobject);
+
+ return err;
+}
+
+int ib_uverbs_ex_destroy_wq(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_destroy_wq cmd = {};
+ struct ib_uverbs_ex_destroy_wq_resp resp = {};
+ struct ib_wq *wq;
+ struct ib_uobject *uobj;
+ struct ib_uwq_object *obj;
+ size_t required_cmd_sz;
+ size_t required_resp_len;
+ int ret;
+
+ required_cmd_sz = offsetof(typeof(cmd), wq_handle) + sizeof(cmd.wq_handle);
+ required_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
+
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->outlen < required_resp_len)
+ return -ENOSPC;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (ret)
+ return ret;
+
+ if (cmd.comp_mask)
+ return -EOPNOTSUPP;
+
+ resp.response_length = required_resp_len;
+ uobj = idr_write_uobj(&ib_uverbs_wq_idr, cmd.wq_handle,
+ file->ucontext);
+ if (!uobj)
+ return -EINVAL;
+
+ wq = uobj->object;
+ obj = container_of(uobj, struct ib_uwq_object, uevent.uobject);
+ ret = ib_destroy_wq(wq);
+ if (!ret)
+ uobj->live = 0;
+
+ put_uobj_write(uobj);
+ if (ret)
+ return ret;
+
+ idr_remove_uobj(&ib_uverbs_wq_idr, uobj);
+
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ ib_uverbs_release_uevent(file, &obj->uevent);
+ resp.events_reported = obj->uevent.events_reported;
+ put_uobj(uobj);
+
+ ret = ib_copy_to_udata(ucore, &resp, resp.response_length);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int ib_uverbs_ex_modify_wq(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_modify_wq cmd = {};
+ struct ib_wq *wq;
+ struct ib_wq_attr wq_attr = {};
+ size_t required_cmd_sz;
+ int ret;
+
+ required_cmd_sz = offsetof(typeof(cmd), curr_wq_state) + sizeof(cmd.curr_wq_state);
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (ret)
+ return ret;
+
+ if (!cmd.attr_mask)
+ return -EINVAL;
+
+ if (cmd.attr_mask > (IB_WQ_STATE | IB_WQ_CUR_STATE))
+ return -EINVAL;
+
+ wq = idr_read_wq(cmd.wq_handle, file->ucontext);
+ if (!wq)
+ return -EINVAL;
+
+ wq_attr.curr_wq_state = cmd.curr_wq_state;
+ wq_attr.wq_state = cmd.wq_state;
+ ret = wq->device->modify_wq(wq, &wq_attr, cmd.attr_mask, uhw);
+ put_wq_read(wq);
+ return ret;
+}
+
+int ib_uverbs_ex_create_rwq_ind_table(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_create_rwq_ind_table cmd = {};
+ struct ib_uverbs_ex_create_rwq_ind_table_resp resp = {};
+ struct ib_uobject *uobj;
+ int err = 0;
+ struct ib_rwq_ind_table_init_attr init_attr = {};
+ struct ib_rwq_ind_table *rwq_ind_tbl;
+ struct ib_wq **wqs = NULL;
+ u32 *wqs_handles = NULL;
+ struct ib_wq *wq = NULL;
+ int i, j, num_read_wqs;
+ u32 num_wq_handles;
+ u32 expected_in_size;
+ size_t required_cmd_sz_header;
+ size_t required_resp_len;
+
+ required_cmd_sz_header = offsetof(typeof(cmd), log_ind_tbl_size) + sizeof(cmd.log_ind_tbl_size);
+ required_resp_len = offsetof(typeof(resp), ind_tbl_num) + sizeof(resp.ind_tbl_num);
+
+ if (ucore->inlen < required_cmd_sz_header)
+ return -EINVAL;
+
+ if (ucore->outlen < required_resp_len)
+ return -ENOSPC;
+
+ err = ib_copy_from_udata(&cmd, ucore, required_cmd_sz_header);
+ if (err)
+ return err;
+
+ ucore->inbuf += required_cmd_sz_header;
+ ucore->inlen -= required_cmd_sz_header;
+
+ if (cmd.comp_mask)
+ return -EOPNOTSUPP;
+
+ if (cmd.log_ind_tbl_size > IB_USER_VERBS_MAX_LOG_IND_TBL_SIZE)
+ return -EINVAL;
+
+ num_wq_handles = 1 << cmd.log_ind_tbl_size;
+ expected_in_size = num_wq_handles * sizeof(__u32);
+ if (num_wq_handles == 1)
+ /* input size for wq handles is u64 aligned */
+ expected_in_size += sizeof(__u32);
+
+ if (ucore->inlen < expected_in_size)
+ return -EINVAL;
+
+ if (ucore->inlen > expected_in_size &&
+ !ib_is_udata_cleared(ucore, expected_in_size,
+ ucore->inlen - expected_in_size))
+ return -EOPNOTSUPP;
+
+ wqs_handles = kcalloc(num_wq_handles, sizeof(*wqs_handles),
+ GFP_KERNEL);
+ if (!wqs_handles)
+ return -ENOMEM;
+
+ err = ib_copy_from_udata(wqs_handles, ucore,
+ num_wq_handles * sizeof(__u32));
+ if (err)
+ goto err_free;
+
+ wqs = kcalloc(num_wq_handles, sizeof(*wqs), GFP_KERNEL);
+ if (!wqs) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ for (num_read_wqs = 0; num_read_wqs < num_wq_handles;
+ num_read_wqs++) {
+ wq = idr_read_wq(wqs_handles[num_read_wqs], file->ucontext);
+ if (!wq) {
+ err = -EINVAL;
+ goto put_wqs;
+ }
+
+ wqs[num_read_wqs] = wq;
+ }
+
+ uobj = kmalloc(sizeof(*uobj), GFP_KERNEL);
+ if (!uobj) {
+ err = -ENOMEM;
+ goto put_wqs;
+ }
+
+ init_uobj(uobj, 0, file->ucontext, &rwq_ind_table_lock_class);
+ down_write(&uobj->mutex);
+ init_attr.log_ind_tbl_size = cmd.log_ind_tbl_size;
+ init_attr.ind_tbl = wqs;
+ rwq_ind_tbl = ib_dev->create_rwq_ind_table(ib_dev, &init_attr, uhw);
+
+ if (IS_ERR(rwq_ind_tbl)) {
+ err = PTR_ERR(rwq_ind_tbl);
+ goto err_uobj;
+ }
+
+ rwq_ind_tbl->ind_tbl = wqs;
+ rwq_ind_tbl->log_ind_tbl_size = init_attr.log_ind_tbl_size;
+ rwq_ind_tbl->uobject = uobj;
+ uobj->object = rwq_ind_tbl;
+ rwq_ind_tbl->device = ib_dev;
+ atomic_set(&rwq_ind_tbl->usecnt, 0);
+
+ for (i = 0; i < num_wq_handles; i++)
+ atomic_inc(&wqs[i]->usecnt);
+
+ err = idr_add_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
+ if (err)
+ goto destroy_ind_tbl;
+
+ resp.ind_tbl_handle = uobj->id;
+ resp.ind_tbl_num = rwq_ind_tbl->ind_tbl_num;
+ resp.response_length = required_resp_len;
+
+ err = ib_copy_to_udata(ucore,
+ &resp, resp.response_length);
+ if (err)
+ goto err_copy;
+
+ kfree(wqs_handles);
+
+ for (j = 0; j < num_read_wqs; j++)
+ put_wq_read(wqs[j]);
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&uobj->list, &file->ucontext->rwq_ind_tbl_list);
+ mutex_unlock(&file->mutex);
+
+ uobj->live = 1;
+
+ up_write(&uobj->mutex);
+ return 0;
+
+err_copy:
+ idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
+destroy_ind_tbl:
+ ib_destroy_rwq_ind_table(rwq_ind_tbl);
+err_uobj:
+ put_uobj_write(uobj);
+put_wqs:
+ for (j = 0; j < num_read_wqs; j++)
+ put_wq_read(wqs[j]);
+err_free:
+ kfree(wqs_handles);
+ kfree(wqs);
+ return err;
+}
+
+int ib_uverbs_ex_destroy_rwq_ind_table(struct ib_uverbs_file *file,
+ struct ib_device *ib_dev,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_ex_destroy_rwq_ind_table cmd = {};
+ struct ib_rwq_ind_table *rwq_ind_tbl;
+ struct ib_uobject *uobj;
+ int ret;
+ struct ib_wq **ind_tbl;
+ size_t required_cmd_sz;
+
+ required_cmd_sz = offsetof(typeof(cmd), ind_tbl_handle) + sizeof(cmd.ind_tbl_handle);
+
+ if (ucore->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (ucore->inlen > sizeof(cmd) &&
+ !ib_is_udata_cleared(ucore, sizeof(cmd),
+ ucore->inlen - sizeof(cmd)))
+ return -EOPNOTSUPP;
+
+ ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+ if (ret)
+ return ret;
+
+ if (cmd.comp_mask)
+ return -EOPNOTSUPP;
+
+ uobj = idr_write_uobj(&ib_uverbs_rwq_ind_tbl_idr, cmd.ind_tbl_handle,
+ file->ucontext);
+ if (!uobj)
+ return -EINVAL;
+ rwq_ind_tbl = uobj->object;
+ ind_tbl = rwq_ind_tbl->ind_tbl;
+
+ ret = ib_destroy_rwq_ind_table(rwq_ind_tbl);
+ if (!ret)
+ uobj->live = 0;
+
+ put_uobj_write(uobj);
+
+ if (ret)
+ return ret;
+
+ idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
+
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ put_uobj(uobj);
+ kfree(ind_tbl);
+ return ret;
+}
+
int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
struct ib_device *ib_dev,
struct ib_udata *ucore,
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 31f422a70623..0012fa58c105 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -76,6 +76,8 @@ DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr);
DEFINE_IDR(ib_uverbs_xrcd_idr);
DEFINE_IDR(ib_uverbs_rule_idr);
+DEFINE_IDR(ib_uverbs_wq_idr);
+DEFINE_IDR(ib_uverbs_rwq_ind_tbl_idr);
static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -130,6 +132,11 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
[IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
[IB_USER_VERBS_EX_CMD_CREATE_CQ] = ib_uverbs_ex_create_cq,
[IB_USER_VERBS_EX_CMD_CREATE_QP] = ib_uverbs_ex_create_qp,
+ [IB_USER_VERBS_EX_CMD_CREATE_WQ] = ib_uverbs_ex_create_wq,
+ [IB_USER_VERBS_EX_CMD_MODIFY_WQ] = ib_uverbs_ex_modify_wq,
+ [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq,
+ [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table,
+ [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table,
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -265,6 +272,27 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uqp);
}
+ list_for_each_entry_safe(uobj, tmp, &context->rwq_ind_tbl_list, list) {
+ struct ib_rwq_ind_table *rwq_ind_tbl = uobj->object;
+ struct ib_wq **ind_tbl = rwq_ind_tbl->ind_tbl;
+
+ idr_remove_uobj(&ib_uverbs_rwq_ind_tbl_idr, uobj);
+ ib_destroy_rwq_ind_table(rwq_ind_tbl);
+ kfree(ind_tbl);
+ kfree(uobj);
+ }
+
+ list_for_each_entry_safe(uobj, tmp, &context->wq_list, list) {
+ struct ib_wq *wq = uobj->object;
+ struct ib_uwq_object *uwq =
+ container_of(uobj, struct ib_uwq_object, uevent.uobject);
+
+ idr_remove_uobj(&ib_uverbs_wq_idr, uobj);
+ ib_destroy_wq(wq);
+ ib_uverbs_release_uevent(file, &uwq->uevent);
+ kfree(uwq);
+ }
+
list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
struct ib_srq *srq = uobj->object;
struct ib_uevent_object *uevent =
@@ -568,6 +596,16 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
&uobj->events_reported);
}
+void ib_uverbs_wq_event_handler(struct ib_event *event, void *context_ptr)
+{
+ struct ib_uevent_object *uobj = container_of(event->element.wq->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
+}
+
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
{
struct ib_uevent_object *uobj;
@@ -931,6 +969,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
file->async_file = NULL;
kref_init(&file->ref);
mutex_init(&file->mutex);
+ mutex_init(&file->cleanup_mutex);
filp->private_data = file;
kobject_get(&dev->kobj);
@@ -956,18 +995,20 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
{
struct ib_uverbs_file *file = filp->private_data;
struct ib_uverbs_device *dev = file->device;
- struct ib_ucontext *ucontext = NULL;
+
+ mutex_lock(&file->cleanup_mutex);
+ if (file->ucontext) {
+ ib_uverbs_cleanup_ucontext(file, file->ucontext);
+ file->ucontext = NULL;
+ }
+ mutex_unlock(&file->cleanup_mutex);
mutex_lock(&file->device->lists_mutex);
- ucontext = file->ucontext;
- file->ucontext = NULL;
if (!file->is_closed) {
list_del(&file->list);
file->is_closed = 1;
}
mutex_unlock(&file->device->lists_mutex);
- if (ucontext)
- ib_uverbs_cleanup_ucontext(file, ucontext);
if (file->async_file)
kref_put(&file->async_file->ref, ib_uverbs_release_event_file);
@@ -1181,22 +1222,30 @@ static void ib_uverbs_free_hw_resources(struct ib_uverbs_device *uverbs_dev,
mutex_lock(&uverbs_dev->lists_mutex);
while (!list_empty(&uverbs_dev->uverbs_file_list)) {
struct ib_ucontext *ucontext;
-
file = list_first_entry(&uverbs_dev->uverbs_file_list,
struct ib_uverbs_file, list);
file->is_closed = 1;
- ucontext = file->ucontext;
list_del(&file->list);
- file->ucontext = NULL;
kref_get(&file->ref);
mutex_unlock(&uverbs_dev->lists_mutex);
- /* We must release the mutex before going ahead and calling
- * disassociate_ucontext. disassociate_ucontext might end up
- * indirectly calling uverbs_close, for example due to freeing
- * the resources (e.g mmput).
- */
+
ib_uverbs_event_handler(&file->event_handler, &event);
+
+ mutex_lock(&file->cleanup_mutex);
+ ucontext = file->ucontext;
+ file->ucontext = NULL;
+ mutex_unlock(&file->cleanup_mutex);
+
+ /* At this point ib_uverbs_close cannot be running
+ * ib_uverbs_cleanup_ucontext
+ */
if (ucontext) {
+ /* We must release the mutex before going ahead and
+ * calling disassociate_ucontext. disassociate_ucontext
+ * might end up indirectly calling uverbs_close,
+ * for example due to freeing the resources
+ * (e.g mmput).
+ */
ib_dev->disassociate_ucontext(ucontext);
ib_uverbs_cleanup_ucontext(file, ucontext);
}
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 6298f54b4137..f2b776efab3a 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -758,6 +758,12 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
struct ib_qp *qp;
int ret;
+ if (qp_init_attr->rwq_ind_tbl &&
+ (qp_init_attr->recv_cq ||
+ qp_init_attr->srq || qp_init_attr->cap.max_recv_wr ||
+ qp_init_attr->cap.max_recv_sge))
+ return ERR_PTR(-EINVAL);
+
/*
* If the callers is using the RDMA API calculate the resources
* needed for the RDMA READ/WRITE operations.
@@ -775,6 +781,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
qp->real_qp = qp;
qp->uobject = NULL;
qp->qp_type = qp_init_attr->qp_type;
+ qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
atomic_set(&qp->usecnt, 0);
qp->mrs_used = 0;
@@ -792,7 +799,8 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
qp->srq = NULL;
} else {
qp->recv_cq = qp_init_attr->recv_cq;
- atomic_inc(&qp_init_attr->recv_cq->usecnt);
+ if (qp_init_attr->recv_cq)
+ atomic_inc(&qp_init_attr->recv_cq->usecnt);
qp->srq = qp_init_attr->srq;
if (qp->srq)
atomic_inc(&qp_init_attr->srq->usecnt);
@@ -803,7 +811,10 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
qp->xrcd = NULL;
atomic_inc(&pd->usecnt);
- atomic_inc(&qp_init_attr->send_cq->usecnt);
+ if (qp_init_attr->send_cq)
+ atomic_inc(&qp_init_attr->send_cq->usecnt);
+ if (qp_init_attr->rwq_ind_tbl)
+ atomic_inc(&qp->rwq_ind_tbl->usecnt);
if (qp_init_attr->cap.max_rdma_ctxs) {
ret = rdma_rw_init_mrs(qp, qp_init_attr);
@@ -814,6 +825,15 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,
}
}
+ /*
+ * Note: all hw drivers guarantee that max_send_sge is lower than
+ * the device RDMA WRITE SGE limit but not all hw drivers ensure that
+ * max_send_sge <= max_sge_rd.
+ */
+ qp->max_write_sge = qp_init_attr->cap.max_send_sge;
+ qp->max_read_sge = min_t(u32, qp_init_attr->cap.max_send_sge,
+ device->attrs.max_sge_rd);
+
return qp;
}
EXPORT_SYMBOL(ib_create_qp);
@@ -1283,6 +1303,7 @@ int ib_destroy_qp(struct ib_qp *qp)
struct ib_pd *pd;
struct ib_cq *scq, *rcq;
struct ib_srq *srq;
+ struct ib_rwq_ind_table *ind_tbl;
int ret;
WARN_ON_ONCE(qp->mrs_used > 0);
@@ -1297,6 +1318,7 @@ int ib_destroy_qp(struct ib_qp *qp)
scq = qp->send_cq;
rcq = qp->recv_cq;
srq = qp->srq;
+ ind_tbl = qp->rwq_ind_tbl;
if (!qp->uobject)
rdma_rw_cleanup_mrs(qp);
@@ -1311,6 +1333,8 @@ int ib_destroy_qp(struct ib_qp *qp)
atomic_dec(&rcq->usecnt);
if (srq)
atomic_dec(&srq->usecnt);
+ if (ind_tbl)
+ atomic_dec(&ind_tbl->usecnt);
}
return ret;
@@ -1558,6 +1582,150 @@ int ib_dealloc_xrcd(struct ib_xrcd *xrcd)
}
EXPORT_SYMBOL(ib_dealloc_xrcd);
+/**
+ * ib_create_wq - Creates a WQ associated with the specified protection
+ * domain.
+ * @pd: The protection domain associated with the WQ.
+ * @wq_init_attr: A list of initial attributes required to create the
+ * WQ. If WQ creation succeeds, then the attributes are updated to
+ * the actual capabilities of the created WQ.
+ *
+ * wq_init_attr->max_wr and wq_init_attr->max_sge determine
+ * the requested size of the WQ, and set to the actual values allocated
+ * on return.
+ * If ib_create_wq() succeeds, then max_wr and max_sge will always be
+ * at least as large as the requested values.
+ */
+struct ib_wq *ib_create_wq(struct ib_pd *pd,
+ struct ib_wq_init_attr *wq_attr)
+{
+ struct ib_wq *wq;
+
+ if (!pd->device->create_wq)
+ return ERR_PTR(-ENOSYS);
+
+ wq = pd->device->create_wq(pd, wq_attr, NULL);
+ if (!IS_ERR(wq)) {
+ wq->event_handler = wq_attr->event_handler;
+ wq->wq_context = wq_attr->wq_context;
+ wq->wq_type = wq_attr->wq_type;
+ wq->cq = wq_attr->cq;
+ wq->device = pd->device;
+ wq->pd = pd;
+ wq->uobject = NULL;
+ atomic_inc(&pd->usecnt);
+ atomic_inc(&wq_attr->cq->usecnt);
+ atomic_set(&wq->usecnt, 0);
+ }
+ return wq;
+}
+EXPORT_SYMBOL(ib_create_wq);
+
+/**
+ * ib_destroy_wq - Destroys the specified WQ.
+ * @wq: The WQ to destroy.
+ */
+int ib_destroy_wq(struct ib_wq *wq)
+{
+ int err;
+ struct ib_cq *cq = wq->cq;
+ struct ib_pd *pd = wq->pd;
+
+ if (atomic_read(&wq->usecnt))
+ return -EBUSY;
+
+ err = wq->device->destroy_wq(wq);
+ if (!err) {
+ atomic_dec(&pd->usecnt);
+ atomic_dec(&cq->usecnt);
+ }
+ return err;
+}
+EXPORT_SYMBOL(ib_destroy_wq);
+
+/**
+ * ib_modify_wq - Modifies the specified WQ.
+ * @wq: The WQ to modify.
+ * @wq_attr: On input, specifies the WQ attributes to modify.
+ * @wq_attr_mask: A bit-mask used to specify which attributes of the WQ
+ * are being modified.
+ * On output, the current values of selected WQ attributes are returned.
+ */
+int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
+ u32 wq_attr_mask)
+{
+ int err;
+
+ if (!wq->device->modify_wq)
+ return -ENOSYS;
+
+ err = wq->device->modify_wq(wq, wq_attr, wq_attr_mask, NULL);
+ return err;
+}
+EXPORT_SYMBOL(ib_modify_wq);
+
+/*
+ * ib_create_rwq_ind_table - Creates a RQ Indirection Table.
+ * @device: The device on which to create the rwq indirection table.
+ * @ib_rwq_ind_table_init_attr: A list of initial attributes required to
+ * create the Indirection Table.
+ *
+ * Note: The life time of ib_rwq_ind_table_init_attr->ind_tbl is not less
+ * than the created ib_rwq_ind_table object and the caller is responsible
+ * for its memory allocation/free.
+ */
+struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device,
+ struct ib_rwq_ind_table_init_attr *init_attr)
+{
+ struct ib_rwq_ind_table *rwq_ind_table;
+ int i;
+ u32 table_size;
+
+ if (!device->create_rwq_ind_table)
+ return ERR_PTR(-ENOSYS);
+
+ table_size = (1 << init_attr->log_ind_tbl_size);
+ rwq_ind_table = device->create_rwq_ind_table(device,
+ init_attr, NULL);
+ if (IS_ERR(rwq_ind_table))
+ return rwq_ind_table;
+
+ rwq_ind_table->ind_tbl = init_attr->ind_tbl;
+ rwq_ind_table->log_ind_tbl_size = init_attr->log_ind_tbl_size;
+ rwq_ind_table->device = device;
+ rwq_ind_table->uobject = NULL;
+ atomic_set(&rwq_ind_table->usecnt, 0);
+
+ for (i = 0; i < table_size; i++)
+ atomic_inc(&rwq_ind_table->ind_tbl[i]->usecnt);
+
+ return rwq_ind_table;
+}
+EXPORT_SYMBOL(ib_create_rwq_ind_table);
+
+/*
+ * ib_destroy_rwq_ind_table - Destroys the specified Indirection Table.
+ * @wq_ind_table: The Indirection Table to destroy.
+*/
+int ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *rwq_ind_table)
+{
+ int err, i;
+ u32 table_size = (1 << rwq_ind_table->log_ind_tbl_size);
+ struct ib_wq **ind_tbl = rwq_ind_table->ind_tbl;
+
+ if (atomic_read(&rwq_ind_table->usecnt))
+ return -EBUSY;
+
+ err = rwq_ind_table->device->destroy_rwq_ind_table(rwq_ind_table);
+ if (!err) {
+ for (i = 0; i < table_size; i++)
+ atomic_dec(&ind_tbl[i]->usecnt);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(ib_destroy_rwq_ind_table);
+
struct ib_flow *ib_create_flow(struct ib_qp *qp,
struct ib_flow_attr *flow_attr,
int domain)
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 3e8431b5cad7..04bbf172abde 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1396,10 +1396,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
state_set(&child_ep->com, CONNECTING);
child_ep->com.tdev = tdev;
child_ep->com.cm_id = NULL;
- child_ep->com.local_addr.sin_family = PF_INET;
+ child_ep->com.local_addr.sin_family = AF_INET;
child_ep->com.local_addr.sin_port = req->local_port;
child_ep->com.local_addr.sin_addr.s_addr = req->local_ip;
- child_ep->com.remote_addr.sin_family = PF_INET;
+ child_ep->com.remote_addr.sin_family = AF_INET;
child_ep->com.remote_addr.sin_port = req->peer_port;
child_ep->com.remote_addr.sin_addr.s_addr = req->peer_ip;
get_ep(&parent_ep->com);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index bb1a839d4d6d..3edb80644b53 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -1183,18 +1183,6 @@ static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
return sprintf(buf, "%d\n", iwch_dev->rdev.t3cdev_p->type);
}
-static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct iwch_dev *iwch_dev = container_of(dev, struct iwch_dev,
- ibdev.dev);
- struct ethtool_drvinfo info;
- struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
-
- PDBG("%s dev 0x%p\n", __func__, dev);
- lldev->ethtool_ops->get_drvinfo(lldev, &info);
- return sprintf(buf, "%s\n", info.fw_version);
-}
-
static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1334,13 +1322,11 @@ static int iwch_get_mib(struct ib_device *ibdev, struct rdma_hw_stats *stats,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct device_attribute *iwch_class_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id,
};
@@ -1362,6 +1348,18 @@ static int iwch_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_ver_str(struct ib_device *ibdev, char *str,
+ size_t str_len)
+{
+ struct iwch_dev *iwch_dev = to_iwch_dev(ibdev);
+ struct ethtool_drvinfo info;
+ struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev;
+
+ PDBG("%s dev 0x%p\n", __func__, iwch_dev);
+ lldev->ethtool_ops->get_drvinfo(lldev, &info);
+ snprintf(str, str_len, "%s", info.fw_version);
+}
+
int iwch_register_device(struct iwch_dev *dev)
{
int ret;
@@ -1437,6 +1435,7 @@ int iwch_register_device(struct iwch_dev *dev)
dev->ibdev.get_hw_stats = iwch_get_mib;
dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION;
dev->ibdev.get_port_immutable = iwch_port_immutable;
+ dev->ibdev.get_dev_fw_str = get_dev_fw_ver_str;
dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
if (!dev->ibdev.iwcm)
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index a3a67216bce6..3aca7f6171b4 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -294,6 +294,25 @@ static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
return;
}
+static int alloc_ep_skb_list(struct sk_buff_head *ep_skb_list, int size)
+{
+ struct sk_buff *skb;
+ unsigned int i;
+ size_t len;
+
+ len = roundup(sizeof(union cpl_wr_size), 16);
+ for (i = 0; i < size; i++) {
+ skb = alloc_skb(len, GFP_KERNEL);
+ if (!skb)
+ goto fail;
+ skb_queue_tail(ep_skb_list, skb);
+ }
+ return 0;
+fail:
+ skb_queue_purge(ep_skb_list);
+ return -ENOMEM;
+}
+
static void *alloc_ep(int size, gfp_t gfp)
{
struct c4iw_ep_common *epc;
@@ -384,6 +403,8 @@ void _c4iw_free_ep(struct kref *kref)
if (ep->mpa_skb)
kfree_skb(ep->mpa_skb);
}
+ if (!skb_queue_empty(&ep->com.ep_skb_list))
+ skb_queue_purge(&ep->com.ep_skb_list);
kfree(ep);
}
@@ -620,25 +641,27 @@ static void abort_arp_failure(void *handle, struct sk_buff *skb)
}
}
-static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
+static int send_flowc(struct c4iw_ep *ep)
{
- unsigned int flowclen = 80;
struct fw_flowc_wr *flowc;
+ struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list);
int i;
u16 vlan = ep->l2t->vlan;
int nparams;
+ if (WARN_ON(!skb))
+ return -ENOMEM;
+
if (vlan == CPL_L2T_VLAN_NONE)
nparams = 8;
else
nparams = 9;
- skb = get_skb(skb, flowclen, GFP_KERNEL);
- flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen);
+ flowc = (struct fw_flowc_wr *)__skb_put(skb, FLOWC_LEN);
flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) |
FW_FLOWC_WR_NPARAMS_V(nparams));
- flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen,
+ flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(FLOWC_LEN,
16)) | FW_WR_FLOWID_V(ep->hwtid));
flowc->mnemval[0].mnemonic = FW_FLOWC_MNEM_PFNVFN;
@@ -679,18 +702,16 @@ static int send_flowc(struct c4iw_ep *ep, struct sk_buff *skb)
return c4iw_ofld_send(&ep->com.dev->rdev, skb);
}
-static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp)
+static int send_halfclose(struct c4iw_ep *ep)
{
struct cpl_close_con_req *req;
- struct sk_buff *skb;
+ struct sk_buff *skb = skb_dequeue(&ep->com.ep_skb_list);
int wrlen = roundup(sizeof *req, 16);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
- skb = get_skb(NULL, wrlen, gfp);
- if (!skb) {
- printk(KERN_ERR MOD "%s - failed to alloc skb\n", __func__);
+ if (WARN_ON(!skb))
return -ENOMEM;
- }
+
set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
t4_set_arp_err_handler(skb, NULL, arp_failure_discard);
req = (struct cpl_close_con_req *) skb_put(skb, wrlen);
@@ -701,26 +722,24 @@ static int send_halfclose(struct c4iw_ep *ep, gfp_t gfp)
return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
}
-static int send_abort(struct c4iw_ep *ep, struct sk_buff *skb, gfp_t gfp)
+static int send_abort(struct c4iw_ep *ep)
{
struct cpl_abort_req *req;
int wrlen = roundup(sizeof *req, 16);
+ struct sk_buff *req_skb = skb_dequeue(&ep->com.ep_skb_list);
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
- skb = get_skb(skb, wrlen, gfp);
- if (!skb) {
- printk(KERN_ERR MOD "%s - failed to alloc skb.\n",
- __func__);
+ if (WARN_ON(!req_skb))
return -ENOMEM;
- }
- set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
- t4_set_arp_err_handler(skb, ep, abort_arp_failure);
- req = (struct cpl_abort_req *) skb_put(skb, wrlen);
+
+ set_wr_txq(req_skb, CPL_PRIORITY_DATA, ep->txq_idx);
+ t4_set_arp_err_handler(req_skb, ep, abort_arp_failure);
+ req = (struct cpl_abort_req *)skb_put(req_skb, wrlen);
memset(req, 0, wrlen);
INIT_TP_WR(req, ep->hwtid);
OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ABORT_REQ, ep->hwtid));
req->cmd = CPL_ABORT_SEND_RST;
- return c4iw_l2t_send(&ep->com.dev->rdev, skb, ep->l2t);
+ return c4iw_l2t_send(&ep->com.dev->rdev, req_skb, ep->l2t);
}
static void best_mtu(const unsigned short *mtus, unsigned short mtu,
@@ -992,9 +1011,19 @@ static int send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
mpa = (struct mpa_message *)(req + 1);
memcpy(mpa->key, MPA_KEY_REQ, sizeof(mpa->key));
- mpa->flags = (crc_enabled ? MPA_CRC : 0) |
- (markers_enabled ? MPA_MARKERS : 0) |
- (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
+
+ mpa->flags = 0;
+ if (crc_enabled)
+ mpa->flags |= MPA_CRC;
+ if (markers_enabled) {
+ mpa->flags |= MPA_MARKERS;
+ ep->mpa_attr.recv_marker_enabled = 1;
+ } else {
+ ep->mpa_attr.recv_marker_enabled = 0;
+ }
+ if (mpa_rev_to_use == 2)
+ mpa->flags |= MPA_ENHANCED_RDMA_CONN;
+
mpa->private_data_size = htons(ep->plen);
mpa->revision = mpa_rev_to_use;
if (mpa_rev_to_use == 1) {
@@ -1169,8 +1198,11 @@ static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen)
mpa = (struct mpa_message *)(req + 1);
memset(mpa, 0, sizeof(*mpa));
memcpy(mpa->key, MPA_KEY_REP, sizeof(mpa->key));
- mpa->flags = (ep->mpa_attr.crc_enabled ? MPA_CRC : 0) |
- (markers_enabled ? MPA_MARKERS : 0);
+ mpa->flags = 0;
+ if (ep->mpa_attr.crc_enabled)
+ mpa->flags |= MPA_CRC;
+ if (ep->mpa_attr.recv_marker_enabled)
+ mpa->flags |= MPA_MARKERS;
mpa->revision = ep->mpa_attr.version;
mpa->private_data_size = htons(plen);
@@ -1248,7 +1280,7 @@ static int act_establish(struct c4iw_dev *dev, struct sk_buff *skb)
set_bit(ACT_ESTAB, &ep->com.history);
/* start MPA negotiation */
- ret = send_flowc(ep, NULL);
+ ret = send_flowc(ep);
if (ret)
goto err;
if (ep->retry_with_mpa_v1)
@@ -1555,7 +1587,6 @@ static int process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb)
*/
__state_set(&ep->com, FPDU_MODE);
ep->mpa_attr.crc_enabled = (mpa->flags & MPA_CRC) | crc_enabled ? 1 : 0;
- ep->mpa_attr.recv_marker_enabled = markers_enabled;
ep->mpa_attr.xmit_marker_enabled = mpa->flags & MPA_MARKERS ? 1 : 0;
ep->mpa_attr.version = mpa->revision;
ep->mpa_attr.p2p_type = FW_RI_INIT_P2PTYPE_DISABLED;
@@ -2004,12 +2035,17 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid)
}
/*
- * Return whether a failed active open has allocated a TID
+ * Some of the error codes above implicitly indicate that there is no TID
+ * allocated with the result of an ACT_OPEN. We use this predicate to make
+ * that explicit.
*/
static inline int act_open_has_tid(int status)
{
- return status != CPL_ERR_TCAM_FULL && status != CPL_ERR_CONN_EXIST &&
- status != CPL_ERR_ARP_MISS;
+ return (status != CPL_ERR_TCAM_PARITY &&
+ status != CPL_ERR_TCAM_MISS &&
+ status != CPL_ERR_TCAM_FULL &&
+ status != CPL_ERR_CONN_EXIST_SYNRECV &&
+ status != CPL_ERR_CONN_EXIST);
}
/* Returns whether a CPL status conveys negative advice.
@@ -2130,6 +2166,7 @@ out:
static int c4iw_reconnect(struct c4iw_ep *ep)
{
int err = 0;
+ int size = 0;
struct sockaddr_in *laddr = (struct sockaddr_in *)
&ep->com.cm_id->m_local_addr;
struct sockaddr_in *raddr = (struct sockaddr_in *)
@@ -2145,6 +2182,21 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
init_timer(&ep->timer);
c4iw_init_wr_wait(&ep->com.wr_wait);
+ /* When MPA revision is different on nodes, the node with MPA_rev=2
+ * tries to reconnect with MPA_rev 1 for the same EP through
+ * c4iw_reconnect(), where the same EP is assigned with new tid for
+ * further connection establishment. As we are using the same EP pointer
+ * for reconnect, few skbs are used during the previous c4iw_connect(),
+ * which leaves the EP with inadequate skbs for further
+ * c4iw_reconnect(), Further causing an assert BUG_ON() due to empty
+ * skb_list() during peer_abort(). Allocate skbs which is already used.
+ */
+ size = (CN_MAX_CON_BUF - skb_queue_len(&ep->com.ep_skb_list));
+ if (alloc_ep_skb_list(&ep->com.ep_skb_list, size)) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
/*
* Allocate an active TID to initiate a TCP connection.
*/
@@ -2210,6 +2262,7 @@ fail2:
* response of 1st connect request.
*/
connect_reply_upcall(ep, -ECONNRESET);
+fail1:
c4iw_put_ep(&ep->com);
out:
return err;
@@ -2576,6 +2629,10 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
if (peer_mss && child_ep->mtu > (peer_mss + hdrs))
child_ep->mtu = peer_mss + hdrs;
+ skb_queue_head_init(&child_ep->com.ep_skb_list);
+ if (alloc_ep_skb_list(&child_ep->com.ep_skb_list, CN_MAX_CON_BUF))
+ goto fail;
+
state_set(&child_ep->com, CONNECTING);
child_ep->com.dev = dev;
child_ep->com.cm_id = NULL;
@@ -2640,6 +2697,8 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
(const u32 *)&sin6->sin6_addr.s6_addr, 1);
}
goto out;
+fail:
+ c4iw_put_ep(&child_ep->com);
reject:
reject_cr(dev, hwtid, skb);
if (parent_ep)
@@ -2670,7 +2729,7 @@ static int pass_establish(struct c4iw_dev *dev, struct sk_buff *skb)
ep->com.state = MPA_REQ_WAIT;
start_ep_timer(ep);
set_bit(PASS_ESTAB, &ep->com.history);
- ret = send_flowc(ep, skb);
+ ret = send_flowc(ep);
mutex_unlock(&ep->com.mutex);
if (ret)
c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
@@ -2871,10 +2930,8 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
}
mutex_unlock(&ep->com.mutex);
- rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
- if (!rpl_skb) {
- printk(KERN_ERR MOD "%s - cannot allocate skb!\n",
- __func__);
+ rpl_skb = skb_dequeue(&ep->com.ep_skb_list);
+ if (WARN_ON(!rpl_skb)) {
release = 1;
goto out;
}
@@ -3011,9 +3068,9 @@ static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb)
PDBG("%s last streaming msg ack ep %p tid %u state %u "
"initiator %u freeing skb\n", __func__, ep, ep->hwtid,
state_read(&ep->com), ep->mpa_attr.initiator ? 1 : 0);
+ mutex_lock(&ep->com.mutex);
kfree_skb(ep->mpa_skb);
ep->mpa_skb = NULL;
- mutex_lock(&ep->com.mutex);
if (test_bit(STOP_MPA_TIMER, &ep->com.flags))
stop_ep_timer(ep);
mutex_unlock(&ep->com.mutex);
@@ -3025,9 +3082,9 @@ out:
int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
{
- int err = 0;
- int disconnect = 0;
+ int abort;
struct c4iw_ep *ep = to_ep(cm_id);
+
PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
mutex_lock(&ep->com.mutex);
@@ -3038,16 +3095,13 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
}
set_bit(ULP_REJECT, &ep->com.history);
if (mpa_rev == 0)
- disconnect = 2;
- else {
- err = send_mpa_reject(ep, pdata, pdata_len);
- disconnect = 1;
- }
+ abort = 1;
+ else
+ abort = send_mpa_reject(ep, pdata, pdata_len);
mutex_unlock(&ep->com.mutex);
- if (disconnect) {
- stop_ep_timer(ep);
- err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
- }
+
+ stop_ep_timer(ep);
+ c4iw_ep_disconnect(ep, abort != 0, GFP_KERNEL);
c4iw_put_ep(&ep->com);
return 0;
}
@@ -3248,6 +3302,13 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = -ENOMEM;
goto out;
}
+
+ skb_queue_head_init(&ep->com.ep_skb_list);
+ if (alloc_ep_skb_list(&ep->com.ep_skb_list, CN_MAX_CON_BUF)) {
+ err = -ENOMEM;
+ goto fail1;
+ }
+
init_timer(&ep->timer);
ep->plen = conn_param->private_data_len;
if (ep->plen)
@@ -3266,7 +3327,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (!ep->com.qp) {
PDBG("%s qpn 0x%x not found!\n", __func__, conn_param->qpn);
err = -EINVAL;
- goto fail1;
+ goto fail2;
}
ref_qp(ep);
PDBG("%s qpn 0x%x qp %p cm_id %p\n", __func__, conn_param->qpn,
@@ -3279,7 +3340,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ep->atid == -1) {
printk(KERN_ERR MOD "%s - cannot alloc atid.\n", __func__);
err = -ENOMEM;
- goto fail1;
+ goto fail2;
}
insert_handle(dev, &dev->atid_idr, ep, ep->atid);
@@ -3303,7 +3364,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) {
err = pick_local_ipaddrs(dev, cm_id);
if (err)
- goto fail1;
+ goto fail2;
}
/* find a route */
@@ -3323,7 +3384,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) {
err = pick_local_ip6addrs(dev, cm_id);
if (err)
- goto fail1;
+ goto fail2;
}
/* find a route */
@@ -3339,14 +3400,14 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (!ep->dst) {
printk(KERN_ERR MOD "%s - cannot find route.\n", __func__);
err = -EHOSTUNREACH;
- goto fail2;
+ goto fail3;
}
err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true,
ep->com.dev->rdev.lldi.adapter_type, cm_id->tos);
if (err) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
- goto fail3;
+ goto fail4;
}
PDBG("%s txq_idx %u tx_chan %u smac_idx %u rss_qid %u l2t_idx %u\n",
@@ -3362,13 +3423,15 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
goto out;
cxgb4_l2t_release(ep->l2t);
-fail3:
+fail4:
dst_release(ep->dst);
-fail2:
+fail3:
remove_handle(ep->com.dev, &ep->com.dev->atid_idr, ep->atid);
cxgb4_free_atid(ep->com.dev->rdev.lldi.tids, ep->atid);
-fail1:
+fail2:
+ skb_queue_purge(&ep->com.ep_skb_list);
deref_cm_id(&ep->com);
+fail1:
c4iw_put_ep(&ep->com);
out:
return err;
@@ -3461,6 +3524,7 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
err = -ENOMEM;
goto fail1;
}
+ skb_queue_head_init(&ep->com.ep_skb_list);
PDBG("%s ep %p\n", __func__, ep);
ep->com.cm_id = cm_id;
ref_cm_id(&ep->com);
@@ -3577,11 +3641,22 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
case MPA_REQ_RCVD:
case MPA_REP_SENT:
case FPDU_MODE:
+ case CONNECTING:
close = 1;
if (abrupt)
ep->com.state = ABORTING;
else {
ep->com.state = CLOSING;
+
+ /*
+ * if we close before we see the fw4_ack() then we fix
+ * up the timer state since we're reusing it.
+ */
+ if (ep->mpa_skb &&
+ test_bit(STOP_MPA_TIMER, &ep->com.flags)) {
+ clear_bit(STOP_MPA_TIMER, &ep->com.flags);
+ stop_ep_timer(ep);
+ }
start_ep_timer(ep);
}
set_bit(CLOSE_SENT, &ep->com.flags);
@@ -3611,10 +3686,10 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
if (abrupt) {
set_bit(EP_DISC_ABORT, &ep->com.history);
close_complete_upcall(ep, -ECONNRESET);
- ret = send_abort(ep, NULL, gfp);
+ ret = send_abort(ep);
} else {
set_bit(EP_DISC_CLOSE, &ep->com.history);
- ret = send_halfclose(ep, gfp);
+ ret = send_halfclose(ep);
}
if (ret) {
set_bit(EP_DISC_FAIL, &ep->com.history);
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index b0b955724458..812ab7278b8e 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -33,19 +33,15 @@
#include "iw_cxgb4.h"
static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
- struct c4iw_dev_ucontext *uctx)
+ struct c4iw_dev_ucontext *uctx, struct sk_buff *skb)
{
struct fw_ri_res_wr *res_wr;
struct fw_ri_res *res;
int wr_len;
struct c4iw_wr_wait wr_wait;
- struct sk_buff *skb;
int ret;
wr_len = sizeof *res_wr + sizeof *res;
- skb = alloc_skb(wr_len, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
res_wr = (struct fw_ri_res_wr *)__skb_put(skb, wr_len);
@@ -863,7 +859,9 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq)
ucontext = ib_cq->uobject ? to_c4iw_ucontext(ib_cq->uobject->context)
: NULL;
destroy_cq(&chp->rhp->rdev, &chp->cq,
- ucontext ? &ucontext->uctx : &chp->cq.rdev->uctx);
+ ucontext ? &ucontext->uctx : &chp->cq.rdev->uctx,
+ chp->destroy_skb);
+ chp->destroy_skb = NULL;
kfree(chp);
return 0;
}
@@ -879,7 +877,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
struct c4iw_cq *chp;
struct c4iw_create_cq_resp uresp;
struct c4iw_ucontext *ucontext = NULL;
- int ret;
+ int ret, wr_len;
size_t memsize, hwentries;
struct c4iw_mm_entry *mm, *mm2;
@@ -896,6 +894,13 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
if (!chp)
return ERR_PTR(-ENOMEM);
+ wr_len = sizeof(struct fw_ri_res_wr) + sizeof(struct fw_ri_res);
+ chp->destroy_skb = alloc_skb(wr_len, GFP_KERNEL);
+ if (!chp->destroy_skb) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+
if (ib_context)
ucontext = to_c4iw_ucontext(ib_context);
@@ -936,7 +941,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
ret = create_cq(&rhp->rdev, &chp->cq,
ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
if (ret)
- goto err1;
+ goto err2;
chp->rhp = rhp;
chp->cq.size--; /* status page */
@@ -947,15 +952,15 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
init_waitqueue_head(&chp->wait);
ret = insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid);
if (ret)
- goto err2;
+ goto err3;
if (ucontext) {
mm = kmalloc(sizeof *mm, GFP_KERNEL);
if (!mm)
- goto err3;
+ goto err4;
mm2 = kmalloc(sizeof *mm2, GFP_KERNEL);
if (!mm2)
- goto err4;
+ goto err5;
uresp.qid_mask = rhp->rdev.cqmask;
uresp.cqid = chp->cq.cqid;
@@ -970,7 +975,7 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
ret = ib_copy_to_udata(udata, &uresp,
sizeof(uresp) - sizeof(uresp.reserved));
if (ret)
- goto err5;
+ goto err6;
mm->key = uresp.key;
mm->addr = virt_to_phys(chp->cq.queue);
@@ -986,15 +991,18 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev,
__func__, chp->cq.cqid, chp, chp->cq.size,
chp->cq.memsize, (unsigned long long) chp->cq.dma_addr);
return &chp->ibcq;
-err5:
+err6:
kfree(mm2);
-err4:
+err5:
kfree(mm);
-err3:
+err4:
remove_handle(rhp, &rhp->cqidr, chp->cq.cqid);
-err2:
+err3:
destroy_cq(&chp->rhp->rdev, &chp->cq,
- ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+ ucontext ? &ucontext->uctx : &rhp->rdev.uctx,
+ chp->destroy_skb);
+err2:
+ kfree_skb(chp->destroy_skb);
err1:
kfree(chp);
return ERR_PTR(ret);
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index ae2e8b23d2dd..071d7332ec06 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -317,7 +317,7 @@ static int qp_open(struct inode *inode, struct file *file)
idr_for_each(&qpd->devp->qpidr, count_idrs, &count);
spin_unlock_irq(&qpd->devp->lock);
- qpd->bufsize = count * 128;
+ qpd->bufsize = count * 180;
qpd->buf = vmalloc(qpd->bufsize);
if (!qpd->buf) {
kfree(qpd);
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index f6f34a75af27..aa47e0ae80bc 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -384,6 +384,7 @@ struct c4iw_mr {
struct ib_mr ibmr;
struct ib_umem *umem;
struct c4iw_dev *rhp;
+ struct sk_buff *dereg_skb;
u64 kva;
struct tpt_attributes attr;
u64 *mpl;
@@ -400,6 +401,7 @@ static inline struct c4iw_mr *to_c4iw_mr(struct ib_mr *ibmr)
struct c4iw_mw {
struct ib_mw ibmw;
struct c4iw_dev *rhp;
+ struct sk_buff *dereg_skb;
u64 kva;
struct tpt_attributes attr;
};
@@ -412,6 +414,7 @@ static inline struct c4iw_mw *to_c4iw_mw(struct ib_mw *ibmw)
struct c4iw_cq {
struct ib_cq ibcq;
struct c4iw_dev *rhp;
+ struct sk_buff *destroy_skb;
struct t4_cq cq;
spinlock_t lock;
spinlock_t comp_handler_lock;
@@ -472,7 +475,7 @@ struct c4iw_qp {
struct t4_wq wq;
spinlock_t lock;
struct mutex mutex;
- atomic_t refcnt;
+ struct kref kref;
wait_queue_head_t wait;
struct timer_list timer;
int sq_sig_all;
@@ -789,10 +792,29 @@ enum c4iw_ep_history {
CM_ID_DEREFED = 28,
};
+enum conn_pre_alloc_buffers {
+ CN_ABORT_REQ_BUF,
+ CN_ABORT_RPL_BUF,
+ CN_CLOSE_CON_REQ_BUF,
+ CN_DESTROY_BUF,
+ CN_FLOWC_BUF,
+ CN_MAX_CON_BUF
+};
+
+#define FLOWC_LEN 80
+union cpl_wr_size {
+ struct cpl_abort_req abrt_req;
+ struct cpl_abort_rpl abrt_rpl;
+ struct fw_ri_wr ri_req;
+ struct cpl_close_con_req close_req;
+ char flowc_buf[FLOWC_LEN];
+};
+
struct c4iw_ep_common {
struct iw_cm_id *cm_id;
struct c4iw_qp *qp;
struct c4iw_dev *dev;
+ struct sk_buff_head ep_skb_list;
enum c4iw_ep_state state;
struct kref kref;
struct mutex mutex;
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 55d0651ee4de..0b91b0f4df71 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -59,9 +59,9 @@ static int mr_exceeds_hw_limits(struct c4iw_dev *dev, u64 length)
}
static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr,
- u32 len, dma_addr_t data, int wait)
+ u32 len, dma_addr_t data,
+ int wait, struct sk_buff *skb)
{
- struct sk_buff *skb;
struct ulp_mem_io *req;
struct ulptx_sgl *sgl;
u8 wr_len;
@@ -74,9 +74,11 @@ static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr,
c4iw_init_wr_wait(&wr_wait);
wr_len = roundup(sizeof(*req) + sizeof(*sgl), 16);
- skb = alloc_skb(wr_len, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
+ if (!skb) {
+ skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL);
+ if (!skb)
+ return -ENOMEM;
+ }
set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
@@ -108,9 +110,8 @@ static int _c4iw_write_mem_dma_aligned(struct c4iw_rdev *rdev, u32 addr,
}
static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
- void *data)
+ void *data, struct sk_buff *skb)
{
- struct sk_buff *skb;
struct ulp_mem_io *req;
struct ulptx_idata *sc;
u8 wr_len, *to_dp, *from_dp;
@@ -134,9 +135,11 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
wr_len = roundup(sizeof *req + sizeof *sc +
roundup(copy_len, T4_ULPTX_MIN_IO), 16);
- skb = alloc_skb(wr_len, GFP_KERNEL);
- if (!skb)
- return -ENOMEM;
+ if (!skb) {
+ skb = alloc_skb(wr_len, GFP_KERNEL | __GFP_NOFAIL);
+ if (!skb)
+ return -ENOMEM;
+ }
set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
req = (struct ulp_mem_io *)__skb_put(skb, wr_len);
@@ -173,6 +176,7 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
memset(to_dp + copy_len, 0, T4_ULPTX_MIN_IO -
(copy_len % T4_ULPTX_MIN_IO));
ret = c4iw_ofld_send(rdev, skb);
+ skb = NULL;
if (ret)
return ret;
len -= C4IW_MAX_INLINE_SIZE;
@@ -182,7 +186,8 @@ static int _c4iw_write_mem_inline(struct c4iw_rdev *rdev, u32 addr, u32 len,
return ret;
}
-static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
+static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len,
+ void *data, struct sk_buff *skb)
{
u32 remain = len;
u32 dmalen;
@@ -205,7 +210,7 @@ static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *
dmalen = T4_ULPTX_MAX_DMA;
remain -= dmalen;
ret = _c4iw_write_mem_dma_aligned(rdev, addr, dmalen, daddr,
- !remain);
+ !remain, skb);
if (ret)
goto out;
addr += dmalen >> 5;
@@ -213,7 +218,7 @@ static int _c4iw_write_mem_dma(struct c4iw_rdev *rdev, u32 addr, u32 len, void *
daddr += dmalen;
}
if (remain)
- ret = _c4iw_write_mem_inline(rdev, addr, remain, data);
+ ret = _c4iw_write_mem_inline(rdev, addr, remain, data, skb);
out:
dma_unmap_single(&rdev->lldi.pdev->dev, save, len, DMA_TO_DEVICE);
return ret;
@@ -224,23 +229,25 @@ out:
* If data is NULL, clear len byte of memory to zero.
*/
static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
- void *data)
+ void *data, struct sk_buff *skb)
{
if (is_t5(rdev->lldi.adapter_type) && use_dsgl) {
if (len > inline_threshold) {
- if (_c4iw_write_mem_dma(rdev, addr, len, data)) {
+ if (_c4iw_write_mem_dma(rdev, addr, len, data, skb)) {
printk_ratelimited(KERN_WARNING
"%s: dma map"
" failure (non fatal)\n",
pci_name(rdev->lldi.pdev));
return _c4iw_write_mem_inline(rdev, addr, len,
- data);
- } else
+ data, skb);
+ } else {
return 0;
+ }
} else
- return _c4iw_write_mem_inline(rdev, addr, len, data);
+ return _c4iw_write_mem_inline(rdev, addr,
+ len, data, skb);
} else
- return _c4iw_write_mem_inline(rdev, addr, len, data);
+ return _c4iw_write_mem_inline(rdev, addr, len, data, skb);
}
/*
@@ -253,7 +260,8 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
u32 *stag, u8 stag_state, u32 pdid,
enum fw_ri_stag_type type, enum fw_ri_mem_perms perm,
int bind_enabled, u32 zbva, u64 to,
- u64 len, u8 page_size, u32 pbl_size, u32 pbl_addr)
+ u64 len, u8 page_size, u32 pbl_size, u32 pbl_addr,
+ struct sk_buff *skb)
{
int err;
struct fw_ri_tpte tpt;
@@ -307,7 +315,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
}
err = write_adapter_mem(rdev, stag_idx +
(rdev->lldi.vr->stag.start >> 5),
- sizeof(tpt), &tpt);
+ sizeof(tpt), &tpt, skb);
if (reset_tpt_entry) {
c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
@@ -327,28 +335,29 @@ static int write_pbl(struct c4iw_rdev *rdev, __be64 *pbl,
__func__, pbl_addr, rdev->lldi.vr->pbl.start,
pbl_size);
- err = write_adapter_mem(rdev, pbl_addr >> 5, pbl_size << 3, pbl);
+ err = write_adapter_mem(rdev, pbl_addr >> 5, pbl_size << 3, pbl, NULL);
return err;
}
static int dereg_mem(struct c4iw_rdev *rdev, u32 stag, u32 pbl_size,
- u32 pbl_addr)
+ u32 pbl_addr, struct sk_buff *skb)
{
return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0,
- pbl_size, pbl_addr);
+ pbl_size, pbl_addr, skb);
}
static int allocate_window(struct c4iw_rdev *rdev, u32 * stag, u32 pdid)
{
*stag = T4_STAG_UNSET;
return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_MW, 0, 0, 0,
- 0UL, 0, 0, 0, 0);
+ 0UL, 0, 0, 0, 0, NULL);
}
-static int deallocate_window(struct c4iw_rdev *rdev, u32 stag)
+static int deallocate_window(struct c4iw_rdev *rdev, u32 stag,
+ struct sk_buff *skb)
{
return write_tpt_entry(rdev, 1, &stag, 0, 0, 0, 0, 0, 0, 0UL, 0, 0, 0,
- 0);
+ 0, skb);
}
static int allocate_stag(struct c4iw_rdev *rdev, u32 *stag, u32 pdid,
@@ -356,7 +365,7 @@ static int allocate_stag(struct c4iw_rdev *rdev, u32 *stag, u32 pdid,
{
*stag = T4_STAG_UNSET;
return write_tpt_entry(rdev, 0, stag, 0, pdid, FW_RI_STAG_NSMR, 0, 0, 0,
- 0UL, 0, 0, pbl_size, pbl_addr);
+ 0UL, 0, 0, pbl_size, pbl_addr, NULL);
}
static int finish_mem_reg(struct c4iw_mr *mhp, u32 stag)
@@ -383,14 +392,16 @@ static int register_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
mhp->attr.mw_bind_enable, mhp->attr.zbva,
mhp->attr.va_fbo, mhp->attr.len ?
mhp->attr.len : -1, shift - 12,
- mhp->attr.pbl_size, mhp->attr.pbl_addr);
+ mhp->attr.pbl_size, mhp->attr.pbl_addr, NULL);
if (ret)
return ret;
ret = finish_mem_reg(mhp, stag);
- if (ret)
+ if (ret) {
dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
- mhp->attr.pbl_addr);
+ mhp->attr.pbl_addr, mhp->dereg_skb);
+ mhp->dereg_skb = NULL;
+ }
return ret;
}
@@ -423,6 +434,12 @@ struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
if (!mhp)
return ERR_PTR(-ENOMEM);
+ mhp->dereg_skb = alloc_skb(SGE_MAX_WR_LEN, GFP_KERNEL);
+ if (!mhp->dereg_skb) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+
mhp->rhp = rhp;
mhp->attr.pdid = php->pdid;
mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
@@ -435,7 +452,8 @@ struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, php->pdid,
FW_RI_STAG_NSMR, mhp->attr.perms,
- mhp->attr.mw_bind_enable, 0, 0, ~0ULL, 0, 0, 0);
+ mhp->attr.mw_bind_enable, 0, 0, ~0ULL, 0, 0, 0,
+ NULL);
if (ret)
goto err1;
@@ -445,8 +463,10 @@ struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc)
return &mhp->ibmr;
err2:
dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
- mhp->attr.pbl_addr);
+ mhp->attr.pbl_addr, mhp->dereg_skb);
err1:
+ kfree_skb(mhp->dereg_skb);
+err0:
kfree(mhp);
return ERR_PTR(ret);
}
@@ -481,11 +501,18 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
if (!mhp)
return ERR_PTR(-ENOMEM);
+ mhp->dereg_skb = alloc_skb(SGE_MAX_WR_LEN, GFP_KERNEL);
+ if (!mhp->dereg_skb) {
+ kfree(mhp);
+ return ERR_PTR(-ENOMEM);
+ }
+
mhp->rhp = rhp;
mhp->umem = ib_umem_get(pd->uobject->context, start, length, acc, 0);
if (IS_ERR(mhp->umem)) {
err = PTR_ERR(mhp->umem);
+ kfree_skb(mhp->dereg_skb);
kfree(mhp);
return ERR_PTR(err);
}
@@ -550,6 +577,7 @@ err_pbl:
err:
ib_umem_release(mhp->umem);
+ kfree_skb(mhp->dereg_skb);
kfree(mhp);
return ERR_PTR(err);
}
@@ -572,11 +600,16 @@ struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
if (!mhp)
return ERR_PTR(-ENOMEM);
- ret = allocate_window(&rhp->rdev, &stag, php->pdid);
- if (ret) {
- kfree(mhp);
- return ERR_PTR(ret);
+
+ mhp->dereg_skb = alloc_skb(SGE_MAX_WR_LEN, GFP_KERNEL);
+ if (!mhp->dereg_skb) {
+ ret = -ENOMEM;
+ goto free_mhp;
}
+
+ ret = allocate_window(&rhp->rdev, &stag, php->pdid);
+ if (ret)
+ goto free_skb;
mhp->rhp = rhp;
mhp->attr.pdid = php->pdid;
mhp->attr.type = FW_RI_STAG_MW;
@@ -584,12 +617,19 @@ struct ib_mw *c4iw_alloc_mw(struct ib_pd *pd, enum ib_mw_type type,
mmid = (stag) >> 8;
mhp->ibmw.rkey = stag;
if (insert_handle(rhp, &rhp->mmidr, mhp, mmid)) {
- deallocate_window(&rhp->rdev, mhp->attr.stag);
- kfree(mhp);
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto dealloc_win;
}
PDBG("%s mmid 0x%x mhp %p stag 0x%x\n", __func__, mmid, mhp, stag);
return &(mhp->ibmw);
+
+dealloc_win:
+ deallocate_window(&rhp->rdev, mhp->attr.stag, mhp->dereg_skb);
+free_skb:
+ kfree_skb(mhp->dereg_skb);
+free_mhp:
+ kfree(mhp);
+ return ERR_PTR(ret);
}
int c4iw_dealloc_mw(struct ib_mw *mw)
@@ -602,7 +642,8 @@ int c4iw_dealloc_mw(struct ib_mw *mw)
rhp = mhp->rhp;
mmid = (mw->rkey) >> 8;
remove_handle(rhp, &rhp->mmidr, mmid);
- deallocate_window(&rhp->rdev, mhp->attr.stag);
+ deallocate_window(&rhp->rdev, mhp->attr.stag, mhp->dereg_skb);
+ kfree_skb(mhp->dereg_skb);
kfree(mhp);
PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
return 0;
@@ -666,7 +707,7 @@ struct ib_mr *c4iw_alloc_mr(struct ib_pd *pd,
return &(mhp->ibmr);
err3:
dereg_mem(&rhp->rdev, stag, mhp->attr.pbl_size,
- mhp->attr.pbl_addr);
+ mhp->attr.pbl_addr, mhp->dereg_skb);
err2:
c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
mhp->attr.pbl_size << 3);
@@ -717,7 +758,7 @@ int c4iw_dereg_mr(struct ib_mr *ib_mr)
dma_free_coherent(&mhp->rhp->rdev.lldi.pdev->dev,
mhp->max_mpl_len, mhp->mpl, mhp->mpl_addr);
dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
- mhp->attr.pbl_addr);
+ mhp->attr.pbl_addr, mhp->dereg_skb);
if (mhp->attr.pbl_size)
c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
mhp->attr.pbl_size << 3);
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index dd8a86b726d2..df127ce6b6ec 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -409,20 +409,6 @@ static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
CHELSIO_CHIP_RELEASE(c4iw_dev->rdev.lldi.adapter_type));
}
-static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct c4iw_dev *c4iw_dev = container_of(dev, struct c4iw_dev,
- ibdev.dev);
- PDBG("%s dev 0x%p\n", __func__, dev);
-
- return sprintf(buf, "%u.%u.%u.%u\n",
- FW_HDR_FW_VER_MAJOR_G(c4iw_dev->rdev.lldi.fw_vers),
- FW_HDR_FW_VER_MINOR_G(c4iw_dev->rdev.lldi.fw_vers),
- FW_HDR_FW_VER_MICRO_G(c4iw_dev->rdev.lldi.fw_vers),
- FW_HDR_FW_VER_BUILD_G(c4iw_dev->rdev.lldi.fw_vers));
-}
-
static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -502,13 +488,11 @@ static int c4iw_get_mib(struct ib_device *ibdev,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct device_attribute *c4iw_class_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id,
};
@@ -530,6 +514,20 @@ static int c4iw_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_str(struct ib_device *dev, char *str,
+ size_t str_len)
+{
+ struct c4iw_dev *c4iw_dev = container_of(dev, struct c4iw_dev,
+ ibdev);
+ PDBG("%s dev 0x%p\n", __func__, dev);
+
+ snprintf(str, str_len, "%u.%u.%u.%u",
+ FW_HDR_FW_VER_MAJOR_G(c4iw_dev->rdev.lldi.fw_vers),
+ FW_HDR_FW_VER_MINOR_G(c4iw_dev->rdev.lldi.fw_vers),
+ FW_HDR_FW_VER_MICRO_G(c4iw_dev->rdev.lldi.fw_vers),
+ FW_HDR_FW_VER_BUILD_G(c4iw_dev->rdev.lldi.fw_vers));
+}
+
int c4iw_register_device(struct c4iw_dev *dev)
{
int ret;
@@ -605,6 +603,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
dev->ibdev.get_hw_stats = c4iw_get_mib;
dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
dev->ibdev.get_port_immutable = c4iw_port_immutable;
+ dev->ibdev.get_dev_fw_str = get_dev_fw_str;
dev->ibdev.drain_sq = c4iw_drain_sq;
dev->ibdev.drain_rq = c4iw_drain_rq;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index e8993e49b8b3..edb1172b6f54 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -683,17 +683,25 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr,
return 0;
}
+void _free_qp(struct kref *kref)
+{
+ struct c4iw_qp *qhp;
+
+ qhp = container_of(kref, struct c4iw_qp, kref);
+ PDBG("%s qhp %p\n", __func__, qhp);
+ kfree(qhp);
+}
+
void c4iw_qp_add_ref(struct ib_qp *qp)
{
PDBG("%s ib_qp %p\n", __func__, qp);
- atomic_inc(&(to_c4iw_qp(qp)->refcnt));
+ kref_get(&to_c4iw_qp(qp)->kref);
}
void c4iw_qp_rem_ref(struct ib_qp *qp)
{
PDBG("%s ib_qp %p\n", __func__, qp);
- if (atomic_dec_and_test(&(to_c4iw_qp(qp)->refcnt)))
- wake_up(&(to_c4iw_qp(qp)->wait));
+ kref_put(&to_c4iw_qp(qp)->kref, _free_qp);
}
static void add_to_fc_list(struct list_head *head, struct list_head *entry)
@@ -1081,9 +1089,10 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
qhp->ep->hwtid);
- skb = alloc_skb(sizeof *wqe, gfp);
- if (!skb)
+ skb = skb_dequeue(&qhp->ep->com.ep_skb_list);
+ if (WARN_ON(!skb))
return;
+
set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
@@ -1202,9 +1211,10 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
ep->hwtid);
- skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
- if (!skb)
+ skb = skb_dequeue(&ep->com.ep_skb_list);
+ if (WARN_ON(!skb))
return -ENOMEM;
+
set_wr_txq(skb, CPL_PRIORITY_DATA, ep->txq_idx);
wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
@@ -1592,8 +1602,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
wait_event(qhp->wait, !qhp->ep);
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
- atomic_dec(&qhp->refcnt);
- wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
spin_lock_irq(&rhp->lock);
if (!list_empty(&qhp->db_fc_entry))
@@ -1606,8 +1614,9 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
destroy_qp(&rhp->rdev, &qhp->wq,
ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+ c4iw_qp_rem_ref(ib_qp);
+
PDBG("%s ib_qp %p qpid 0x%0x\n", __func__, ib_qp, qhp->wq.sq.qid);
- kfree(qhp);
return 0;
}
@@ -1704,7 +1713,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
init_completion(&qhp->rq_drained);
mutex_init(&qhp->mutex);
init_waitqueue_head(&qhp->wait);
- atomic_set(&qhp->refcnt, 1);
+ kref_init(&qhp->kref);
ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
if (ret)
@@ -1896,12 +1905,20 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
return 0;
}
+static void move_qp_to_err(struct c4iw_qp *qp)
+{
+ struct c4iw_qp_attributes attrs = { .next_state = C4IW_QP_STATE_ERROR };
+
+ (void)c4iw_modify_qp(qp->rhp, qp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+}
+
void c4iw_drain_sq(struct ib_qp *ibqp)
{
struct c4iw_qp *qp = to_c4iw_qp(ibqp);
unsigned long flag;
bool need_to_wait;
+ move_qp_to_err(qp);
spin_lock_irqsave(&qp->lock, flag);
need_to_wait = !t4_sq_empty(&qp->wq);
spin_unlock_irqrestore(&qp->lock, flag);
@@ -1916,6 +1933,7 @@ void c4iw_drain_rq(struct ib_qp *ibqp)
unsigned long flag;
bool need_to_wait;
+ move_qp_to_err(qp);
spin_lock_irqsave(&qp->lock, flag);
need_to_wait = !t4_rq_empty(&qp->wq);
spin_unlock_irqrestore(&qp->lock, flag);
diff --git a/drivers/infiniband/hw/hfi1/Kconfig b/drivers/infiniband/hw/hfi1/Kconfig
index a925fb0db706..f6ea0881765a 100644
--- a/drivers/infiniband/hw/hfi1/Kconfig
+++ b/drivers/infiniband/hw/hfi1/Kconfig
@@ -1,9 +1,9 @@
config INFINIBAND_HFI1
tristate "Intel OPA Gen1 support"
- depends on X86_64 && INFINIBAND_RDMAVT
+ depends on X86_64 && INFINIBAND_RDMAVT && I2C
select MMU_NOTIFIER
select CRC32
- default m
+ select I2C_ALGOBIT
---help---
This is a low-level driver for Intel OPA Gen1 adapter.
config HFI1_DEBUG_SDMA_ORDER
diff --git a/drivers/infiniband/hw/hfi1/Makefile b/drivers/infiniband/hw/hfi1/Makefile
index 9b5382c94b0c..0cf97a09b64b 100644
--- a/drivers/infiniband/hw/hfi1/Makefile
+++ b/drivers/infiniband/hw/hfi1/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_INFINIBAND_HFI1) += hfi1.o
hfi1-y := affinity.o chip.o device.o driver.o efivar.o \
eprom.o file_ops.o firmware.o \
init.o intr.o mad.o mmu_rb.o pcie.o pio.o pio_copy.o platform.o \
- qp.o qsfp.o rc.o ruc.o sdma.o sysfs.o trace.o twsi.o \
+ qp.o qsfp.o rc.o ruc.o sdma.o sysfs.o trace.o \
uc.o ud.o user_exp_rcv.o user_pages.o user_sdma.o verbs.o \
verbs_txreq.o
hfi1-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c
index 14d7eeb09be6..79575ee873f2 100644
--- a/drivers/infiniband/hw/hfi1/affinity.c
+++ b/drivers/infiniband/hw/hfi1/affinity.c
@@ -47,12 +47,18 @@
#include <linux/topology.h>
#include <linux/cpumask.h>
#include <linux/module.h>
+#include <linux/cpumask.h>
#include "hfi.h"
#include "affinity.h"
#include "sdma.h"
#include "trace.h"
+struct hfi1_affinity_node_list node_affinity = {
+ .list = LIST_HEAD_INIT(node_affinity.list),
+ .lock = __SPIN_LOCK_UNLOCKED(&node_affinity.lock),
+};
+
/* Name of IRQ types, indexed by enum irq_type */
static const char * const irq_type_names[] = {
"SDMA",
@@ -61,6 +67,9 @@ static const char * const irq_type_names[] = {
"OTHER",
};
+/* Per NUMA node count of HFI devices */
+static unsigned int *hfi1_per_node_cntr;
+
static inline void init_cpu_mask_set(struct cpu_mask_set *set)
{
cpumask_clear(&set->mask);
@@ -69,47 +78,136 @@ static inline void init_cpu_mask_set(struct cpu_mask_set *set)
}
/* Initialize non-HT cpu cores mask */
-int init_real_cpu_mask(struct hfi1_devdata *dd)
+void init_real_cpu_mask(void)
{
- struct hfi1_affinity *info;
int possible, curr_cpu, i, ht;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- cpumask_clear(&info->real_cpu_mask);
+ cpumask_clear(&node_affinity.real_cpu_mask);
/* Start with cpu online mask as the real cpu mask */
- cpumask_copy(&info->real_cpu_mask, cpu_online_mask);
+ cpumask_copy(&node_affinity.real_cpu_mask, cpu_online_mask);
/*
* Remove HT cores from the real cpu mask. Do this in two steps below.
*/
- possible = cpumask_weight(&info->real_cpu_mask);
+ possible = cpumask_weight(&node_affinity.real_cpu_mask);
ht = cpumask_weight(topology_sibling_cpumask(
- cpumask_first(&info->real_cpu_mask)));
+ cpumask_first(&node_affinity.real_cpu_mask)));
/*
* Step 1. Skip over the first N HT siblings and use them as the
* "real" cores. Assumes that HT cores are not enumerated in
* succession (except in the single core case).
*/
- curr_cpu = cpumask_first(&info->real_cpu_mask);
+ curr_cpu = cpumask_first(&node_affinity.real_cpu_mask);
for (i = 0; i < possible / ht; i++)
- curr_cpu = cpumask_next(curr_cpu, &info->real_cpu_mask);
+ curr_cpu = cpumask_next(curr_cpu, &node_affinity.real_cpu_mask);
/*
* Step 2. Remove the remaining HT siblings. Use cpumask_next() to
* skip any gaps.
*/
for (; i < possible; i++) {
- cpumask_clear_cpu(curr_cpu, &info->real_cpu_mask);
- curr_cpu = cpumask_next(curr_cpu, &info->real_cpu_mask);
+ cpumask_clear_cpu(curr_cpu, &node_affinity.real_cpu_mask);
+ curr_cpu = cpumask_next(curr_cpu, &node_affinity.real_cpu_mask);
+ }
+}
+
+int node_affinity_init(void)
+{
+ int node;
+ struct pci_dev *dev = NULL;
+ const struct pci_device_id *ids = hfi1_pci_tbl;
+
+ cpumask_clear(&node_affinity.proc.used);
+ cpumask_copy(&node_affinity.proc.mask, cpu_online_mask);
+
+ node_affinity.proc.gen = 0;
+ node_affinity.num_core_siblings =
+ cpumask_weight(topology_sibling_cpumask(
+ cpumask_first(&node_affinity.proc.mask)
+ ));
+ node_affinity.num_online_nodes = num_online_nodes();
+ node_affinity.num_online_cpus = num_online_cpus();
+
+ /*
+ * The real cpu mask is part of the affinity struct but it has to be
+ * initialized early. It is needed to calculate the number of user
+ * contexts in set_up_context_variables().
+ */
+ init_real_cpu_mask();
+
+ hfi1_per_node_cntr = kcalloc(num_possible_nodes(),
+ sizeof(*hfi1_per_node_cntr), GFP_KERNEL);
+ if (!hfi1_per_node_cntr)
+ return -ENOMEM;
+
+ while (ids->vendor) {
+ dev = NULL;
+ while ((dev = pci_get_device(ids->vendor, ids->device, dev))) {
+ node = pcibus_to_node(dev->bus);
+ if (node < 0)
+ node = numa_node_id();
+
+ hfi1_per_node_cntr[node]++;
+ }
+ ids++;
}
- dd->affinity = info;
return 0;
}
+void node_affinity_destroy(void)
+{
+ struct list_head *pos, *q;
+ struct hfi1_affinity_node *entry;
+
+ spin_lock(&node_affinity.lock);
+ list_for_each_safe(pos, q, &node_affinity.list) {
+ entry = list_entry(pos, struct hfi1_affinity_node,
+ list);
+ list_del(pos);
+ kfree(entry);
+ }
+ spin_unlock(&node_affinity.lock);
+ kfree(hfi1_per_node_cntr);
+}
+
+static struct hfi1_affinity_node *node_affinity_allocate(int node)
+{
+ struct hfi1_affinity_node *entry;
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return NULL;
+ entry->node = node;
+ INIT_LIST_HEAD(&entry->list);
+
+ return entry;
+}
+
+/*
+ * It appends an entry to the list.
+ * It *must* be called with node_affinity.lock held.
+ */
+static void node_affinity_add_tail(struct hfi1_affinity_node *entry)
+{
+ list_add_tail(&entry->list, &node_affinity.list);
+}
+
+/* It must be called with node_affinity.lock held */
+static struct hfi1_affinity_node *node_affinity_lookup(int node)
+{
+ struct list_head *pos;
+ struct hfi1_affinity_node *entry;
+
+ list_for_each(pos, &node_affinity.list) {
+ entry = list_entry(pos, struct hfi1_affinity_node, list);
+ if (entry->node == node)
+ return entry;
+ }
+
+ return NULL;
+}
+
/*
* Interrupt affinity.
*
@@ -121,10 +219,10 @@ int init_real_cpu_mask(struct hfi1_devdata *dd)
* to the node relative 1 as necessary.
*
*/
-void hfi1_dev_affinity_init(struct hfi1_devdata *dd)
+int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
{
int node = pcibus_to_node(dd->pcidev->bus);
- struct hfi1_affinity *info = dd->affinity;
+ struct hfi1_affinity_node *entry;
const struct cpumask *local_mask;
int curr_cpu, possible, i;
@@ -132,56 +230,93 @@ void hfi1_dev_affinity_init(struct hfi1_devdata *dd)
node = numa_node_id();
dd->node = node;
- spin_lock_init(&info->lock);
-
- init_cpu_mask_set(&info->def_intr);
- init_cpu_mask_set(&info->rcv_intr);
- init_cpu_mask_set(&info->proc);
-
local_mask = cpumask_of_node(dd->node);
if (cpumask_first(local_mask) >= nr_cpu_ids)
local_mask = topology_core_cpumask(0);
- /* Use the "real" cpu mask of this node as the default */
- cpumask_and(&info->def_intr.mask, &info->real_cpu_mask, local_mask);
-
- /* fill in the receive list */
- possible = cpumask_weight(&info->def_intr.mask);
- curr_cpu = cpumask_first(&info->def_intr.mask);
- if (possible == 1) {
- /* only one CPU, everyone will use it */
- cpumask_set_cpu(curr_cpu, &info->rcv_intr.mask);
- } else {
- /*
- * Retain the first CPU in the default list for the control
- * context.
- */
- curr_cpu = cpumask_next(curr_cpu, &info->def_intr.mask);
- /*
- * Remove the remaining kernel receive queues from
- * the default list and add them to the receive list.
- */
- for (i = 0; i < dd->n_krcv_queues - 1; i++) {
- cpumask_clear_cpu(curr_cpu, &info->def_intr.mask);
- cpumask_set_cpu(curr_cpu, &info->rcv_intr.mask);
- curr_cpu = cpumask_next(curr_cpu, &info->def_intr.mask);
- if (curr_cpu >= nr_cpu_ids)
- break;
+
+ spin_lock(&node_affinity.lock);
+ entry = node_affinity_lookup(dd->node);
+ spin_unlock(&node_affinity.lock);
+
+ /*
+ * If this is the first time this NUMA node's affinity is used,
+ * create an entry in the global affinity structure and initialize it.
+ */
+ if (!entry) {
+ entry = node_affinity_allocate(node);
+ if (!entry) {
+ dd_dev_err(dd,
+ "Unable to allocate global affinity node\n");
+ return -ENOMEM;
}
- }
+ init_cpu_mask_set(&entry->def_intr);
+ init_cpu_mask_set(&entry->rcv_intr);
+ cpumask_clear(&entry->general_intr_mask);
+ /* Use the "real" cpu mask of this node as the default */
+ cpumask_and(&entry->def_intr.mask, &node_affinity.real_cpu_mask,
+ local_mask);
+
+ /* fill in the receive list */
+ possible = cpumask_weight(&entry->def_intr.mask);
+ curr_cpu = cpumask_first(&entry->def_intr.mask);
+
+ if (possible == 1) {
+ /* only one CPU, everyone will use it */
+ cpumask_set_cpu(curr_cpu, &entry->rcv_intr.mask);
+ cpumask_set_cpu(curr_cpu, &entry->general_intr_mask);
+ } else {
+ /*
+ * The general/control context will be the first CPU in
+ * the default list, so it is removed from the default
+ * list and added to the general interrupt list.
+ */
+ cpumask_clear_cpu(curr_cpu, &entry->def_intr.mask);
+ cpumask_set_cpu(curr_cpu, &entry->general_intr_mask);
+ curr_cpu = cpumask_next(curr_cpu,
+ &entry->def_intr.mask);
- cpumask_copy(&info->proc.mask, cpu_online_mask);
-}
+ /*
+ * Remove the remaining kernel receive queues from
+ * the default list and add them to the receive list.
+ */
+ for (i = 0;
+ i < (dd->n_krcv_queues - 1) *
+ hfi1_per_node_cntr[dd->node];
+ i++) {
+ cpumask_clear_cpu(curr_cpu,
+ &entry->def_intr.mask);
+ cpumask_set_cpu(curr_cpu,
+ &entry->rcv_intr.mask);
+ curr_cpu = cpumask_next(curr_cpu,
+ &entry->def_intr.mask);
+ if (curr_cpu >= nr_cpu_ids)
+ break;
+ }
-void hfi1_dev_affinity_free(struct hfi1_devdata *dd)
-{
- kfree(dd->affinity);
+ /*
+ * If there ends up being 0 CPU cores leftover for SDMA
+ * engines, use the same CPU cores as general/control
+ * context.
+ */
+ if (cpumask_weight(&entry->def_intr.mask) == 0)
+ cpumask_copy(&entry->def_intr.mask,
+ &entry->general_intr_mask);
+ }
+
+ spin_lock(&node_affinity.lock);
+ node_affinity_add_tail(entry);
+ spin_unlock(&node_affinity.lock);
+ }
+
+ return 0;
}
int hfi1_get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix)
{
int ret;
cpumask_var_t diff;
- struct cpu_mask_set *set;
+ struct hfi1_affinity_node *entry;
+ struct cpu_mask_set *set = NULL;
struct sdma_engine *sde = NULL;
struct hfi1_ctxtdata *rcd = NULL;
char extra[64];
@@ -194,22 +329,25 @@ int hfi1_get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix)
if (!ret)
return -ENOMEM;
+ spin_lock(&node_affinity.lock);
+ entry = node_affinity_lookup(dd->node);
+ spin_unlock(&node_affinity.lock);
+
switch (msix->type) {
case IRQ_SDMA:
sde = (struct sdma_engine *)msix->arg;
scnprintf(extra, 64, "engine %u", sde->this_idx);
- /* fall through */
+ set = &entry->def_intr;
+ break;
case IRQ_GENERAL:
- set = &dd->affinity->def_intr;
+ cpu = cpumask_first(&entry->general_intr_mask);
break;
case IRQ_RCVCTXT:
rcd = (struct hfi1_ctxtdata *)msix->arg;
- if (rcd->ctxt == HFI1_CTRL_CTXT) {
- set = &dd->affinity->def_intr;
- cpu = cpumask_first(&set->mask);
- } else {
- set = &dd->affinity->rcv_intr;
- }
+ if (rcd->ctxt == HFI1_CTRL_CTXT)
+ cpu = cpumask_first(&entry->general_intr_mask);
+ else
+ set = &entry->rcv_intr;
scnprintf(extra, 64, "ctxt %u", rcd->ctxt);
break;
default:
@@ -218,12 +356,12 @@ int hfi1_get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix)
}
/*
- * The control receive context is placed on a particular CPU, which
- * is set above. Skip accounting for it. Everything else finds its
- * CPU here.
+ * The general and control contexts are placed on a particular
+ * CPU, which is set above. Skip accounting for it. Everything else
+ * finds its CPU here.
*/
- if (cpu == -1) {
- spin_lock(&dd->affinity->lock);
+ if (cpu == -1 && set) {
+ spin_lock(&node_affinity.lock);
if (cpumask_equal(&set->mask, &set->used)) {
/*
* We've used up all the CPUs, bump up the generation
@@ -235,7 +373,7 @@ int hfi1_get_irq_affinity(struct hfi1_devdata *dd, struct hfi1_msix_entry *msix)
cpumask_andnot(diff, &set->mask, &set->used);
cpu = cpumask_first(diff);
cpumask_set_cpu(cpu, &set->used);
- spin_unlock(&dd->affinity->lock);
+ spin_unlock(&node_affinity.lock);
}
switch (msix->type) {
@@ -263,43 +401,84 @@ void hfi1_put_irq_affinity(struct hfi1_devdata *dd,
{
struct cpu_mask_set *set = NULL;
struct hfi1_ctxtdata *rcd;
+ struct hfi1_affinity_node *entry;
+
+ spin_lock(&node_affinity.lock);
+ entry = node_affinity_lookup(dd->node);
+ spin_unlock(&node_affinity.lock);
switch (msix->type) {
case IRQ_SDMA:
+ set = &entry->def_intr;
+ break;
case IRQ_GENERAL:
- set = &dd->affinity->def_intr;
+ /* Don't do accounting for general contexts */
break;
case IRQ_RCVCTXT:
rcd = (struct hfi1_ctxtdata *)msix->arg;
- /* only do accounting for non control contexts */
+ /* Don't do accounting for control contexts */
if (rcd->ctxt != HFI1_CTRL_CTXT)
- set = &dd->affinity->rcv_intr;
+ set = &entry->rcv_intr;
break;
default:
return;
}
if (set) {
- spin_lock(&dd->affinity->lock);
+ spin_lock(&node_affinity.lock);
cpumask_andnot(&set->used, &set->used, &msix->mask);
if (cpumask_empty(&set->used) && set->gen) {
set->gen--;
cpumask_copy(&set->used, &set->mask);
}
- spin_unlock(&dd->affinity->lock);
+ spin_unlock(&node_affinity.lock);
}
irq_set_affinity_hint(msix->msix.vector, NULL);
cpumask_clear(&msix->mask);
}
-int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
+/* This should be called with node_affinity.lock held */
+static void find_hw_thread_mask(uint hw_thread_no, cpumask_var_t hw_thread_mask,
+ struct hfi1_affinity_node_list *affinity)
{
- int cpu = -1, ret;
- cpumask_var_t diff, mask, intrs;
+ int possible, curr_cpu, i;
+ uint num_cores_per_socket = node_affinity.num_online_cpus /
+ affinity->num_core_siblings /
+ node_affinity.num_online_nodes;
+
+ cpumask_copy(hw_thread_mask, &affinity->proc.mask);
+ if (affinity->num_core_siblings > 0) {
+ /* Removing other siblings not needed for now */
+ possible = cpumask_weight(hw_thread_mask);
+ curr_cpu = cpumask_first(hw_thread_mask);
+ for (i = 0;
+ i < num_cores_per_socket * node_affinity.num_online_nodes;
+ i++)
+ curr_cpu = cpumask_next(curr_cpu, hw_thread_mask);
+
+ for (; i < possible; i++) {
+ cpumask_clear_cpu(curr_cpu, hw_thread_mask);
+ curr_cpu = cpumask_next(curr_cpu, hw_thread_mask);
+ }
+
+ /* Identifying correct HW threads within physical cores */
+ cpumask_shift_left(hw_thread_mask, hw_thread_mask,
+ num_cores_per_socket *
+ node_affinity.num_online_nodes *
+ hw_thread_no);
+ }
+}
+
+int hfi1_get_proc_affinity(int node)
+{
+ int cpu = -1, ret, i;
+ struct hfi1_affinity_node *entry;
+ cpumask_var_t diff, hw_thread_mask, available_mask, intrs_mask;
const struct cpumask *node_mask,
*proc_mask = tsk_cpus_allowed(current);
- struct cpu_mask_set *set = &dd->affinity->proc;
+ struct hfi1_affinity_node_list *affinity = &node_affinity;
+ struct cpu_mask_set *set = &affinity->proc;
/*
* check whether process/context affinity has already
@@ -325,22 +504,41 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
/*
* The process does not have a preset CPU affinity so find one to
- * recommend. We prefer CPUs on the same NUMA as the device.
+ * recommend using the following algorithm:
+ *
+ * For each user process that is opening a context on HFI Y:
+ * a) If all cores are filled, reinitialize the bitmask
+ * b) Fill real cores first, then HT cores (First set of HT
+ * cores on all physical cores, then second set of HT core,
+ * and, so on) in the following order:
+ *
+ * 1. Same NUMA node as HFI Y and not running an IRQ
+ * handler
+ * 2. Same NUMA node as HFI Y and running an IRQ handler
+ * 3. Different NUMA node to HFI Y and not running an IRQ
+ * handler
+ * 4. Different NUMA node to HFI Y and running an IRQ
+ * handler
+ * c) Mark core as filled in the bitmask. As user processes are
+ * done, clear cores from the bitmask.
*/
ret = zalloc_cpumask_var(&diff, GFP_KERNEL);
if (!ret)
goto done;
- ret = zalloc_cpumask_var(&mask, GFP_KERNEL);
+ ret = zalloc_cpumask_var(&hw_thread_mask, GFP_KERNEL);
if (!ret)
goto free_diff;
- ret = zalloc_cpumask_var(&intrs, GFP_KERNEL);
+ ret = zalloc_cpumask_var(&available_mask, GFP_KERNEL);
+ if (!ret)
+ goto free_hw_thread_mask;
+ ret = zalloc_cpumask_var(&intrs_mask, GFP_KERNEL);
if (!ret)
- goto free_mask;
+ goto free_available_mask;
- spin_lock(&dd->affinity->lock);
+ spin_lock(&affinity->lock);
/*
- * If we've used all available CPUs, clear the mask and start
+ * If we've used all available HW threads, clear the mask and start
* overloading.
*/
if (cpumask_equal(&set->mask, &set->used)) {
@@ -348,81 +546,198 @@ int hfi1_get_proc_affinity(struct hfi1_devdata *dd, int node)
cpumask_clear(&set->used);
}
- /* CPUs used by interrupt handlers */
- cpumask_copy(intrs, (dd->affinity->def_intr.gen ?
- &dd->affinity->def_intr.mask :
- &dd->affinity->def_intr.used));
- cpumask_or(intrs, intrs, (dd->affinity->rcv_intr.gen ?
- &dd->affinity->rcv_intr.mask :
- &dd->affinity->rcv_intr.used));
+ /*
+ * If NUMA node has CPUs used by interrupt handlers, include them in the
+ * interrupt handler mask.
+ */
+ entry = node_affinity_lookup(node);
+ if (entry) {
+ cpumask_copy(intrs_mask, (entry->def_intr.gen ?
+ &entry->def_intr.mask :
+ &entry->def_intr.used));
+ cpumask_or(intrs_mask, intrs_mask, (entry->rcv_intr.gen ?
+ &entry->rcv_intr.mask :
+ &entry->rcv_intr.used));
+ cpumask_or(intrs_mask, intrs_mask, &entry->general_intr_mask);
+ }
hfi1_cdbg(PROC, "CPUs used by interrupts: %*pbl",
- cpumask_pr_args(intrs));
+ cpumask_pr_args(intrs_mask));
+
+ cpumask_copy(hw_thread_mask, &set->mask);
/*
- * If we don't have a NUMA node requested, preference is towards
- * device NUMA node
+ * If HT cores are enabled, identify which HW threads within the
+ * physical cores should be used.
*/
- if (node == -1)
- node = dd->node;
+ if (affinity->num_core_siblings > 0) {
+ for (i = 0; i < affinity->num_core_siblings; i++) {
+ find_hw_thread_mask(i, hw_thread_mask, affinity);
+
+ /*
+ * If there's at least one available core for this HW
+ * thread number, stop looking for a core.
+ *
+ * diff will always be not empty at least once in this
+ * loop as the used mask gets reset when
+ * (set->mask == set->used) before this loop.
+ */
+ cpumask_andnot(diff, hw_thread_mask, &set->used);
+ if (!cpumask_empty(diff))
+ break;
+ }
+ }
+ hfi1_cdbg(PROC, "Same available HW thread on all physical CPUs: %*pbl",
+ cpumask_pr_args(hw_thread_mask));
+
node_mask = cpumask_of_node(node);
- hfi1_cdbg(PROC, "device on NUMA %u, CPUs %*pbl", node,
+ hfi1_cdbg(PROC, "Device on NUMA %u, CPUs %*pbl", node,
cpumask_pr_args(node_mask));
- /* diff will hold all unused cpus */
- cpumask_andnot(diff, &set->mask, &set->used);
- hfi1_cdbg(PROC, "unused CPUs (all) %*pbl", cpumask_pr_args(diff));
-
- /* get cpumask of available CPUs on preferred NUMA */
- cpumask_and(mask, diff, node_mask);
- hfi1_cdbg(PROC, "available cpus on NUMA %*pbl", cpumask_pr_args(mask));
+ /* Get cpumask of available CPUs on preferred NUMA */
+ cpumask_and(available_mask, hw_thread_mask, node_mask);
+ cpumask_andnot(available_mask, available_mask, &set->used);
+ hfi1_cdbg(PROC, "Available CPUs on NUMA %u: %*pbl", node,
+ cpumask_pr_args(available_mask));
/*
* At first, we don't want to place processes on the same
- * CPUs as interrupt handlers.
+ * CPUs as interrupt handlers. Then, CPUs running interrupt
+ * handlers are used.
+ *
+ * 1) If diff is not empty, then there are CPUs not running
+ * non-interrupt handlers available, so diff gets copied
+ * over to available_mask.
+ * 2) If diff is empty, then all CPUs not running interrupt
+ * handlers are taken, so available_mask contains all
+ * available CPUs running interrupt handlers.
+ * 3) If available_mask is empty, then all CPUs on the
+ * preferred NUMA node are taken, so other NUMA nodes are
+ * used for process assignments using the same method as
+ * the preferred NUMA node.
*/
- cpumask_andnot(diff, mask, intrs);
+ cpumask_andnot(diff, available_mask, intrs_mask);
if (!cpumask_empty(diff))
- cpumask_copy(mask, diff);
+ cpumask_copy(available_mask, diff);
- /*
- * if we don't have a cpu on the preferred NUMA, get
- * the list of the remaining available CPUs
- */
- if (cpumask_empty(mask)) {
- cpumask_andnot(diff, &set->mask, &set->used);
- cpumask_andnot(mask, diff, node_mask);
+ /* If we don't have CPUs on the preferred node, use other NUMA nodes */
+ if (cpumask_empty(available_mask)) {
+ cpumask_andnot(available_mask, hw_thread_mask, &set->used);
+ /* Excluding preferred NUMA cores */
+ cpumask_andnot(available_mask, available_mask, node_mask);
+ hfi1_cdbg(PROC,
+ "Preferred NUMA node cores are taken, cores available in other NUMA nodes: %*pbl",
+ cpumask_pr_args(available_mask));
+
+ /*
+ * At first, we don't want to place processes on the same
+ * CPUs as interrupt handlers.
+ */
+ cpumask_andnot(diff, available_mask, intrs_mask);
+ if (!cpumask_empty(diff))
+ cpumask_copy(available_mask, diff);
}
- hfi1_cdbg(PROC, "possible CPUs for process %*pbl",
- cpumask_pr_args(mask));
+ hfi1_cdbg(PROC, "Possible CPUs for process: %*pbl",
+ cpumask_pr_args(available_mask));
- cpu = cpumask_first(mask);
+ cpu = cpumask_first(available_mask);
if (cpu >= nr_cpu_ids) /* empty */
cpu = -1;
else
cpumask_set_cpu(cpu, &set->used);
- spin_unlock(&dd->affinity->lock);
-
- free_cpumask_var(intrs);
-free_mask:
- free_cpumask_var(mask);
+ spin_unlock(&affinity->lock);
+ hfi1_cdbg(PROC, "Process assigned to CPU %d", cpu);
+
+ free_cpumask_var(intrs_mask);
+free_available_mask:
+ free_cpumask_var(available_mask);
+free_hw_thread_mask:
+ free_cpumask_var(hw_thread_mask);
free_diff:
free_cpumask_var(diff);
done:
return cpu;
}
-void hfi1_put_proc_affinity(struct hfi1_devdata *dd, int cpu)
+void hfi1_put_proc_affinity(int cpu)
{
- struct cpu_mask_set *set = &dd->affinity->proc;
+ struct hfi1_affinity_node_list *affinity = &node_affinity;
+ struct cpu_mask_set *set = &affinity->proc;
if (cpu < 0)
return;
- spin_lock(&dd->affinity->lock);
+ spin_lock(&affinity->lock);
cpumask_clear_cpu(cpu, &set->used);
+ hfi1_cdbg(PROC, "Returning CPU %d for future process assignment", cpu);
if (cpumask_empty(&set->used) && set->gen) {
set->gen--;
cpumask_copy(&set->used, &set->mask);
}
- spin_unlock(&dd->affinity->lock);
+ spin_unlock(&affinity->lock);
}
+/* Prevents concurrent reads and writes of the sdma_affinity attrib */
+static DEFINE_MUTEX(sdma_affinity_mutex);
+
+int hfi1_set_sdma_affinity(struct hfi1_devdata *dd, const char *buf,
+ size_t count)
+{
+ struct hfi1_affinity_node *entry;
+ struct cpumask mask;
+ int ret, i;
+
+ spin_lock(&node_affinity.lock);
+ entry = node_affinity_lookup(dd->node);
+ spin_unlock(&node_affinity.lock);
+
+ if (!entry)
+ return -EINVAL;
+
+ ret = cpulist_parse(buf, &mask);
+ if (ret)
+ return ret;
+
+ if (!cpumask_subset(&mask, cpu_online_mask) || cpumask_empty(&mask)) {
+ dd_dev_warn(dd, "Invalid CPU mask\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&sdma_affinity_mutex);
+ /* reset the SDMA interrupt affinity details */
+ init_cpu_mask_set(&entry->def_intr);
+ cpumask_copy(&entry->def_intr.mask, &mask);
+ /*
+ * Reassign the affinity for each SDMA interrupt.
+ */
+ for (i = 0; i < dd->num_msix_entries; i++) {
+ struct hfi1_msix_entry *msix;
+
+ msix = &dd->msix_entries[i];
+ if (msix->type != IRQ_SDMA)
+ continue;
+
+ ret = hfi1_get_irq_affinity(dd, msix);
+
+ if (ret)
+ break;
+ }
+
+ mutex_unlock(&sdma_affinity_mutex);
+ return ret ? ret : strnlen(buf, PAGE_SIZE);
+}
+
+int hfi1_get_sdma_affinity(struct hfi1_devdata *dd, char *buf)
+{
+ struct hfi1_affinity_node *entry;
+
+ spin_lock(&node_affinity.lock);
+ entry = node_affinity_lookup(dd->node);
+ spin_unlock(&node_affinity.lock);
+
+ if (!entry)
+ return -EINVAL;
+
+ mutex_lock(&sdma_affinity_mutex);
+ cpumap_print_to_pagebuf(true, buf, &entry->def_intr.mask);
+ mutex_unlock(&sdma_affinity_mutex);
+ return strnlen(buf, PAGE_SIZE);
+}
diff --git a/drivers/infiniband/hw/hfi1/affinity.h b/drivers/infiniband/hw/hfi1/affinity.h
index 20f52fe74091..8879cf7a8cac 100644
--- a/drivers/infiniband/hw/hfi1/affinity.h
+++ b/drivers/infiniband/hw/hfi1/affinity.h
@@ -73,7 +73,6 @@ struct cpu_mask_set {
struct hfi1_affinity {
struct cpu_mask_set def_intr;
struct cpu_mask_set rcv_intr;
- struct cpu_mask_set proc;
struct cpumask real_cpu_mask;
/* spin lock to protect affinity struct */
spinlock_t lock;
@@ -82,11 +81,9 @@ struct hfi1_affinity {
struct hfi1_msix_entry;
/* Initialize non-HT cpu cores mask */
-int init_real_cpu_mask(struct hfi1_devdata *);
+void init_real_cpu_mask(void);
/* Initialize driver affinity data */
-void hfi1_dev_affinity_init(struct hfi1_devdata *);
-/* Free driver affinity data */
-void hfi1_dev_affinity_free(struct hfi1_devdata *);
+int hfi1_dev_affinity_init(struct hfi1_devdata *);
/*
* Set IRQ affinity to a CPU. The function will determine the
* CPU and set the affinity to it.
@@ -101,8 +98,35 @@ void hfi1_put_irq_affinity(struct hfi1_devdata *, struct hfi1_msix_entry *);
* Determine a CPU affinity for a user process, if the process does not
* have an affinity set yet.
*/
-int hfi1_get_proc_affinity(struct hfi1_devdata *, int);
+int hfi1_get_proc_affinity(int);
/* Release a CPU used by a user process. */
-void hfi1_put_proc_affinity(struct hfi1_devdata *, int);
+void hfi1_put_proc_affinity(int);
+
+int hfi1_get_sdma_affinity(struct hfi1_devdata *dd, char *buf);
+int hfi1_set_sdma_affinity(struct hfi1_devdata *dd, const char *buf,
+ size_t count);
+
+struct hfi1_affinity_node {
+ int node;
+ struct cpu_mask_set def_intr;
+ struct cpu_mask_set rcv_intr;
+ struct cpumask general_intr_mask;
+ struct list_head list;
+};
+
+struct hfi1_affinity_node_list {
+ struct list_head list;
+ struct cpumask real_cpu_mask;
+ struct cpu_mask_set proc;
+ int num_core_siblings;
+ int num_online_nodes;
+ int num_online_cpus;
+ /* protect affinity node list */
+ spinlock_t lock;
+};
+
+int node_affinity_init(void);
+void node_affinity_destroy(void);
+extern struct hfi1_affinity_node_list node_affinity;
#endif /* _HFI1_AFFINITY_H */
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index dad4d0ebbdff..b32638d58ae8 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -63,6 +63,7 @@
#include "efivar.h"
#include "platform.h"
#include "aspm.h"
+#include "affinity.h"
#define NUM_IB_PORTS 1
@@ -121,6 +122,7 @@ struct flag_table {
#define SEC_SC_HALTED 0x4 /* per-context only */
#define SEC_SPC_FREEZE 0x8 /* per-HFI only */
+#define DEFAULT_KRCVQS 2
#define MIN_KERNEL_KCTXTS 2
#define FIRST_KERNEL_KCTXT 1
/* sizes for both the QP and RSM map tables */
@@ -238,6 +240,9 @@ struct flag_table {
/* all CceStatus sub-block RXE pause bits */
#define ALL_RXE_PAUSE CCE_STATUS_RXE_PAUSED_SMASK
+#define CNTR_MAX 0xFFFFFFFFFFFFFFFFULL
+#define CNTR_32BIT_MAX 0x00000000FFFFFFFF
+
/*
* CCE Error flags.
*/
@@ -3947,6 +3952,28 @@ static u64 access_sdma_wrong_dw_err_cnt(const struct cntr_entry *entry,
return dd->sw_send_dma_eng_err_status_cnt[0];
}
+static u64 access_dc_rcv_err_cnt(const struct cntr_entry *entry,
+ void *context, int vl, int mode,
+ u64 data)
+{
+ struct hfi1_devdata *dd = (struct hfi1_devdata *)context;
+
+ u64 val = 0;
+ u64 csr = entry->csr;
+
+ val = read_write_csr(dd, csr, mode, data);
+ if (mode == CNTR_MODE_R) {
+ val = val > CNTR_MAX - dd->sw_rcv_bypass_packet_errors ?
+ CNTR_MAX : val + dd->sw_rcv_bypass_packet_errors;
+ } else if (mode == CNTR_MODE_W) {
+ dd->sw_rcv_bypass_packet_errors = 0;
+ } else {
+ dd_dev_err(dd, "Invalid cntr register access mode");
+ return 0;
+ }
+ return val;
+}
+
#define def_access_sw_cpu(cntr) \
static u64 access_sw_cpu_##cntr(const struct cntr_entry *entry, \
void *context, int vl, int mode, u64 data) \
@@ -4020,7 +4047,8 @@ static struct cntr_entry dev_cntrs[DEV_CNTR_LAST] = {
CCE_SEND_CREDIT_INT_CNT, CNTR_NORMAL),
[C_DC_UNC_ERR] = DC_PERF_CNTR(DcUnctblErr, DCC_ERR_UNCORRECTABLE_CNT,
CNTR_SYNTH),
-[C_DC_RCV_ERR] = DC_PERF_CNTR(DcRecvErr, DCC_ERR_PORTRCV_ERR_CNT, CNTR_SYNTH),
+[C_DC_RCV_ERR] = CNTR_ELEM("DcRecvErr", DCC_ERR_PORTRCV_ERR_CNT, 0, CNTR_SYNTH,
+ access_dc_rcv_err_cnt),
[C_DC_FM_CFG_ERR] = DC_PERF_CNTR(DcFmCfgErr, DCC_ERR_FMCONFIG_ERR_CNT,
CNTR_SYNTH),
[C_DC_RMT_PHY_ERR] = DC_PERF_CNTR(DcRmtPhyErr, DCC_ERR_RCVREMOTE_PHY_ERR_CNT,
@@ -8798,30 +8826,6 @@ static int write_tx_settings(struct hfi1_devdata *dd,
return load_8051_config(dd, TX_SETTINGS, GENERAL_CONFIG, frame);
}
-static void check_fabric_firmware_versions(struct hfi1_devdata *dd)
-{
- u32 frame, version, prod_id;
- int ret, lane;
-
- /* 4 lanes */
- for (lane = 0; lane < 4; lane++) {
- ret = read_8051_config(dd, SPICO_FW_VERSION, lane, &frame);
- if (ret) {
- dd_dev_err(dd,
- "Unable to read lane %d firmware details\n",
- lane);
- continue;
- }
- version = (frame >> SPICO_ROM_VERSION_SHIFT)
- & SPICO_ROM_VERSION_MASK;
- prod_id = (frame >> SPICO_ROM_PROD_ID_SHIFT)
- & SPICO_ROM_PROD_ID_MASK;
- dd_dev_info(dd,
- "Lane %d firmware: version 0x%04x, prod_id 0x%04x\n",
- lane, version, prod_id);
- }
-}
-
/*
* Read an idle LCB message.
*
@@ -9187,17 +9191,24 @@ static void wait_for_qsfp_init(struct hfi1_pportdata *ppd)
unsigned long timeout;
/*
- * Check for QSFP interrupt for t_init (SFF 8679)
+ * Some QSFP cables have a quirk that asserts the IntN line as a side
+ * effect of power up on plug-in. We ignore this false positive
+ * interrupt until the module has finished powering up by waiting for
+ * a minimum timeout of the module inrush initialization time of
+ * 500 ms (SFF 8679 Table 5-6) to ensure the voltage rails in the
+ * module have stabilized.
+ */
+ msleep(500);
+
+ /*
+ * Check for QSFP interrupt for t_init (SFF 8679 Table 8-1)
*/
timeout = jiffies + msecs_to_jiffies(2000);
while (1) {
mask = read_csr(dd, dd->hfi1_id ?
ASIC_QSFP2_IN : ASIC_QSFP1_IN);
- if (!(mask & QSFP_HFI0_INT_N)) {
- write_csr(dd, dd->hfi1_id ? ASIC_QSFP2_CLEAR :
- ASIC_QSFP1_CLEAR, QSFP_HFI0_INT_N);
+ if (!(mask & QSFP_HFI0_INT_N))
break;
- }
if (time_after(jiffies, timeout)) {
dd_dev_info(dd, "%s: No IntN detected, reset complete\n",
__func__);
@@ -9213,10 +9224,17 @@ static void set_qsfp_int_n(struct hfi1_pportdata *ppd, u8 enable)
u64 mask;
mask = read_csr(dd, dd->hfi1_id ? ASIC_QSFP2_MASK : ASIC_QSFP1_MASK);
- if (enable)
+ if (enable) {
+ /*
+ * Clear the status register to avoid an immediate interrupt
+ * when we re-enable the IntN pin
+ */
+ write_csr(dd, dd->hfi1_id ? ASIC_QSFP2_CLEAR : ASIC_QSFP1_CLEAR,
+ QSFP_HFI0_INT_N);
mask |= (u64)QSFP_HFI0_INT_N;
- else
+ } else {
mask &= ~(u64)QSFP_HFI0_INT_N;
+ }
write_csr(dd, dd->hfi1_id ? ASIC_QSFP2_MASK : ASIC_QSFP1_MASK, mask);
}
@@ -9630,14 +9648,6 @@ void hfi1_clear_tids(struct hfi1_ctxtdata *rcd)
hfi1_put_tid(dd, i, PT_INVALID, 0, 0);
}
-int hfi1_get_base_kinfo(struct hfi1_ctxtdata *rcd,
- struct hfi1_ctxt_info *kinfo)
-{
- kinfo->runtime_flags = (HFI1_MISC_GET() << HFI1_CAP_USER_SHIFT) |
- HFI1_CAP_UGET(MASK) | HFI1_CAP_KGET(K2U);
- return 0;
-}
-
struct hfi1_message_header *hfi1_get_msgheader(
struct hfi1_devdata *dd, __le32 *rhf_addr)
{
@@ -9890,6 +9900,131 @@ static int wait_phy_linkstate(struct hfi1_devdata *dd, u32 state, u32 msecs)
return 0;
}
+static const char *state_completed_string(u32 completed)
+{
+ static const char * const state_completed[] = {
+ "EstablishComm",
+ "OptimizeEQ",
+ "VerifyCap"
+ };
+
+ if (completed < ARRAY_SIZE(state_completed))
+ return state_completed[completed];
+
+ return "unknown";
+}
+
+static const char all_lanes_dead_timeout_expired[] =
+ "All lanes were inactive – was the interconnect media removed?";
+static const char tx_out_of_policy[] =
+ "Passing lanes on local port do not meet the local link width policy";
+static const char no_state_complete[] =
+ "State timeout occurred before link partner completed the state";
+static const char * const state_complete_reasons[] = {
+ [0x00] = "Reason unknown",
+ [0x01] = "Link was halted by driver, refer to LinkDownReason",
+ [0x02] = "Link partner reported failure",
+ [0x10] = "Unable to achieve frame sync on any lane",
+ [0x11] =
+ "Unable to find a common bit rate with the link partner",
+ [0x12] =
+ "Unable to achieve frame sync on sufficient lanes to meet the local link width policy",
+ [0x13] =
+ "Unable to identify preset equalization on sufficient lanes to meet the local link width policy",
+ [0x14] = no_state_complete,
+ [0x15] =
+ "State timeout occurred before link partner identified equalization presets",
+ [0x16] =
+ "Link partner completed the EstablishComm state, but the passing lanes do not meet the local link width policy",
+ [0x17] = tx_out_of_policy,
+ [0x20] = all_lanes_dead_timeout_expired,
+ [0x21] =
+ "Unable to achieve acceptable BER on sufficient lanes to meet the local link width policy",
+ [0x22] = no_state_complete,
+ [0x23] =
+ "Link partner completed the OptimizeEq state, but the passing lanes do not meet the local link width policy",
+ [0x24] = tx_out_of_policy,
+ [0x30] = all_lanes_dead_timeout_expired,
+ [0x31] =
+ "State timeout occurred waiting for host to process received frames",
+ [0x32] = no_state_complete,
+ [0x33] =
+ "Link partner completed the VerifyCap state, but the passing lanes do not meet the local link width policy",
+ [0x34] = tx_out_of_policy,
+};
+
+static const char *state_complete_reason_code_string(struct hfi1_pportdata *ppd,
+ u32 code)
+{
+ const char *str = NULL;
+
+ if (code < ARRAY_SIZE(state_complete_reasons))
+ str = state_complete_reasons[code];
+
+ if (str)
+ return str;
+ return "Reserved";
+}
+
+/* describe the given last state complete frame */
+static void decode_state_complete(struct hfi1_pportdata *ppd, u32 frame,
+ const char *prefix)
+{
+ struct hfi1_devdata *dd = ppd->dd;
+ u32 success;
+ u32 state;
+ u32 reason;
+ u32 lanes;
+
+ /*
+ * Decode frame:
+ * [ 0: 0] - success
+ * [ 3: 1] - state
+ * [ 7: 4] - next state timeout
+ * [15: 8] - reason code
+ * [31:16] - lanes
+ */
+ success = frame & 0x1;
+ state = (frame >> 1) & 0x7;
+ reason = (frame >> 8) & 0xff;
+ lanes = (frame >> 16) & 0xffff;
+
+ dd_dev_err(dd, "Last %s LNI state complete frame 0x%08x:\n",
+ prefix, frame);
+ dd_dev_err(dd, " last reported state state: %s (0x%x)\n",
+ state_completed_string(state), state);
+ dd_dev_err(dd, " state successfully completed: %s\n",
+ success ? "yes" : "no");
+ dd_dev_err(dd, " fail reason 0x%x: %s\n",
+ reason, state_complete_reason_code_string(ppd, reason));
+ dd_dev_err(dd, " passing lane mask: 0x%x", lanes);
+}
+
+/*
+ * Read the last state complete frames and explain them. This routine
+ * expects to be called if the link went down during link negotiation
+ * and initialization (LNI). That is, anywhere between polling and link up.
+ */
+static void check_lni_states(struct hfi1_pportdata *ppd)
+{
+ u32 last_local_state;
+ u32 last_remote_state;
+
+ read_last_local_state(ppd->dd, &last_local_state);
+ read_last_remote_state(ppd->dd, &last_remote_state);
+
+ /*
+ * Don't report anything if there is nothing to report. A value of
+ * 0 means the link was taken down while polling and there was no
+ * training in-process.
+ */
+ if (last_local_state == 0 && last_remote_state == 0)
+ return;
+
+ decode_state_complete(ppd, last_local_state, "transmitted");
+ decode_state_complete(ppd, last_remote_state, "received");
+}
+
/*
* Helper for set_link_state(). Do not call except from that routine.
* Expects ppd->hls_mutex to be held.
@@ -9902,8 +10037,6 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
{
struct hfi1_devdata *dd = ppd->dd;
u32 pstate, previous_state;
- u32 last_local_state;
- u32 last_remote_state;
int ret;
int do_transition;
int do_wait;
@@ -10003,12 +10136,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
} else if (previous_state
& (HLS_DN_POLL | HLS_VERIFY_CAP | HLS_GOING_UP)) {
/* went down while attempting link up */
- /* byte 1 of last_*_state is the failure reason */
- read_last_local_state(dd, &last_local_state);
- read_last_remote_state(dd, &last_remote_state);
- dd_dev_err(dd,
- "LNI failure last states: local 0x%08x, remote 0x%08x\n",
- last_local_state, last_remote_state);
+ check_lni_states(ppd);
}
/* the active link width (downgrade) is 0 on link down */
@@ -11668,9 +11796,6 @@ static void free_cntrs(struct hfi1_devdata *dd)
dd->cntrnames = NULL;
}
-#define CNTR_MAX 0xFFFFFFFFFFFFFFFFULL
-#define CNTR_32BIT_MAX 0x00000000FFFFFFFF
-
static u64 read_dev_port_cntr(struct hfi1_devdata *dd, struct cntr_entry *entry,
u64 *psval, void *context, int vl)
{
@@ -12325,37 +12450,6 @@ u8 hfi1_ibphys_portstate(struct hfi1_pportdata *ppd)
return ib_pstate;
}
-/*
- * Read/modify/write ASIC_QSFP register bits as selected by mask
- * data: 0 or 1 in the positions depending on what needs to be written
- * dir: 0 for read, 1 for write
- * mask: select by setting
- * I2CCLK (bit 0)
- * I2CDATA (bit 1)
- */
-u64 hfi1_gpio_mod(struct hfi1_devdata *dd, u32 target, u32 data, u32 dir,
- u32 mask)
-{
- u64 qsfp_oe, target_oe;
-
- target_oe = target ? ASIC_QSFP2_OE : ASIC_QSFP1_OE;
- if (mask) {
- /* We are writing register bits, so lock access */
- dir &= mask;
- data &= mask;
-
- qsfp_oe = read_csr(dd, target_oe);
- qsfp_oe = (qsfp_oe & ~(u64)mask) | (u64)dir;
- write_csr(dd, target_oe, qsfp_oe);
- }
- /* We are exclusively reading bits here, but it is unlikely
- * we'll get valid data when we set the direction of the pin
- * in the same call, so read should call this function again
- * to get valid data
- */
- return read_csr(dd, target ? ASIC_QSFP2_IN : ASIC_QSFP1_IN);
-}
-
#define CLEAR_STATIC_RATE_CONTROL_SMASK(r) \
(r &= ~SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_STATIC_RATE_CONTROL_SMASK)
@@ -12780,7 +12874,6 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
/*
* Kernel receive contexts:
- * - min of 2 or 1 context/numa (excluding control context)
* - Context 0 - control context (VL15/multicast/error)
* - Context 1 - first kernel context
* - Context 2 - second kernel context
@@ -12794,9 +12887,7 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
*/
num_kernel_contexts = n_krcvqs + 1;
else
- num_kernel_contexts = num_online_nodes() + 1;
- num_kernel_contexts =
- max_t(int, MIN_KERNEL_KCTXTS, num_kernel_contexts);
+ num_kernel_contexts = DEFAULT_KRCVQS + 1;
/*
* Every kernel receive context needs an ACK send context.
* one send context is allocated for each VL{0-7} and VL15
@@ -12815,7 +12906,7 @@ static int set_up_context_variables(struct hfi1_devdata *dd)
*/
if (num_user_contexts < 0)
num_user_contexts =
- cpumask_weight(&dd->affinity->real_cpu_mask);
+ cpumask_weight(&node_affinity.real_cpu_mask);
total_contexts = num_kernel_contexts + num_user_contexts;
@@ -14141,6 +14232,11 @@ static int init_asic_data(struct hfi1_devdata *dd)
}
dd->asic_data->dds[dd->hfi1_id] = dd; /* self back-pointer */
spin_unlock_irqrestore(&hfi1_devs_lock, flags);
+
+ /* first one through - set up i2c devices */
+ if (!peer)
+ ret = set_up_i2c(dd, dd->asic_data);
+
return ret;
}
@@ -14445,19 +14541,6 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
(dd->revision >> CCE_REVISION_SW_SHIFT)
& CCE_REVISION_SW_MASK);
- /*
- * The real cpu mask is part of the affinity struct but has to be
- * initialized earlier than the rest of the affinity struct because it
- * is needed to calculate the number of user contexts in
- * set_up_context_variables(). However, hfi1_dev_affinity_init(),
- * which initializes the rest of the affinity struct members,
- * depends on set_up_context_variables() for the number of kernel
- * contexts, so it cannot be called before set_up_context_variables().
- */
- ret = init_real_cpu_mask(dd);
- if (ret)
- goto bail_cleanup;
-
ret = set_up_context_variables(dd);
if (ret)
goto bail_cleanup;
@@ -14471,7 +14554,9 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
/* set up KDETH QP prefix in both RX and TX CSRs */
init_kdeth_qp(dd);
- hfi1_dev_affinity_init(dd);
+ ret = hfi1_dev_affinity_init(dd);
+ if (ret)
+ goto bail_cleanup;
/* send contexts must be set up before receive contexts */
ret = init_send_contexts(dd);
@@ -14508,8 +14593,14 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
/* set up LCB access - must be after set_up_interrupts() */
init_lcb_access(dd);
+ /*
+ * Serial number is created from the base guid:
+ * [27:24] = base guid [38:35]
+ * [23: 0] = base guid [23: 0]
+ */
snprintf(dd->serial, SERIAL_MAX, "0x%08llx\n",
- dd->base_guid & 0xFFFFFF);
+ (dd->base_guid & 0xFFFFFF) |
+ ((dd->base_guid >> 11) & 0xF000000));
dd->oui1 = dd->base_guid >> 56 & 0xFF;
dd->oui2 = dd->base_guid >> 48 & 0xFF;
@@ -14518,7 +14609,6 @@ struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
ret = load_firmware(dd); /* asymmetric with dispose_firmware() */
if (ret)
goto bail_clear_intr;
- check_fabric_firmware_versions(dd);
thermal_init(dd);
diff --git a/drivers/infiniband/hw/hfi1/chip.h b/drivers/infiniband/hw/hfi1/chip.h
index 66a327978739..ed11107c50fe 100644
--- a/drivers/infiniband/hw/hfi1/chip.h
+++ b/drivers/infiniband/hw/hfi1/chip.h
@@ -640,6 +640,7 @@ extern uint platform_config_load;
/* SBus commands */
#define RESET_SBUS_RECEIVER 0x20
#define WRITE_SBUS_RECEIVER 0x21
+#define READ_SBUS_RECEIVER 0x22
void sbus_request(struct hfi1_devdata *dd,
u8 receiver_addr, u8 data_addr, u8 command, u32 data_in);
int sbus_request_slow(struct hfi1_devdata *dd,
@@ -1336,10 +1337,6 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd);
void hfi1_clear_tids(struct hfi1_ctxtdata *rcd);
struct hfi1_message_header *hfi1_get_msgheader(
struct hfi1_devdata *dd, __le32 *rhf_addr);
-int hfi1_get_base_kinfo(struct hfi1_ctxtdata *rcd,
- struct hfi1_ctxt_info *kinfo);
-u64 hfi1_gpio_mod(struct hfi1_devdata *dd, u32 target, u32 data, u32 dir,
- u32 mask);
int hfi1_init_ctxt(struct send_context *sc);
void hfi1_put_tid(struct hfi1_devdata *dd, u32 index,
u32 type, unsigned long pa, u16 order);
diff --git a/drivers/infiniband/hw/hfi1/chip_registers.h b/drivers/infiniband/hw/hfi1/chip_registers.h
index 8744de6667c2..5b9993899789 100644
--- a/drivers/infiniband/hw/hfi1/chip_registers.h
+++ b/drivers/infiniband/hw/hfi1/chip_registers.h
@@ -471,6 +471,10 @@
#define ASIC_STS_SBUS_RESULT (ASIC + 0x000000000010)
#define ASIC_STS_SBUS_RESULT_DONE_SMASK 0x1ull
#define ASIC_STS_SBUS_RESULT_RCV_DATA_VALID_SMASK 0x2ull
+#define ASIC_STS_SBUS_RESULT_RESULT_CODE_SHIFT 2
+#define ASIC_STS_SBUS_RESULT_RESULT_CODE_MASK 0x7ull
+#define ASIC_STS_SBUS_RESULT_DATA_OUT_SHIFT 32
+#define ASIC_STS_SBUS_RESULT_DATA_OUT_MASK 0xFFFFFFFFull
#define ASIC_STS_THERM (ASIC + 0x000000000058)
#define ASIC_STS_THERM_CRIT_TEMP_MASK 0x7FFull
#define ASIC_STS_THERM_CRIT_TEMP_SHIFT 18
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
index c75b0ae688f8..8246dc7d0573 100644
--- a/drivers/infiniband/hw/hfi1/driver.c
+++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -392,9 +392,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
u16 rlid;
u8 svc_type, sl, sc5;
- sc5 = (be16_to_cpu(rhdr->lrh[0]) >> 12) & 0xf;
- if (rhf_dc_info(packet->rhf))
- sc5 |= 0x10;
+ sc5 = hdr2sc(rhdr, packet->rhf);
sl = ibp->sc_to_sl[sc5];
lqpn = be32_to_cpu(bth[1]) & RVT_QPN_MASK;
@@ -450,14 +448,20 @@ static inline void init_packet(struct hfi1_ctxtdata *rcd,
packet->rcv_flags = 0;
}
-static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr,
- struct hfi1_other_headers *ohdr,
- u64 rhf, u32 bth1, struct ib_grh *grh)
+void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
+ bool do_cnp)
{
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- u32 rqpn = 0;
- u16 rlid;
- u8 sc5, svc_type;
+ struct hfi1_ib_header *hdr = pkt->hdr;
+ struct hfi1_other_headers *ohdr = pkt->ohdr;
+ struct ib_grh *grh = NULL;
+ u32 rqpn = 0, bth1;
+ u16 rlid, dlid = be16_to_cpu(hdr->lrh[1]);
+ u8 sc, svc_type;
+ bool is_mcast = false;
+
+ if (pkt->rcv_flags & HFI1_HAS_GRH)
+ grh = &hdr->u.l.grh;
switch (qp->ibqp.qp_type) {
case IB_QPT_SMI:
@@ -466,6 +470,8 @@ static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr,
rlid = be16_to_cpu(hdr->lrh[3]);
rqpn = be32_to_cpu(ohdr->u.ud.deth[1]) & RVT_QPN_MASK;
svc_type = IB_CC_SVCTYPE_UD;
+ is_mcast = (dlid > be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
+ (dlid != be16_to_cpu(IB_LID_PERMISSIVE));
break;
case IB_QPT_UC:
rlid = qp->remote_ah_attr.dlid;
@@ -481,24 +487,23 @@ static void process_ecn(struct rvt_qp *qp, struct hfi1_ib_header *hdr,
return;
}
- sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
- if (rhf_dc_info(rhf))
- sc5 |= 0x10;
+ sc = hdr2sc((struct hfi1_message_header *)hdr, pkt->rhf);
- if (bth1 & HFI1_FECN_SMASK) {
+ bth1 = be32_to_cpu(ohdr->bth[1]);
+ if (do_cnp && (bth1 & HFI1_FECN_SMASK)) {
u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
- u16 dlid = be16_to_cpu(hdr->lrh[1]);
- return_cnp(ibp, qp, rqpn, pkey, dlid, rlid, sc5, grh);
+ return_cnp(ibp, qp, rqpn, pkey, dlid, rlid, sc, grh);
}
- if (bth1 & HFI1_BECN_SMASK) {
+ if (!is_mcast && (bth1 & HFI1_BECN_SMASK)) {
struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
u32 lqpn = bth1 & RVT_QPN_MASK;
- u8 sl = ibp->sc_to_sl[sc5];
+ u8 sl = ibp->sc_to_sl[sc];
process_becn(ppd, sl, rlid, lqpn, rqpn, svc_type);
}
+
}
struct ps_mdata {
@@ -596,7 +601,6 @@ static void __prescan_rxq(struct hfi1_packet *packet)
struct rvt_qp *qp;
struct hfi1_ib_header *hdr;
struct hfi1_other_headers *ohdr;
- struct ib_grh *grh = NULL;
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
u64 rhf = rhf_to_cpu(rhf_addr);
u32 etype = rhf_rcv_type(rhf), qpn, bth1;
@@ -616,14 +620,13 @@ static void __prescan_rxq(struct hfi1_packet *packet)
hfi1_get_msgheader(dd, rhf_addr);
lnh = be16_to_cpu(hdr->lrh[0]) & 3;
- if (lnh == HFI1_LRH_BTH) {
+ if (lnh == HFI1_LRH_BTH)
ohdr = &hdr->u.oth;
- } else if (lnh == HFI1_LRH_GRH) {
+ else if (lnh == HFI1_LRH_GRH)
ohdr = &hdr->u.l.oth;
- grh = &hdr->u.l.grh;
- } else {
+ else
goto next; /* just in case */
- }
+
bth1 = be32_to_cpu(ohdr->bth[1]);
is_ecn = !!(bth1 & (HFI1_FECN_SMASK | HFI1_BECN_SMASK));
@@ -639,7 +642,7 @@ static void __prescan_rxq(struct hfi1_packet *packet)
goto next;
}
- process_ecn(qp, hdr, ohdr, rhf, bth1, grh);
+ process_ecn(qp, packet, true);
rcu_read_unlock();
/* turn off BECN, FECN */
@@ -1362,6 +1365,7 @@ int process_receive_bypass(struct hfi1_packet *packet)
dd_dev_err(packet->rcd->dd,
"Bypass packets are not supported in normal operation. Dropping\n");
+ incr_cntr64(&packet->rcd->dd->sw_rcv_bypass_packet_errors);
return RHF_RCV_CONTINUE;
}
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index c702a009608f..1ecbec192358 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -168,6 +168,7 @@ static inline int is_valid_mmap(u64 token)
static int hfi1_file_open(struct inode *inode, struct file *fp)
{
+ struct hfi1_filedata *fd;
struct hfi1_devdata *dd = container_of(inode->i_cdev,
struct hfi1_devdata,
user_cdev);
@@ -176,10 +177,17 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
kobject_get(&dd->kobj);
/* The real work is performed later in assign_ctxt() */
- fp->private_data = kzalloc(sizeof(struct hfi1_filedata), GFP_KERNEL);
- if (fp->private_data) /* no cpu affinity by default */
- ((struct hfi1_filedata *)fp->private_data)->rec_cpu_num = -1;
- return fp->private_data ? 0 : -ENOMEM;
+
+ fd = kzalloc(sizeof(*fd), GFP_KERNEL);
+
+ if (fd) {
+ fd->rec_cpu_num = -1; /* no cpu affinity by default */
+ fd->mm = current->mm;
+ }
+
+ fp->private_data = fd;
+
+ return fd ? 0 : -ENOMEM;
}
static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
@@ -228,7 +236,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
sizeof(struct hfi1_base_info));
break;
case HFI1_IOCTL_CREDIT_UPD:
- if (uctxt && uctxt->sc)
+ if (uctxt)
sc_return_credits(uctxt->sc);
break;
@@ -392,41 +400,38 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
struct hfi1_filedata *fd = kiocb->ki_filp->private_data;
struct hfi1_user_sdma_pkt_q *pq = fd->pq;
struct hfi1_user_sdma_comp_q *cq = fd->cq;
- int ret = 0, done = 0, reqs = 0;
+ int done = 0, reqs = 0;
unsigned long dim = from->nr_segs;
- if (!cq || !pq) {
- ret = -EIO;
- goto done;
- }
+ if (!cq || !pq)
+ return -EIO;
- if (!iter_is_iovec(from) || !dim) {
- ret = -EINVAL;
- goto done;
- }
+ if (!iter_is_iovec(from) || !dim)
+ return -EINVAL;
hfi1_cdbg(SDMA, "SDMA request from %u:%u (%lu)",
fd->uctxt->ctxt, fd->subctxt, dim);
- if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
- ret = -ENOSPC;
- goto done;
- }
+ if (atomic_read(&pq->n_reqs) == pq->n_max_reqs)
+ return -ENOSPC;
while (dim) {
+ int ret;
unsigned long count = 0;
ret = hfi1_user_sdma_process_request(
kiocb->ki_filp, (struct iovec *)(from->iov + done),
dim, &count);
- if (ret)
- goto done;
+ if (ret) {
+ reqs = ret;
+ break;
+ }
dim -= count;
done += count;
reqs++;
}
-done:
- return ret ? ret : reqs;
+
+ return reqs;
}
static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
@@ -718,7 +723,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
hfi1_user_sdma_free_queues(fdata);
/* release the cpu */
- hfi1_put_proc_affinity(dd, fdata->rec_cpu_num);
+ hfi1_put_proc_affinity(fdata->rec_cpu_num);
/*
* Clear any left over, unhandled events so the next process that
@@ -730,7 +735,6 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
if (--uctxt->cnt) {
uctxt->active_slaves &= ~(1 << fdata->subctxt);
- uctxt->subpid[fdata->subctxt] = 0;
mutex_unlock(&hfi1_mutex);
goto done;
}
@@ -756,7 +760,6 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
write_kctxt_csr(dd, uctxt->sc->hw_context, SEND_CTXT_CHECK_ENABLE,
hfi1_pkt_default_send_ctxt_mask(dd, uctxt->sc->type));
sc_disable(uctxt->sc);
- uctxt->pid = 0;
spin_unlock_irqrestore(&dd->uctxt_lock, flags);
dd->rcd[uctxt->ctxt] = NULL;
@@ -818,9 +821,10 @@ static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo)
ret = find_shared_ctxt(fp, uinfo);
if (ret < 0)
goto done_unlock;
- if (ret)
- fd->rec_cpu_num = hfi1_get_proc_affinity(
- fd->uctxt->dd, fd->uctxt->numa_id);
+ if (ret) {
+ fd->rec_cpu_num =
+ hfi1_get_proc_affinity(fd->uctxt->numa_id);
+ }
}
/*
@@ -895,7 +899,6 @@ static int find_shared_ctxt(struct file *fp,
}
fd->uctxt = uctxt;
fd->subctxt = uctxt->cnt++;
- uctxt->subpid[fd->subctxt] = current->pid;
uctxt->active_slaves |= 1 << fd->subctxt;
ret = 1;
goto done;
@@ -932,7 +935,11 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
if (ctxt == dd->num_rcv_contexts)
return -EBUSY;
- fd->rec_cpu_num = hfi1_get_proc_affinity(dd, -1);
+ /*
+ * If we don't have a NUMA node requested, preference is towards
+ * device NUMA node.
+ */
+ fd->rec_cpu_num = hfi1_get_proc_affinity(dd->node);
if (fd->rec_cpu_num != -1)
numa = cpu_to_node(fd->rec_cpu_num);
else
@@ -976,8 +983,7 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
return ret;
}
uctxt->userversion = uinfo->userversion;
- uctxt->pid = current->pid;
- uctxt->flags = HFI1_CAP_UGET(MASK);
+ uctxt->flags = hfi1_cap_mask; /* save current flag state */
init_waitqueue_head(&uctxt->wait);
strlcpy(uctxt->comm, current->comm, sizeof(uctxt->comm));
memcpy(uctxt->uuid, uinfo->uuid, sizeof(uctxt->uuid));
@@ -1080,18 +1086,18 @@ static int user_init(struct file *fp)
hfi1_set_ctxt_jkey(uctxt->dd, uctxt->ctxt, uctxt->jkey);
rcvctrl_ops = HFI1_RCVCTRL_CTXT_ENB;
- if (HFI1_CAP_KGET_MASK(uctxt->flags, HDRSUPP))
+ if (HFI1_CAP_UGET_MASK(uctxt->flags, HDRSUPP))
rcvctrl_ops |= HFI1_RCVCTRL_TIDFLOW_ENB;
/*
* Ignore the bit in the flags for now until proper
* support for multiple packet per rcv array entry is
* added.
*/
- if (!HFI1_CAP_KGET_MASK(uctxt->flags, MULTI_PKT_EGR))
+ if (!HFI1_CAP_UGET_MASK(uctxt->flags, MULTI_PKT_EGR))
rcvctrl_ops |= HFI1_RCVCTRL_ONE_PKT_EGR_ENB;
- if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_EGR_FULL))
+ if (HFI1_CAP_UGET_MASK(uctxt->flags, NODROP_EGR_FULL))
rcvctrl_ops |= HFI1_RCVCTRL_NO_EGR_DROP_ENB;
- if (HFI1_CAP_KGET_MASK(uctxt->flags, NODROP_RHQ_FULL))
+ if (HFI1_CAP_UGET_MASK(uctxt->flags, NODROP_RHQ_FULL))
rcvctrl_ops |= HFI1_RCVCTRL_NO_RHQ_DROP_ENB;
/*
* The RcvCtxtCtrl.TailUpd bit has to be explicitly written.
@@ -1099,7 +1105,7 @@ static int user_init(struct file *fp)
* uses of the chip or ctxt. Therefore, add the rcvctrl op
* for both cases.
*/
- if (HFI1_CAP_KGET_MASK(uctxt->flags, DMA_RTAIL))
+ if (HFI1_CAP_UGET_MASK(uctxt->flags, DMA_RTAIL))
rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_ENB;
else
rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_DIS;
@@ -1122,9 +1128,14 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
int ret = 0;
memset(&cinfo, 0, sizeof(cinfo));
- ret = hfi1_get_base_kinfo(uctxt, &cinfo);
- if (ret < 0)
- goto done;
+ cinfo.runtime_flags = (((uctxt->flags >> HFI1_CAP_MISC_SHIFT) &
+ HFI1_CAP_MISC_MASK) << HFI1_CAP_USER_SHIFT) |
+ HFI1_CAP_UGET_MASK(uctxt->flags, MASK) |
+ HFI1_CAP_KGET_MASK(uctxt->flags, K2U);
+ /* adjust flag if this fd is not able to cache */
+ if (!fd->handler)
+ cinfo.runtime_flags |= HFI1_CAP_TID_UNMAP; /* no caching */
+
cinfo.num_active = hfi1_count_active_units();
cinfo.unit = uctxt->dd->unit;
cinfo.ctxt = uctxt->ctxt;
@@ -1146,7 +1157,7 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
trace_hfi1_ctxt_info(uctxt->dd, uctxt->ctxt, fd->subctxt, cinfo);
if (copy_to_user(ubase, &cinfo, sizeof(cinfo)))
ret = -EFAULT;
-done:
+
return ret;
}
diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c
index ed680fda611d..13db8eb4f4ec 100644
--- a/drivers/infiniband/hw/hfi1/firmware.c
+++ b/drivers/infiniband/hw/hfi1/firmware.c
@@ -206,6 +206,9 @@ static const struct firmware *platform_config;
/* the number of fabric SerDes on the SBus */
#define NUM_FABRIC_SERDES 4
+/* ASIC_STS_SBUS_RESULT.RESULT_CODE value */
+#define SBUS_READ_COMPLETE 0x4
+
/* SBus fabric SerDes addresses, one set per HFI */
static const u8 fabric_serdes_addrs[2][NUM_FABRIC_SERDES] = {
{ 0x01, 0x02, 0x03, 0x04 },
@@ -240,6 +243,7 @@ static const u8 all_pcie_serdes_broadcast = 0xe0;
static void dispose_one_firmware(struct firmware_details *fdet);
static int load_fabric_serdes_firmware(struct hfi1_devdata *dd,
struct firmware_details *fdet);
+static void dump_fw_version(struct hfi1_devdata *dd);
/*
* Read a single 64-bit value from 8051 data memory.
@@ -1079,6 +1083,44 @@ void sbus_request(struct hfi1_devdata *dd,
}
/*
+ * Read a value from the SBus.
+ *
+ * Requires the caller to be in fast mode
+ */
+static u32 sbus_read(struct hfi1_devdata *dd, u8 receiver_addr, u8 data_addr,
+ u32 data_in)
+{
+ u64 reg;
+ int retries;
+ int success = 0;
+ u32 result = 0;
+ u32 result_code = 0;
+
+ sbus_request(dd, receiver_addr, data_addr, READ_SBUS_RECEIVER, data_in);
+
+ for (retries = 0; retries < 100; retries++) {
+ usleep_range(1000, 1200); /* arbitrary */
+ reg = read_csr(dd, ASIC_STS_SBUS_RESULT);
+ result_code = (reg >> ASIC_STS_SBUS_RESULT_RESULT_CODE_SHIFT)
+ & ASIC_STS_SBUS_RESULT_RESULT_CODE_MASK;
+ if (result_code != SBUS_READ_COMPLETE)
+ continue;
+
+ success = 1;
+ result = (reg >> ASIC_STS_SBUS_RESULT_DATA_OUT_SHIFT)
+ & ASIC_STS_SBUS_RESULT_DATA_OUT_MASK;
+ break;
+ }
+
+ if (!success) {
+ dd_dev_err(dd, "%s: read failed, result code 0x%x\n", __func__,
+ result_code);
+ }
+
+ return result;
+}
+
+/*
* Turn off the SBus and fabric serdes spicos.
*
* + Must be called with Sbus fast mode turned on.
@@ -1636,6 +1678,7 @@ int load_firmware(struct hfi1_devdata *dd)
return ret;
}
+ dump_fw_version(dd);
return 0;
}
@@ -2054,3 +2097,85 @@ void read_guid(struct hfi1_devdata *dd)
dd_dev_info(dd, "GUID %llx",
(unsigned long long)dd->base_guid);
}
+
+/* read and display firmware version info */
+static void dump_fw_version(struct hfi1_devdata *dd)
+{
+ u32 pcie_vers[NUM_PCIE_SERDES];
+ u32 fabric_vers[NUM_FABRIC_SERDES];
+ u32 sbus_vers;
+ int i;
+ int all_same;
+ int ret;
+ u8 rcv_addr;
+
+ ret = acquire_chip_resource(dd, CR_SBUS, SBUS_TIMEOUT);
+ if (ret) {
+ dd_dev_err(dd, "Unable to acquire SBus to read firmware versions\n");
+ return;
+ }
+
+ /* set fast mode */
+ set_sbus_fast_mode(dd);
+
+ /* read version for SBus Master */
+ sbus_request(dd, SBUS_MASTER_BROADCAST, 0x02, WRITE_SBUS_RECEIVER, 0);
+ sbus_request(dd, SBUS_MASTER_BROADCAST, 0x07, WRITE_SBUS_RECEIVER, 0x1);
+ /* wait for interrupt to be processed */
+ usleep_range(10000, 11000);
+ sbus_vers = sbus_read(dd, SBUS_MASTER_BROADCAST, 0x08, 0x1);
+ dd_dev_info(dd, "SBus Master firmware version 0x%08x\n", sbus_vers);
+
+ /* read version for PCIe SerDes */
+ all_same = 1;
+ pcie_vers[0] = 0;
+ for (i = 0; i < NUM_PCIE_SERDES; i++) {
+ rcv_addr = pcie_serdes_addrs[dd->hfi1_id][i];
+ sbus_request(dd, rcv_addr, 0x03, WRITE_SBUS_RECEIVER, 0);
+ /* wait for interrupt to be processed */
+ usleep_range(10000, 11000);
+ pcie_vers[i] = sbus_read(dd, rcv_addr, 0x04, 0x0);
+ if (i > 0 && pcie_vers[0] != pcie_vers[i])
+ all_same = 0;
+ }
+
+ if (all_same) {
+ dd_dev_info(dd, "PCIe SerDes firmware version 0x%x\n",
+ pcie_vers[0]);
+ } else {
+ dd_dev_warn(dd, "PCIe SerDes do not have the same firmware version\n");
+ for (i = 0; i < NUM_PCIE_SERDES; i++) {
+ dd_dev_info(dd,
+ "PCIe SerDes lane %d firmware version 0x%x\n",
+ i, pcie_vers[i]);
+ }
+ }
+
+ /* read version for fabric SerDes */
+ all_same = 1;
+ fabric_vers[0] = 0;
+ for (i = 0; i < NUM_FABRIC_SERDES; i++) {
+ rcv_addr = fabric_serdes_addrs[dd->hfi1_id][i];
+ sbus_request(dd, rcv_addr, 0x03, WRITE_SBUS_RECEIVER, 0);
+ /* wait for interrupt to be processed */
+ usleep_range(10000, 11000);
+ fabric_vers[i] = sbus_read(dd, rcv_addr, 0x04, 0x0);
+ if (i > 0 && fabric_vers[0] != fabric_vers[i])
+ all_same = 0;
+ }
+
+ if (all_same) {
+ dd_dev_info(dd, "Fabric SerDes firmware version 0x%x\n",
+ fabric_vers[0]);
+ } else {
+ dd_dev_warn(dd, "Fabric SerDes do not have the same firmware version\n");
+ for (i = 0; i < NUM_FABRIC_SERDES; i++) {
+ dd_dev_info(dd,
+ "Fabric SerDes lane %d firmware version 0x%x\n",
+ i, fabric_vers[i]);
+ }
+ }
+
+ clear_sbus_fast_mode(dd);
+ release_chip_resource(dd, CR_SBUS);
+}
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h
index 4417a0fd3ef9..1000e0fd96d9 100644
--- a/drivers/infiniband/hw/hfi1/hfi.h
+++ b/drivers/infiniband/hw/hfi1/hfi.h
@@ -62,6 +62,8 @@
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
#include <rdma/rdma_vt.h>
#include "chip_registers.h"
@@ -253,7 +255,7 @@ struct hfi1_ctxtdata {
/* chip offset of PIO buffers for this ctxt */
u32 piobufs;
/* per-context configuration flags */
- u32 flags;
+ unsigned long flags;
/* per-context event flags for fileops/intr communication */
unsigned long event_flags;
/* WAIT_RCV that timed out, no interrupt */
@@ -268,9 +270,6 @@ struct hfi1_ctxtdata {
u32 urgent;
/* saved total number of polled urgent packets for poll edge trigger */
u32 urgent_poll;
- /* pid of process using this ctxt */
- pid_t pid;
- pid_t subpid[HFI1_MAX_SHARED_CTXTS];
/* same size as task_struct .comm[], command that opened context */
char comm[TASK_COMM_LEN];
/* so file ops can get at unit */
@@ -366,11 +365,6 @@ struct hfi1_packet {
u8 etype;
};
-static inline bool has_sc4_bit(struct hfi1_packet *p)
-{
- return !!rhf_dc_info(p->rhf);
-}
-
/*
* Private data for snoop/capture support.
*/
@@ -805,10 +799,19 @@ struct hfi1_temp {
u8 triggers; /* temperature triggers */
};
+struct hfi1_i2c_bus {
+ struct hfi1_devdata *controlling_dd; /* current controlling device */
+ struct i2c_adapter adapter; /* bus details */
+ struct i2c_algo_bit_data algo; /* bus algorithm details */
+ int num; /* bus number, 0 or 1 */
+};
+
/* common data between shared ASIC HFIs */
struct hfi1_asic_data {
struct hfi1_devdata *dds[2]; /* back pointers */
struct mutex asic_resource_mutex;
+ struct hfi1_i2c_bus *i2c_bus0;
+ struct hfi1_i2c_bus *i2c_bus1;
};
/* device data struct now contains only "general per-device" info.
@@ -1128,7 +1131,8 @@ struct hfi1_devdata {
NUM_SEND_DMA_ENG_ERR_STATUS_COUNTERS];
/* Software counter that aggregates all cce_err_status errors */
u64 sw_cce_err_status_aggregate;
-
+ /* Software counter that aggregates all bypass packet rcv errors */
+ u64 sw_rcv_bypass_packet_errors;
/* receive interrupt functions */
rhf_rcv_function_ptr *rhf_rcv_function_map;
rhf_rcv_function_ptr normal_rhf_rcv_functions[8];
@@ -1174,6 +1178,8 @@ struct hfi1_devdata {
/* 8051 firmware version helper */
#define dc8051_ver(a, b) ((a) << 8 | (b))
+#define dc8051_ver_maj(a) ((a & 0xff00) >> 8)
+#define dc8051_ver_min(a) (a & 0x00ff)
/* f_put_tid types */
#define PT_EXPECTED 0
@@ -1182,6 +1188,7 @@ struct hfi1_devdata {
struct tid_rb_node;
struct mmu_rb_node;
+struct mmu_rb_handler;
/* Private data for file operations */
struct hfi1_filedata {
@@ -1192,7 +1199,7 @@ struct hfi1_filedata {
/* for cpu affinity; -1 if none */
int rec_cpu_num;
u32 tid_n_pinned;
- struct rb_root tid_rb_root;
+ struct mmu_rb_handler *handler;
struct tid_rb_node **entry_to_rb;
spinlock_t tid_lock; /* protect tid_[limit,used] counters */
u32 tid_limit;
@@ -1201,6 +1208,7 @@ struct hfi1_filedata {
u32 invalid_tid_idx;
/* protect invalid_tids array and invalid_tid_idx */
spinlock_t invalid_lock;
+ struct mm_struct *mm;
};
extern struct list_head hfi1_dev_list;
@@ -1234,6 +1242,8 @@ int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *, int);
int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *, int);
void set_all_slowpath(struct hfi1_devdata *dd);
+extern const struct pci_device_id hfi1_pci_tbl[];
+
/* receive packet handler dispositions */
#define RCV_PKT_OK 0x0 /* keep going */
#define RCV_PKT_LIMIT 0x1 /* stop, hit limit, start thread */
@@ -1259,7 +1269,7 @@ void receive_interrupt_work(struct work_struct *work);
static inline int hdr2sc(struct hfi1_message_header *hdr, u64 rhf)
{
return ((be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf) |
- ((!!(rhf & RHF_DC_INFO_SMASK)) << 4);
+ ((!!(rhf_dc_info(rhf))) << 4);
}
static inline u16 generate_jkey(kuid_t uid)
@@ -1569,6 +1579,22 @@ static inline struct hfi1_ibport *to_iport(struct ib_device *ibdev, u8 port)
return &dd->pport[pidx].ibport_data;
}
+void hfi1_process_ecn_slowpath(struct rvt_qp *qp, struct hfi1_packet *pkt,
+ bool do_cnp);
+static inline bool process_ecn(struct rvt_qp *qp, struct hfi1_packet *pkt,
+ bool do_cnp)
+{
+ struct hfi1_other_headers *ohdr = pkt->ohdr;
+ u32 bth1;
+
+ bth1 = be32_to_cpu(ohdr->bth[1]);
+ if (unlikely(bth1 & (HFI1_BECN_SMASK | HFI1_FECN_SMASK))) {
+ hfi1_process_ecn_slowpath(qp, pkt, do_cnp);
+ return bth1 & HFI1_FECN_SMASK;
+ }
+ return false;
+}
+
/*
* Return the indexed PKEY from the port PKEY table.
*/
@@ -1586,8 +1612,7 @@ static inline u16 hfi1_get_pkey(struct hfi1_ibport *ibp, unsigned index)
}
/*
- * Readers of cc_state must call get_cc_state() under rcu_read_lock().
- * Writers of cc_state must call get_cc_state() under cc_state_lock.
+ * Called by readers of cc_state only, must call under rcu_read_lock().
*/
static inline struct cc_state *get_cc_state(struct hfi1_pportdata *ppd)
{
@@ -1595,6 +1620,16 @@ static inline struct cc_state *get_cc_state(struct hfi1_pportdata *ppd)
}
/*
+ * Called by writers of cc_state only, must call under cc_state_lock.
+ */
+static inline
+struct cc_state *get_cc_state_protected(struct hfi1_pportdata *ppd)
+{
+ return rcu_dereference_protected(ppd->cc_state,
+ lockdep_is_held(&ppd->cc_state_lock));
+}
+
+/*
* values for dd->flags (_device_ related flags)
*/
#define HFI1_INITTED 0x1 /* chip and driver up and initted */
@@ -1669,9 +1704,12 @@ void shutdown_led_override(struct hfi1_pportdata *ppd);
*/
#define DEFAULT_RCVHDR_ENTSIZE 32
-bool hfi1_can_pin_pages(struct hfi1_devdata *, u32, u32);
-int hfi1_acquire_user_pages(unsigned long, size_t, bool, struct page **);
-void hfi1_release_user_pages(struct mm_struct *, struct page **, size_t, bool);
+bool hfi1_can_pin_pages(struct hfi1_devdata *dd, struct mm_struct *mm,
+ u32 nlocked, u32 npages);
+int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr,
+ size_t npages, bool writable, struct page **pages);
+void hfi1_release_user_pages(struct mm_struct *mm, struct page **p,
+ size_t npages, bool dirty);
static inline void clear_rcvhdrtail(const struct hfi1_ctxtdata *rcd)
{
@@ -1947,4 +1985,55 @@ static inline u32 qsfp_resource(struct hfi1_devdata *dd)
int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
+#define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev))
+#define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev))
+
+#define packettype_name(etype) { RHF_RCV_TYPE_##etype, #etype }
+#define show_packettype(etype) \
+__print_symbolic(etype, \
+ packettype_name(EXPECTED), \
+ packettype_name(EAGER), \
+ packettype_name(IB), \
+ packettype_name(ERROR), \
+ packettype_name(BYPASS))
+
+#define ib_opcode_name(opcode) { IB_OPCODE_##opcode, #opcode }
+#define show_ib_opcode(opcode) \
+__print_symbolic(opcode, \
+ ib_opcode_name(RC_SEND_FIRST), \
+ ib_opcode_name(RC_SEND_MIDDLE), \
+ ib_opcode_name(RC_SEND_LAST), \
+ ib_opcode_name(RC_SEND_LAST_WITH_IMMEDIATE), \
+ ib_opcode_name(RC_SEND_ONLY), \
+ ib_opcode_name(RC_SEND_ONLY_WITH_IMMEDIATE), \
+ ib_opcode_name(RC_RDMA_WRITE_FIRST), \
+ ib_opcode_name(RC_RDMA_WRITE_MIDDLE), \
+ ib_opcode_name(RC_RDMA_WRITE_LAST), \
+ ib_opcode_name(RC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \
+ ib_opcode_name(RC_RDMA_WRITE_ONLY), \
+ ib_opcode_name(RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \
+ ib_opcode_name(RC_RDMA_READ_REQUEST), \
+ ib_opcode_name(RC_RDMA_READ_RESPONSE_FIRST), \
+ ib_opcode_name(RC_RDMA_READ_RESPONSE_MIDDLE), \
+ ib_opcode_name(RC_RDMA_READ_RESPONSE_LAST), \
+ ib_opcode_name(RC_RDMA_READ_RESPONSE_ONLY), \
+ ib_opcode_name(RC_ACKNOWLEDGE), \
+ ib_opcode_name(RC_ATOMIC_ACKNOWLEDGE), \
+ ib_opcode_name(RC_COMPARE_SWAP), \
+ ib_opcode_name(RC_FETCH_ADD), \
+ ib_opcode_name(UC_SEND_FIRST), \
+ ib_opcode_name(UC_SEND_MIDDLE), \
+ ib_opcode_name(UC_SEND_LAST), \
+ ib_opcode_name(UC_SEND_LAST_WITH_IMMEDIATE), \
+ ib_opcode_name(UC_SEND_ONLY), \
+ ib_opcode_name(UC_SEND_ONLY_WITH_IMMEDIATE), \
+ ib_opcode_name(UC_RDMA_WRITE_FIRST), \
+ ib_opcode_name(UC_RDMA_WRITE_MIDDLE), \
+ ib_opcode_name(UC_RDMA_WRITE_LAST), \
+ ib_opcode_name(UC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \
+ ib_opcode_name(UC_RDMA_WRITE_ONLY), \
+ ib_opcode_name(UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \
+ ib_opcode_name(UD_SEND_ONLY), \
+ ib_opcode_name(UD_SEND_ONLY_WITH_IMMEDIATE), \
+ ib_opcode_name(CNP))
#endif /* _HFI1_KERNEL_H */
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index eed971ccd2a1..a358d23ecd54 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -64,6 +64,7 @@
#include "debugfs.h"
#include "verbs.h"
#include "aspm.h"
+#include "affinity.h"
#undef pr_fmt
#define pr_fmt(fmt) DRIVER_NAME ": " fmt
@@ -474,8 +475,9 @@ static enum hrtimer_restart cca_timer_fn(struct hrtimer *t)
void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
struct hfi1_devdata *dd, u8 hw_pidx, u8 port)
{
- int i, size;
+ int i;
uint default_pkey_idx;
+ struct cc_state *cc_state;
ppd->dd = dd;
ppd->hw_pidx = hw_pidx;
@@ -526,9 +528,9 @@ void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
spin_lock_init(&ppd->cc_state_lock);
spin_lock_init(&ppd->cc_log_lock);
- size = sizeof(struct cc_state);
- RCU_INIT_POINTER(ppd->cc_state, kzalloc(size, GFP_KERNEL));
- if (!rcu_dereference(ppd->cc_state))
+ cc_state = kzalloc(sizeof(*cc_state), GFP_KERNEL);
+ RCU_INIT_POINTER(ppd->cc_state, cc_state);
+ if (!cc_state)
goto bail;
return;
@@ -972,39 +974,49 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
/*
* Release our hold on the shared asic data. If we are the last one,
- * free the structure. Must be holding hfi1_devs_lock.
+ * return the structure to be finalized outside the lock. Must be
+ * holding hfi1_devs_lock.
*/
-static void release_asic_data(struct hfi1_devdata *dd)
+static struct hfi1_asic_data *release_asic_data(struct hfi1_devdata *dd)
{
+ struct hfi1_asic_data *ad;
int other;
if (!dd->asic_data)
- return;
+ return NULL;
dd->asic_data->dds[dd->hfi1_id] = NULL;
other = dd->hfi1_id ? 0 : 1;
- if (!dd->asic_data->dds[other]) {
- /* we are the last holder, free it */
- kfree(dd->asic_data);
- }
+ ad = dd->asic_data;
dd->asic_data = NULL;
+ /* return NULL if the other dd still has a link */
+ return ad->dds[other] ? NULL : ad;
+}
+
+static void finalize_asic_data(struct hfi1_devdata *dd,
+ struct hfi1_asic_data *ad)
+{
+ clean_up_i2c(dd, ad);
+ kfree(ad);
}
static void __hfi1_free_devdata(struct kobject *kobj)
{
struct hfi1_devdata *dd =
container_of(kobj, struct hfi1_devdata, kobj);
+ struct hfi1_asic_data *ad;
unsigned long flags;
spin_lock_irqsave(&hfi1_devs_lock, flags);
idr_remove(&hfi1_unit_table, dd->unit);
list_del(&dd->list);
- release_asic_data(dd);
+ ad = release_asic_data(dd);
spin_unlock_irqrestore(&hfi1_devs_lock, flags);
+ if (ad)
+ finalize_asic_data(dd, ad);
free_platform_config(dd);
rcu_barrier(); /* wait for rcu callbacks to complete */
free_percpu(dd->int_counter);
free_percpu(dd->rcv_limit);
- hfi1_dev_affinity_free(dd);
free_percpu(dd->send_schedule);
rvt_dealloc_device(&dd->verbs_dev.rdi);
}
@@ -1162,7 +1174,7 @@ static int init_one(struct pci_dev *, const struct pci_device_id *);
#define DRIVER_LOAD_MSG "Intel " DRIVER_NAME " loaded: "
#define PFX DRIVER_NAME ": "
-static const struct pci_device_id hfi1_pci_tbl[] = {
+const struct pci_device_id hfi1_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL0) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL1) },
{ 0, }
@@ -1198,6 +1210,10 @@ static int __init hfi1_mod_init(void)
if (ret)
goto bail;
+ ret = node_affinity_init();
+ if (ret)
+ goto bail;
+
/* validate max MTU before any devices start */
if (!valid_opa_max_mtu(hfi1_max_mtu)) {
pr_err("Invalid max_mtu 0x%x, using 0x%x instead\n",
@@ -1278,6 +1294,7 @@ module_init(hfi1_mod_init);
static void __exit hfi1_mod_cleanup(void)
{
pci_unregister_driver(&hfi1_pci_driver);
+ node_affinity_destroy();
hfi1_wss_exit();
hfi1_dbg_exit();
hfi1_cpulist_count = 0;
@@ -1311,7 +1328,7 @@ static void cleanup_device_data(struct hfi1_devdata *dd)
hrtimer_cancel(&ppd->cca_timer[i].hrtimer);
spin_lock(&ppd->cc_state_lock);
- cc_state = get_cc_state(ppd);
+ cc_state = get_cc_state_protected(ppd);
RCU_INIT_POINTER(ppd->cc_state, NULL);
spin_unlock(&ppd->cc_state_lock);
@@ -1760,8 +1777,8 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
hfi1_cdbg(PROC,
"ctxt%u: Alloced %u rcv tid entries @ %uKB, total %zuKB\n",
- rcd->ctxt, rcd->egrbufs.alloced, rcd->egrbufs.rcvtid_size,
- rcd->egrbufs.size);
+ rcd->ctxt, rcd->egrbufs.alloced,
+ rcd->egrbufs.rcvtid_size / 1024, rcd->egrbufs.size / 1024);
/*
* Set the contexts rcv array head update threshold to the closest
diff --git a/drivers/infiniband/hw/hfi1/mad.c b/drivers/infiniband/hw/hfi1/mad.c
index fca07a1d6c28..1263abe01999 100644
--- a/drivers/infiniband/hw/hfi1/mad.c
+++ b/drivers/infiniband/hw/hfi1/mad.c
@@ -588,7 +588,6 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data,
pi->port_phys_conf = (ppd->port_type & 0xf);
-#if PI_LED_ENABLE_SUP
pi->port_states.ledenable_offlinereason = ppd->neighbor_normal << 4;
pi->port_states.ledenable_offlinereason |=
ppd->is_sm_config_started << 5;
@@ -602,11 +601,6 @@ static int __subn_get_opa_portinfo(struct opa_smp *smp, u32 am, u8 *data,
pi->port_states.ledenable_offlinereason |= is_beaconing_active << 6;
pi->port_states.ledenable_offlinereason |=
ppd->offline_disabled_reason;
-#else
- pi->port_states.offline_reason = ppd->neighbor_normal << 4;
- pi->port_states.offline_reason |= ppd->is_sm_config_started << 5;
- pi->port_states.offline_reason |= ppd->offline_disabled_reason;
-#endif /* PI_LED_ENABLE_SUP */
pi->port_states.portphysstate_portstate =
(hfi1_ibphys_portstate(ppd) << 4) | state;
@@ -1752,17 +1746,11 @@ static int __subn_get_opa_psi(struct opa_smp *smp, u32 am, u8 *data,
if (start_of_sm_config && (lstate == IB_PORT_INIT))
ppd->is_sm_config_started = 1;
-#if PI_LED_ENABLE_SUP
psi->port_states.ledenable_offlinereason = ppd->neighbor_normal << 4;
psi->port_states.ledenable_offlinereason |=
ppd->is_sm_config_started << 5;
psi->port_states.ledenable_offlinereason |=
ppd->offline_disabled_reason;
-#else
- psi->port_states.offline_reason = ppd->neighbor_normal << 4;
- psi->port_states.offline_reason |= ppd->is_sm_config_started << 5;
- psi->port_states.offline_reason |= ppd->offline_disabled_reason;
-#endif /* PI_LED_ENABLE_SUP */
psi->port_states.portphysstate_portstate =
(hfi1_ibphys_portstate(ppd) << 4) | (lstate & 0xf);
@@ -2430,14 +2418,9 @@ static int pma_get_opa_portstatus(struct opa_pma_mad *pmp,
rsp->port_rcv_remote_physical_errors =
cpu_to_be64(read_dev_cntr(dd, C_DC_RMT_PHY_ERR,
CNTR_INVALID_VL));
- tmp = read_dev_cntr(dd, C_DC_RX_REPLAY, CNTR_INVALID_VL);
- tmp2 = tmp + read_dev_cntr(dd, C_DC_TX_REPLAY, CNTR_INVALID_VL);
- if (tmp2 < tmp) {
- /* overflow/wrapped */
- rsp->local_link_integrity_errors = cpu_to_be64(~0);
- } else {
- rsp->local_link_integrity_errors = cpu_to_be64(tmp2);
- }
+ rsp->local_link_integrity_errors =
+ cpu_to_be64(read_dev_cntr(dd, C_DC_RX_REPLAY,
+ CNTR_INVALID_VL));
tmp = read_dev_cntr(dd, C_DC_SEQ_CRC_CNT, CNTR_INVALID_VL);
tmp2 = tmp + read_dev_cntr(dd, C_DC_REINIT_FROM_PEER_CNT,
CNTR_INVALID_VL);
@@ -2499,6 +2482,9 @@ static int pma_get_opa_portstatus(struct opa_pma_mad *pmp,
cpu_to_be64(read_dev_cntr(dd, C_DC_RCV_BCN_VL,
idx_from_vl(vl)));
+ rsp->vls[vfi].port_vl_xmit_discards =
+ cpu_to_be64(read_port_cntr(ppd, C_SW_XMIT_DSCD_VL,
+ idx_from_vl(vl)));
vlinfo++;
vfi++;
}
@@ -2529,9 +2515,8 @@ static u64 get_error_counter_summary(struct ib_device *ibdev, u8 port,
error_counter_summary += read_dev_cntr(dd, C_DC_RMT_PHY_ERR,
CNTR_INVALID_VL);
/* local link integrity must be right-shifted by the lli resolution */
- tmp = read_dev_cntr(dd, C_DC_RX_REPLAY, CNTR_INVALID_VL);
- tmp += read_dev_cntr(dd, C_DC_TX_REPLAY, CNTR_INVALID_VL);
- error_counter_summary += (tmp >> res_lli);
+ error_counter_summary += (read_dev_cntr(dd, C_DC_RX_REPLAY,
+ CNTR_INVALID_VL) >> res_lli);
/* link error recovery must b right-shifted by the ler resolution */
tmp = read_dev_cntr(dd, C_DC_SEQ_CRC_CNT, CNTR_INVALID_VL);
tmp += read_dev_cntr(dd, C_DC_REINIT_FROM_PEER_CNT, CNTR_INVALID_VL);
@@ -2800,14 +2785,9 @@ static void pma_get_opa_port_ectrs(struct ib_device *ibdev,
rsp->port_rcv_constraint_errors =
cpu_to_be64(read_port_cntr(ppd, C_SW_RCV_CSTR_ERR,
CNTR_INVALID_VL));
- tmp = read_dev_cntr(dd, C_DC_RX_REPLAY, CNTR_INVALID_VL);
- tmp2 = tmp + read_dev_cntr(dd, C_DC_TX_REPLAY, CNTR_INVALID_VL);
- if (tmp2 < tmp) {
- /* overflow/wrapped */
- rsp->local_link_integrity_errors = cpu_to_be64(~0);
- } else {
- rsp->local_link_integrity_errors = cpu_to_be64(tmp2);
- }
+ rsp->local_link_integrity_errors =
+ cpu_to_be64(read_dev_cntr(dd, C_DC_RX_REPLAY,
+ CNTR_INVALID_VL));
rsp->excessive_buffer_overruns =
cpu_to_be64(read_dev_cntr(dd, C_RCV_OVF, CNTR_INVALID_VL));
}
@@ -2883,14 +2863,17 @@ static int pma_get_opa_porterrors(struct opa_pma_mad *pmp,
tmp = read_dev_cntr(dd, C_DC_UNC_ERR, CNTR_INVALID_VL);
rsp->uncorrectable_errors = tmp < 0x100 ? (tmp & 0xff) : 0xff;
-
+ rsp->port_rcv_errors =
+ cpu_to_be64(read_dev_cntr(dd, C_DC_RCV_ERR, CNTR_INVALID_VL));
vlinfo = &rsp->vls[0];
vfi = 0;
vl_select_mask = be32_to_cpu(req->vl_select_mask);
for_each_set_bit(vl, (unsigned long *)&(vl_select_mask),
8 * sizeof(req->vl_select_mask)) {
memset(vlinfo, 0, sizeof(*vlinfo));
- /* vlinfo->vls[vfi].port_vl_xmit_discards ??? */
+ rsp->vls[vfi].port_vl_xmit_discards =
+ cpu_to_be64(read_port_cntr(ppd, C_SW_XMIT_DSCD_VL,
+ idx_from_vl(vl)));
vlinfo += 1;
vfi++;
}
@@ -3162,10 +3145,8 @@ static int pma_set_opa_portstatus(struct opa_pma_mad *pmp,
if (counter_select & CS_PORT_RCV_REMOTE_PHYSICAL_ERRORS)
write_dev_cntr(dd, C_DC_RMT_PHY_ERR, CNTR_INVALID_VL, 0);
- if (counter_select & CS_LOCAL_LINK_INTEGRITY_ERRORS) {
- write_dev_cntr(dd, C_DC_TX_REPLAY, CNTR_INVALID_VL, 0);
+ if (counter_select & CS_LOCAL_LINK_INTEGRITY_ERRORS)
write_dev_cntr(dd, C_DC_RX_REPLAY, CNTR_INVALID_VL, 0);
- }
if (counter_select & CS_LINK_ERROR_RECOVERY) {
write_dev_cntr(dd, C_DC_SEQ_CRC_CNT, CNTR_INVALID_VL, 0);
@@ -3223,7 +3204,9 @@ static int pma_set_opa_portstatus(struct opa_pma_mad *pmp,
/* if (counter_select & CS_PORT_MARK_FECN)
* write_csr(dd, DCC_PRF_PORT_VL_MARK_FECN_CNT + offset, 0);
*/
- /* port_vl_xmit_discards ??? */
+ if (counter_select & C_SW_XMIT_DSCD_VL)
+ write_port_cntr(ppd, C_SW_XMIT_DSCD_VL,
+ idx_from_vl(vl), 0);
}
if (resp_len)
@@ -3392,7 +3375,7 @@ static void apply_cc_state(struct hfi1_pportdata *ppd)
*/
spin_lock(&ppd->cc_state_lock);
- old_cc_state = get_cc_state(ppd);
+ old_cc_state = get_cc_state_protected(ppd);
if (!old_cc_state) {
/* never active, or shutting down */
spin_unlock(&ppd->cc_state_lock);
@@ -3960,7 +3943,6 @@ void clear_linkup_counters(struct hfi1_devdata *dd)
write_dev_cntr(dd, C_DC_SEQ_CRC_CNT, CNTR_INVALID_VL, 0);
write_dev_cntr(dd, C_DC_REINIT_FROM_PEER_CNT, CNTR_INVALID_VL, 0);
/* LocalLinkIntegrityErrors */
- write_dev_cntr(dd, C_DC_TX_REPLAY, CNTR_INVALID_VL, 0);
write_dev_cntr(dd, C_DC_RX_REPLAY, CNTR_INVALID_VL, 0);
/* ExcessiveBufferOverruns */
write_dev_cntr(dd, C_RCV_OVF, CNTR_INVALID_VL, 0);
diff --git a/drivers/infiniband/hw/hfi1/mad.h b/drivers/infiniband/hw/hfi1/mad.h
index 8b734aaae88a..5aa3fd1be653 100644
--- a/drivers/infiniband/hw/hfi1/mad.h
+++ b/drivers/infiniband/hw/hfi1/mad.h
@@ -48,15 +48,8 @@
#define _HFI1_MAD_H
#include <rdma/ib_pma.h>
-#define USE_PI_LED_ENABLE 1 /*
- * use led enabled bit in struct
- * opa_port_states, if available
- */
#include <rdma/opa_smi.h>
#include <rdma/opa_port_info.h>
-#ifndef PI_LED_ENABLE_SUP
-#define PI_LED_ENABLE_SUP 0
-#endif
#include "opa_compat.h"
/*
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.c b/drivers/infiniband/hw/hfi1/mmu_rb.c
index b7a80aa1ae30..7ad30898fc19 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -53,19 +53,20 @@
#include "trace.h"
struct mmu_rb_handler {
- struct list_head list;
struct mmu_notifier mn;
- struct rb_root *root;
+ struct rb_root root;
+ void *ops_arg;
spinlock_t lock; /* protect the RB tree */
struct mmu_rb_ops *ops;
+ struct mm_struct *mm;
+ struct list_head lru_list;
+ struct work_struct del_work;
+ struct list_head del_list;
+ struct workqueue_struct *wq;
};
-static LIST_HEAD(mmu_rb_handlers);
-static DEFINE_SPINLOCK(mmu_rb_lock); /* protect mmu_rb_handlers list */
-
static unsigned long mmu_node_start(struct mmu_rb_node *);
static unsigned long mmu_node_last(struct mmu_rb_node *);
-static struct mmu_rb_handler *find_mmu_handler(struct rb_root *);
static inline void mmu_notifier_page(struct mmu_notifier *, struct mm_struct *,
unsigned long);
static inline void mmu_notifier_range_start(struct mmu_notifier *,
@@ -76,6 +77,9 @@ static void mmu_notifier_mem_invalidate(struct mmu_notifier *,
unsigned long, unsigned long);
static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *,
unsigned long, unsigned long);
+static void do_remove(struct mmu_rb_handler *handler,
+ struct list_head *del_list);
+static void handle_remove(struct work_struct *work);
static struct mmu_notifier_ops mn_opts = {
.invalidate_page = mmu_notifier_page,
@@ -95,73 +99,79 @@ static unsigned long mmu_node_last(struct mmu_rb_node *node)
return PAGE_ALIGN(node->addr + node->len) - 1;
}
-int hfi1_mmu_rb_register(struct rb_root *root, struct mmu_rb_ops *ops)
+int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
+ struct mmu_rb_ops *ops,
+ struct workqueue_struct *wq,
+ struct mmu_rb_handler **handler)
{
struct mmu_rb_handler *handlr;
-
- if (!ops->invalidate)
- return -EINVAL;
+ int ret;
handlr = kmalloc(sizeof(*handlr), GFP_KERNEL);
if (!handlr)
return -ENOMEM;
- handlr->root = root;
+ handlr->root = RB_ROOT;
handlr->ops = ops;
+ handlr->ops_arg = ops_arg;
INIT_HLIST_NODE(&handlr->mn.hlist);
spin_lock_init(&handlr->lock);
handlr->mn.ops = &mn_opts;
- spin_lock(&mmu_rb_lock);
- list_add_tail_rcu(&handlr->list, &mmu_rb_handlers);
- spin_unlock(&mmu_rb_lock);
+ handlr->mm = mm;
+ INIT_WORK(&handlr->del_work, handle_remove);
+ INIT_LIST_HEAD(&handlr->del_list);
+ INIT_LIST_HEAD(&handlr->lru_list);
+ handlr->wq = wq;
+
+ ret = mmu_notifier_register(&handlr->mn, handlr->mm);
+ if (ret) {
+ kfree(handlr);
+ return ret;
+ }
- return mmu_notifier_register(&handlr->mn, current->mm);
+ *handler = handlr;
+ return 0;
}
-void hfi1_mmu_rb_unregister(struct rb_root *root)
+void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler)
{
- struct mmu_rb_handler *handler = find_mmu_handler(root);
+ struct mmu_rb_node *rbnode;
+ struct rb_node *node;
unsigned long flags;
-
- if (!handler)
- return;
+ struct list_head del_list;
/* Unregister first so we don't get any more notifications. */
- if (current->mm)
- mmu_notifier_unregister(&handler->mn, current->mm);
+ mmu_notifier_unregister(&handler->mn, handler->mm);
- spin_lock(&mmu_rb_lock);
- list_del_rcu(&handler->list);
- spin_unlock(&mmu_rb_lock);
- synchronize_rcu();
+ /*
+ * Make sure the wq delete handler is finished running. It will not
+ * be triggered once the mmu notifiers are unregistered above.
+ */
+ flush_work(&handler->del_work);
+
+ INIT_LIST_HEAD(&del_list);
spin_lock_irqsave(&handler->lock, flags);
- if (!RB_EMPTY_ROOT(root)) {
- struct rb_node *node;
- struct mmu_rb_node *rbnode;
-
- while ((node = rb_first(root))) {
- rbnode = rb_entry(node, struct mmu_rb_node, node);
- rb_erase(node, root);
- if (handler->ops->remove)
- handler->ops->remove(root, rbnode, NULL);
- }
+ while ((node = rb_first(&handler->root))) {
+ rbnode = rb_entry(node, struct mmu_rb_node, node);
+ rb_erase(node, &handler->root);
+ /* move from LRU list to delete list */
+ list_move(&rbnode->list, &del_list);
}
spin_unlock_irqrestore(&handler->lock, flags);
+ do_remove(handler, &del_list);
+
kfree(handler);
}
-int hfi1_mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode)
+int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
+ struct mmu_rb_node *mnode)
{
- struct mmu_rb_handler *handler = find_mmu_handler(root);
struct mmu_rb_node *node;
unsigned long flags;
int ret = 0;
- if (!handler)
- return -EINVAL;
-
spin_lock_irqsave(&handler->lock, flags);
hfi1_cdbg(MMU, "Inserting node addr 0x%llx, len %u", mnode->addr,
mnode->len);
@@ -170,12 +180,13 @@ int hfi1_mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode)
ret = -EINVAL;
goto unlock;
}
- __mmu_int_rb_insert(mnode, root);
+ __mmu_int_rb_insert(mnode, &handler->root);
+ list_add(&mnode->list, &handler->lru_list);
- if (handler->ops->insert) {
- ret = handler->ops->insert(root, mnode);
- if (ret)
- __mmu_int_rb_remove(mnode, root);
+ ret = handler->ops->insert(handler->ops_arg, mnode);
+ if (ret) {
+ __mmu_int_rb_remove(mnode, &handler->root);
+ list_del(&mnode->list); /* remove from LRU list */
}
unlock:
spin_unlock_irqrestore(&handler->lock, flags);
@@ -191,10 +202,10 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler,
hfi1_cdbg(MMU, "Searching for addr 0x%llx, len %u", addr, len);
if (!handler->ops->filter) {
- node = __mmu_int_rb_iter_first(handler->root, addr,
+ node = __mmu_int_rb_iter_first(&handler->root, addr,
(addr + len) - 1);
} else {
- for (node = __mmu_int_rb_iter_first(handler->root, addr,
+ for (node = __mmu_int_rb_iter_first(&handler->root, addr,
(addr + len) - 1);
node;
node = __mmu_int_rb_iter_next(node, addr,
@@ -206,82 +217,72 @@ static struct mmu_rb_node *__mmu_rb_search(struct mmu_rb_handler *handler,
return node;
}
-/* Caller must *not* hold handler lock. */
-static void __mmu_rb_remove(struct mmu_rb_handler *handler,
- struct mmu_rb_node *node, struct mm_struct *mm)
-{
- unsigned long flags;
-
- /* Validity of handler and node pointers has been checked by caller. */
- hfi1_cdbg(MMU, "Removing node addr 0x%llx, len %u", node->addr,
- node->len);
- spin_lock_irqsave(&handler->lock, flags);
- __mmu_int_rb_remove(node, handler->root);
- spin_unlock_irqrestore(&handler->lock, flags);
-
- if (handler->ops->remove)
- handler->ops->remove(handler->root, node, mm);
-}
-
-struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *root, unsigned long addr,
- unsigned long len)
+struct mmu_rb_node *hfi1_mmu_rb_extract(struct mmu_rb_handler *handler,
+ unsigned long addr, unsigned long len)
{
- struct mmu_rb_handler *handler = find_mmu_handler(root);
struct mmu_rb_node *node;
unsigned long flags;
- if (!handler)
- return ERR_PTR(-EINVAL);
-
spin_lock_irqsave(&handler->lock, flags);
node = __mmu_rb_search(handler, addr, len);
+ if (node) {
+ __mmu_int_rb_remove(node, &handler->root);
+ list_del(&node->list); /* remove from LRU list */
+ }
spin_unlock_irqrestore(&handler->lock, flags);
return node;
}
-struct mmu_rb_node *hfi1_mmu_rb_extract(struct rb_root *root,
- unsigned long addr, unsigned long len)
+void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg)
{
- struct mmu_rb_handler *handler = find_mmu_handler(root);
- struct mmu_rb_node *node;
+ struct mmu_rb_node *rbnode, *ptr;
+ struct list_head del_list;
unsigned long flags;
+ bool stop = false;
- if (!handler)
- return ERR_PTR(-EINVAL);
+ INIT_LIST_HEAD(&del_list);
spin_lock_irqsave(&handler->lock, flags);
- node = __mmu_rb_search(handler, addr, len);
- if (node)
- __mmu_int_rb_remove(node, handler->root);
+ list_for_each_entry_safe_reverse(rbnode, ptr, &handler->lru_list,
+ list) {
+ if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg,
+ &stop)) {
+ __mmu_int_rb_remove(rbnode, &handler->root);
+ /* move from LRU list to delete list */
+ list_move(&rbnode->list, &del_list);
+ }
+ if (stop)
+ break;
+ }
spin_unlock_irqrestore(&handler->lock, flags);
- return node;
+ while (!list_empty(&del_list)) {
+ rbnode = list_first_entry(&del_list, struct mmu_rb_node, list);
+ list_del(&rbnode->list);
+ handler->ops->remove(handler->ops_arg, rbnode);
+ }
}
-void hfi1_mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node)
+/*
+ * It is up to the caller to ensure that this function does not race with the
+ * mmu invalidate notifier which may be calling the users remove callback on
+ * 'node'.
+ */
+void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
+ struct mmu_rb_node *node)
{
- struct mmu_rb_handler *handler = find_mmu_handler(root);
-
- if (!handler || !node)
- return;
-
- __mmu_rb_remove(handler, node, NULL);
-}
+ unsigned long flags;
-static struct mmu_rb_handler *find_mmu_handler(struct rb_root *root)
-{
- struct mmu_rb_handler *handler;
+ /* Validity of handler and node pointers has been checked by caller. */
+ hfi1_cdbg(MMU, "Removing node addr 0x%llx, len %u", node->addr,
+ node->len);
+ spin_lock_irqsave(&handler->lock, flags);
+ __mmu_int_rb_remove(node, &handler->root);
+ list_del(&node->list); /* remove from LRU list */
+ spin_unlock_irqrestore(&handler->lock, flags);
- rcu_read_lock();
- list_for_each_entry_rcu(handler, &mmu_rb_handlers, list) {
- if (handler->root == root)
- goto unlock;
- }
- handler = NULL;
-unlock:
- rcu_read_unlock();
- return handler;
+ handler->ops->remove(handler->ops_arg, node);
}
static inline void mmu_notifier_page(struct mmu_notifier *mn,
@@ -304,9 +305,10 @@ static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn,
{
struct mmu_rb_handler *handler =
container_of(mn, struct mmu_rb_handler, mn);
- struct rb_root *root = handler->root;
+ struct rb_root *root = &handler->root;
struct mmu_rb_node *node, *ptr = NULL;
unsigned long flags;
+ bool added = false;
spin_lock_irqsave(&handler->lock, flags);
for (node = __mmu_int_rb_iter_first(root, start, end - 1);
@@ -315,11 +317,53 @@ static void mmu_notifier_mem_invalidate(struct mmu_notifier *mn,
ptr = __mmu_int_rb_iter_next(node, start, end - 1);
hfi1_cdbg(MMU, "Invalidating node addr 0x%llx, len %u",
node->addr, node->len);
- if (handler->ops->invalidate(root, node)) {
+ if (handler->ops->invalidate(handler->ops_arg, node)) {
__mmu_int_rb_remove(node, root);
- if (handler->ops->remove)
- handler->ops->remove(root, node, mm);
+ /* move from LRU list to delete list */
+ list_move(&node->list, &handler->del_list);
+ added = true;
}
}
spin_unlock_irqrestore(&handler->lock, flags);
+
+ if (added)
+ queue_work(handler->wq, &handler->del_work);
+}
+
+/*
+ * Call the remove function for the given handler and the list. This
+ * is expected to be called with a delete list extracted from handler.
+ * The caller should not be holding the handler lock.
+ */
+static void do_remove(struct mmu_rb_handler *handler,
+ struct list_head *del_list)
+{
+ struct mmu_rb_node *node;
+
+ while (!list_empty(del_list)) {
+ node = list_first_entry(del_list, struct mmu_rb_node, list);
+ list_del(&node->list);
+ handler->ops->remove(handler->ops_arg, node);
+ }
+}
+
+/*
+ * Work queue function to remove all nodes that have been queued up to
+ * be removed. The key feature is that mm->mmap_sem is not being held
+ * and the remove callback can sleep while taking it, if needed.
+ */
+static void handle_remove(struct work_struct *work)
+{
+ struct mmu_rb_handler *handler = container_of(work,
+ struct mmu_rb_handler,
+ del_work);
+ struct list_head del_list;
+ unsigned long flags;
+
+ /* remove anything that is queued to get removed */
+ spin_lock_irqsave(&handler->lock, flags);
+ list_replace_init(&handler->del_list, &del_list);
+ spin_unlock_irqrestore(&handler->lock, flags);
+
+ do_remove(handler, &del_list);
}
diff --git a/drivers/infiniband/hw/hfi1/mmu_rb.h b/drivers/infiniband/hw/hfi1/mmu_rb.h
index 7a57b9c49d27..754f6ebf13fb 100644
--- a/drivers/infiniband/hw/hfi1/mmu_rb.h
+++ b/drivers/infiniband/hw/hfi1/mmu_rb.h
@@ -54,23 +54,34 @@ struct mmu_rb_node {
unsigned long len;
unsigned long __last;
struct rb_node node;
+ struct list_head list;
};
+/*
+ * NOTE: filter, insert, invalidate, and evict must not sleep. Only remove is
+ * allowed to sleep.
+ */
struct mmu_rb_ops {
- bool (*filter)(struct mmu_rb_node *, unsigned long, unsigned long);
- int (*insert)(struct rb_root *, struct mmu_rb_node *);
- void (*remove)(struct rb_root *, struct mmu_rb_node *,
- struct mm_struct *);
- int (*invalidate)(struct rb_root *, struct mmu_rb_node *);
+ bool (*filter)(struct mmu_rb_node *node, unsigned long addr,
+ unsigned long len);
+ int (*insert)(void *ops_arg, struct mmu_rb_node *mnode);
+ void (*remove)(void *ops_arg, struct mmu_rb_node *mnode);
+ int (*invalidate)(void *ops_arg, struct mmu_rb_node *node);
+ int (*evict)(void *ops_arg, struct mmu_rb_node *mnode,
+ void *evict_arg, bool *stop);
};
-int hfi1_mmu_rb_register(struct rb_root *root, struct mmu_rb_ops *ops);
-void hfi1_mmu_rb_unregister(struct rb_root *);
-int hfi1_mmu_rb_insert(struct rb_root *, struct mmu_rb_node *);
-void hfi1_mmu_rb_remove(struct rb_root *, struct mmu_rb_node *);
-struct mmu_rb_node *hfi1_mmu_rb_search(struct rb_root *, unsigned long,
- unsigned long);
-struct mmu_rb_node *hfi1_mmu_rb_extract(struct rb_root *, unsigned long,
- unsigned long);
+int hfi1_mmu_rb_register(void *ops_arg, struct mm_struct *mm,
+ struct mmu_rb_ops *ops,
+ struct workqueue_struct *wq,
+ struct mmu_rb_handler **handler);
+void hfi1_mmu_rb_unregister(struct mmu_rb_handler *handler);
+int hfi1_mmu_rb_insert(struct mmu_rb_handler *handler,
+ struct mmu_rb_node *mnode);
+void hfi1_mmu_rb_evict(struct mmu_rb_handler *handler, void *evict_arg);
+void hfi1_mmu_rb_remove(struct mmu_rb_handler *handler,
+ struct mmu_rb_node *mnode);
+struct mmu_rb_node *hfi1_mmu_rb_extract(struct mmu_rb_handler *handler,
+ unsigned long addr, unsigned long len);
#endif /* _HFI1_MMU_RB_H */
diff --git a/drivers/infiniband/hw/hfi1/pcie.c b/drivers/infiniband/hw/hfi1/pcie.c
index 0bac21e6a658..89c68da1c273 100644
--- a/drivers/infiniband/hw/hfi1/pcie.c
+++ b/drivers/infiniband/hw/hfi1/pcie.c
@@ -679,6 +679,10 @@ static uint pcie_pset = UNSET_PSET;
module_param(pcie_pset, uint, S_IRUGO);
MODULE_PARM_DESC(pcie_pset, "PCIe Eq Pset value to use, range is 0-10");
+static uint pcie_ctle = 1; /* discrete on, integrated off */
+module_param(pcie_ctle, uint, S_IRUGO);
+MODULE_PARM_DESC(pcie_ctle, "PCIe static CTLE mode, bit 0 - discrete on/off, bit 1 - integrated on/off");
+
/* equalization columns */
#define PREC 0
#define ATTN 1
@@ -716,6 +720,36 @@ static const u8 integrated_preliminary_eq[11][3] = {
{ 0x00, 0x1e, 0x0a }, /* p10 */
};
+static const u8 discrete_ctle_tunings[11][4] = {
+ /* DC LF HF BW */
+ { 0x48, 0x0b, 0x04, 0x04 }, /* p0 */
+ { 0x60, 0x05, 0x0f, 0x0a }, /* p1 */
+ { 0x50, 0x09, 0x06, 0x06 }, /* p2 */
+ { 0x68, 0x05, 0x0f, 0x0a }, /* p3 */
+ { 0x80, 0x05, 0x0f, 0x0a }, /* p4 */
+ { 0x70, 0x05, 0x0f, 0x0a }, /* p5 */
+ { 0x68, 0x05, 0x0f, 0x0a }, /* p6 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p7 */
+ { 0x48, 0x09, 0x06, 0x06 }, /* p8 */
+ { 0x60, 0x05, 0x0f, 0x0a }, /* p9 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p10 */
+};
+
+static const u8 integrated_ctle_tunings[11][4] = {
+ /* DC LF HF BW */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p0 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p1 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p2 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p3 */
+ { 0x58, 0x0a, 0x05, 0x05 }, /* p4 */
+ { 0x48, 0x0a, 0x05, 0x05 }, /* p5 */
+ { 0x40, 0x0a, 0x05, 0x05 }, /* p6 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p7 */
+ { 0x38, 0x0f, 0x00, 0x00 }, /* p8 */
+ { 0x38, 0x09, 0x06, 0x06 }, /* p9 */
+ { 0x38, 0x0e, 0x01, 0x01 }, /* p10 */
+};
+
/* helper to format the value to write to hardware */
#define eq_value(pre, curr, post) \
((((u32)(pre)) << \
@@ -951,11 +985,14 @@ int do_pcie_gen3_transition(struct hfi1_devdata *dd)
u32 status, err;
int ret;
int do_retry, retry_count = 0;
+ int intnum = 0;
uint default_pset;
u16 target_vector, target_speed;
u16 lnkctl2, vendor;
u8 div;
const u8 (*eq)[3];
+ const u8 (*ctle_tunings)[4];
+ uint static_ctle_mode;
int return_error = 0;
/* PCIe Gen3 is for the ASIC only */
@@ -1089,6 +1126,9 @@ retry:
div = 3;
eq = discrete_preliminary_eq;
default_pset = DEFAULT_DISCRETE_PSET;
+ ctle_tunings = discrete_ctle_tunings;
+ /* bit 0 - discrete on/off */
+ static_ctle_mode = pcie_ctle & 0x1;
} else {
/* 400mV, FS=29, LF = 9 */
fs = 29;
@@ -1096,6 +1136,9 @@ retry:
div = 1;
eq = integrated_preliminary_eq;
default_pset = DEFAULT_MCP_PSET;
+ ctle_tunings = integrated_ctle_tunings;
+ /* bit 1 - integrated on/off */
+ static_ctle_mode = (pcie_ctle >> 1) & 0x1;
}
pci_write_config_dword(dd->pcidev, PCIE_CFG_REG_PL101,
(fs <<
@@ -1135,16 +1178,33 @@ retry:
* step 5c: Program gasket interrupts
*/
/* set the Rx Bit Rate to REFCLK ratio */
- write_gasket_interrupt(dd, 0, 0x0006, 0x0050);
+ write_gasket_interrupt(dd, intnum++, 0x0006, 0x0050);
/* disable pCal for PCIe Gen3 RX equalization */
- write_gasket_interrupt(dd, 1, 0x0026, 0x5b01);
+ /* select adaptive or static CTLE */
+ write_gasket_interrupt(dd, intnum++, 0x0026,
+ 0x5b01 | (static_ctle_mode << 3));
/*
* Enable iCal for PCIe Gen3 RX equalization, and set which
* evaluation of RX_EQ_EVAL will launch the iCal procedure.
*/
- write_gasket_interrupt(dd, 2, 0x0026, 0x5202);
+ write_gasket_interrupt(dd, intnum++, 0x0026, 0x5202);
+
+ if (static_ctle_mode) {
+ /* apply static CTLE tunings */
+ u8 pcie_dc, pcie_lf, pcie_hf, pcie_bw;
+
+ pcie_dc = ctle_tunings[pcie_pset][0];
+ pcie_lf = ctle_tunings[pcie_pset][1];
+ pcie_hf = ctle_tunings[pcie_pset][2];
+ pcie_bw = ctle_tunings[pcie_pset][3];
+ write_gasket_interrupt(dd, intnum++, 0x0026, 0x0200 | pcie_dc);
+ write_gasket_interrupt(dd, intnum++, 0x0026, 0x0100 | pcie_lf);
+ write_gasket_interrupt(dd, intnum++, 0x0026, 0x0000 | pcie_hf);
+ write_gasket_interrupt(dd, intnum++, 0x0026, 0x5500 | pcie_bw);
+ }
+
/* terminate list */
- write_gasket_interrupt(dd, 3, 0x0000, 0x0000);
+ write_gasket_interrupt(dd, intnum++, 0x0000, 0x0000);
/*
* step 5d: program XMT margin
diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
index d4022450b73f..ac1bf4a73571 100644
--- a/drivers/infiniband/hw/hfi1/pio.c
+++ b/drivers/infiniband/hw/hfi1/pio.c
@@ -1952,13 +1952,17 @@ int init_pervl_scs(struct hfi1_devdata *dd)
dd->vld[15].sc = sc_alloc(dd, SC_VL15,
dd->rcd[0]->rcvhdrqentsize, dd->node);
if (!dd->vld[15].sc)
- goto nomem;
+ return -ENOMEM;
+
hfi1_init_ctxt(dd->vld[15].sc);
dd->vld[15].mtu = enum_to_mtu(OPA_MTU_2048);
- dd->kernel_send_context = kmalloc_node(dd->num_send_contexts *
+ dd->kernel_send_context = kzalloc_node(dd->num_send_contexts *
sizeof(struct send_context *),
GFP_KERNEL, dd->node);
+ if (!dd->kernel_send_context)
+ goto freesc15;
+
dd->kernel_send_context[0] = dd->vld[15].sc;
for (i = 0; i < num_vls; i++) {
@@ -2010,12 +2014,21 @@ int init_pervl_scs(struct hfi1_devdata *dd)
if (pio_map_init(dd, ppd->port - 1, num_vls, NULL))
goto nomem;
return 0;
+
nomem:
- sc_free(dd->vld[15].sc);
- for (i = 0; i < num_vls; i++)
+ for (i = 0; i < num_vls; i++) {
sc_free(dd->vld[i].sc);
+ dd->vld[i].sc = NULL;
+ }
+
for (i = num_vls; i < INIT_SC_PER_VL * num_vls; i++)
sc_free(dd->kernel_send_context[i + 1]);
+
+ kfree(dd->kernel_send_context);
+ dd->kernel_send_context = NULL;
+
+freesc15:
+ sc_free(dd->vld[15].sc);
return -ENOMEM;
}
diff --git a/drivers/infiniband/hw/hfi1/platform.c b/drivers/infiniband/hw/hfi1/platform.c
index 03df9322f862..965c8aef0c60 100644
--- a/drivers/infiniband/hw/hfi1/platform.c
+++ b/drivers/infiniband/hw/hfi1/platform.c
@@ -537,20 +537,6 @@ static void apply_tunings(
u8 precur = 0, attn = 0, postcur = 0, external_device_config = 0;
u8 *cache = ppd->qsfp_info.cache;
- /* Enable external device config if channel is limiting active */
- read_8051_config(ppd->dd, LINK_OPTIMIZATION_SETTINGS,
- GENERAL_CONFIG, &config_data);
- config_data &= ~(0xff << ENABLE_EXT_DEV_CONFIG_SHIFT);
- config_data |= ((u32)limiting_active << ENABLE_EXT_DEV_CONFIG_SHIFT);
- ret = load_8051_config(ppd->dd, LINK_OPTIMIZATION_SETTINGS,
- GENERAL_CONFIG, config_data);
- if (ret != HCMD_SUCCESS)
- dd_dev_err(
- ppd->dd,
- "%s: Failed to set enable external device config\n",
- __func__);
-
- config_data = 0; /* re-init */
/* Pass tuning method to 8051 */
read_8051_config(ppd->dd, LINK_TUNING_PARAMETERS, GENERAL_CONFIG,
&config_data);
@@ -638,9 +624,13 @@ static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
if (ret)
return ret;
+ /*
+ * We'll change the QSFP memory contents from here on out, thus we set a
+ * flag here to remind ourselves to reset the QSFP module. This prevents
+ * reuse of stale settings established in our previous pass through.
+ */
if (ppd->qsfp_info.reset_needed) {
reset_qsfp(ppd);
- ppd->qsfp_info.reset_needed = 0;
refresh_qsfp_cache(ppd, &ppd->qsfp_info);
} else {
ppd->qsfp_info.reset_needed = 1;
diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c
index 1a942ffba4cb..a5aa3517e7d5 100644
--- a/drivers/infiniband/hw/hfi1/qp.c
+++ b/drivers/infiniband/hw/hfi1/qp.c
@@ -52,6 +52,7 @@
#include <linux/seq_file.h>
#include <rdma/rdma_vt.h>
#include <rdma/rdmavt_qp.h>
+#include <rdma/ib_verbs.h>
#include "hfi.h"
#include "qp.h"
@@ -115,6 +116,66 @@ static const u16 credit_table[31] = {
32768 /* 1E */
};
+const struct rvt_operation_params hfi1_post_parms[RVT_OPERATION_MAX] = {
+[IB_WR_RDMA_WRITE] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_RDMA_READ] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC,
+},
+
+[IB_WR_ATOMIC_CMP_AND_SWP] = {
+ .length = sizeof(struct ib_atomic_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE,
+},
+
+[IB_WR_ATOMIC_FETCH_AND_ADD] = {
+ .length = sizeof(struct ib_atomic_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE,
+},
+
+[IB_WR_RDMA_WRITE_WITH_IMM] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_SEND] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) |
+ BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_SEND_WITH_IMM] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) |
+ BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_REG_MR] = {
+ .length = sizeof(struct ib_reg_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_LOCAL,
+},
+
+[IB_WR_LOCAL_INV] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_LOCAL,
+},
+
+[IB_WR_SEND_WITH_INV] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+},
+
+};
+
static void flush_tx_list(struct rvt_qp *qp)
{
struct hfi1_qp_priv *priv = qp->priv;
@@ -745,8 +806,9 @@ void *qp_priv_alloc(struct rvt_dev_info *rdi, struct rvt_qp *qp,
priv->owner = qp;
- priv->s_hdr = kzalloc_node(sizeof(*priv->s_hdr), gfp, rdi->dparms.node);
- if (!priv->s_hdr) {
+ priv->s_ahg = kzalloc_node(sizeof(*priv->s_ahg), gfp,
+ rdi->dparms.node);
+ if (!priv->s_ahg) {
kfree(priv);
return ERR_PTR(-ENOMEM);
}
@@ -759,7 +821,7 @@ void qp_priv_free(struct rvt_dev_info *rdi, struct rvt_qp *qp)
{
struct hfi1_qp_priv *priv = qp->priv;
- kfree(priv->s_hdr);
+ kfree(priv->s_ahg);
kfree(priv);
}
diff --git a/drivers/infiniband/hw/hfi1/qp.h b/drivers/infiniband/hw/hfi1/qp.h
index e7bc8d6cf681..587d84d65bb8 100644
--- a/drivers/infiniband/hw/hfi1/qp.h
+++ b/drivers/infiniband/hw/hfi1/qp.h
@@ -54,6 +54,8 @@
extern unsigned int hfi1_qp_table_size;
+extern const struct rvt_operation_params hfi1_post_parms[];
+
/*
* free_ahg - clear ahg from QP
*/
@@ -61,7 +63,7 @@ static inline void clear_ahg(struct rvt_qp *qp)
{
struct hfi1_qp_priv *priv = qp->priv;
- priv->s_hdr->ahgcount = 0;
+ priv->s_ahg->ahgcount = 0;
qp->s_flags &= ~(RVT_S_AHG_VALID | RVT_S_AHG_CLEAR);
if (priv->s_sde && qp->s_ahgidx >= 0)
sdma_ahg_free(priv->s_sde, qp->s_ahgidx);
diff --git a/drivers/infiniband/hw/hfi1/qsfp.c b/drivers/infiniband/hw/hfi1/qsfp.c
index 9fb561682c66..a207717ade2a 100644
--- a/drivers/infiniband/hw/hfi1/qsfp.c
+++ b/drivers/infiniband/hw/hfi1/qsfp.c
@@ -50,46 +50,285 @@
#include <linux/vmalloc.h>
#include "hfi.h"
-#include "twsi.h"
+
+/* for the given bus number, return the CSR for reading an i2c line */
+static inline u32 i2c_in_csr(u32 bus_num)
+{
+ return bus_num ? ASIC_QSFP2_IN : ASIC_QSFP1_IN;
+}
+
+/* for the given bus number, return the CSR for writing an i2c line */
+static inline u32 i2c_oe_csr(u32 bus_num)
+{
+ return bus_num ? ASIC_QSFP2_OE : ASIC_QSFP1_OE;
+}
+
+static void hfi1_setsda(void *data, int state)
+{
+ struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
+ struct hfi1_devdata *dd = bus->controlling_dd;
+ u64 reg;
+ u32 target_oe;
+
+ target_oe = i2c_oe_csr(bus->num);
+ reg = read_csr(dd, target_oe);
+ /*
+ * The OE bit value is inverted and connected to the pin. When
+ * OE is 0 the pin is left to be pulled up, when the OE is 1
+ * the pin is driven low. This matches the "open drain" or "open
+ * collector" convention.
+ */
+ if (state)
+ reg &= ~QSFP_HFI0_I2CDAT;
+ else
+ reg |= QSFP_HFI0_I2CDAT;
+ write_csr(dd, target_oe, reg);
+ /* do a read to force the write into the chip */
+ (void)read_csr(dd, target_oe);
+}
+
+static void hfi1_setscl(void *data, int state)
+{
+ struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
+ struct hfi1_devdata *dd = bus->controlling_dd;
+ u64 reg;
+ u32 target_oe;
+
+ target_oe = i2c_oe_csr(bus->num);
+ reg = read_csr(dd, target_oe);
+ /*
+ * The OE bit value is inverted and connected to the pin. When
+ * OE is 0 the pin is left to be pulled up, when the OE is 1
+ * the pin is driven low. This matches the "open drain" or "open
+ * collector" convention.
+ */
+ if (state)
+ reg &= ~QSFP_HFI0_I2CCLK;
+ else
+ reg |= QSFP_HFI0_I2CCLK;
+ write_csr(dd, target_oe, reg);
+ /* do a read to force the write into the chip */
+ (void)read_csr(dd, target_oe);
+}
+
+static int hfi1_getsda(void *data)
+{
+ struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
+ u64 reg;
+ u32 target_in;
+
+ hfi1_setsda(data, 1); /* clear OE so we do not pull line down */
+ udelay(2); /* 1us pull up + 250ns hold */
+
+ target_in = i2c_in_csr(bus->num);
+ reg = read_csr(bus->controlling_dd, target_in);
+ return !!(reg & QSFP_HFI0_I2CDAT);
+}
+
+static int hfi1_getscl(void *data)
+{
+ struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
+ u64 reg;
+ u32 target_in;
+
+ hfi1_setscl(data, 1); /* clear OE so we do not pull line down */
+ udelay(2); /* 1us pull up + 250ns hold */
+
+ target_in = i2c_in_csr(bus->num);
+ reg = read_csr(bus->controlling_dd, target_in);
+ return !!(reg & QSFP_HFI0_I2CCLK);
+}
/*
- * QSFP support for hfi driver, using "Two Wire Serial Interface" driver
- * in twsi.c
+ * Allocate and initialize the given i2c bus number.
+ * Returns NULL on failure.
*/
-#define I2C_MAX_RETRY 4
+static struct hfi1_i2c_bus *init_i2c_bus(struct hfi1_devdata *dd,
+ struct hfi1_asic_data *ad, int num)
+{
+ struct hfi1_i2c_bus *bus;
+ int ret;
+
+ bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return NULL;
+
+ bus->controlling_dd = dd;
+ bus->num = num; /* our bus number */
+
+ bus->algo.setsda = hfi1_setsda;
+ bus->algo.setscl = hfi1_setscl;
+ bus->algo.getsda = hfi1_getsda;
+ bus->algo.getscl = hfi1_getscl;
+ bus->algo.udelay = 5;
+ bus->algo.timeout = usecs_to_jiffies(50);
+ bus->algo.data = bus;
+
+ bus->adapter.owner = THIS_MODULE;
+ bus->adapter.algo_data = &bus->algo;
+ bus->adapter.dev.parent = &dd->pcidev->dev;
+ snprintf(bus->adapter.name, sizeof(bus->adapter.name),
+ "hfi1_i2c%d", num);
+
+ ret = i2c_bit_add_bus(&bus->adapter);
+ if (ret) {
+ dd_dev_info(dd, "%s: unable to add i2c bus %d, err %d\n",
+ __func__, num, ret);
+ kfree(bus);
+ return NULL;
+ }
+
+ return bus;
+}
/*
- * Raw i2c write. No set-up or lock checking.
+ * Initialize i2c buses.
+ * Return 0 on success, -errno on error.
*/
-static int __i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr,
- int offset, void *bp, int len)
+int set_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad)
{
- struct hfi1_devdata *dd = ppd->dd;
- int ret, cnt;
- u8 *buff = bp;
+ ad->i2c_bus0 = init_i2c_bus(dd, ad, 0);
+ ad->i2c_bus1 = init_i2c_bus(dd, ad, 1);
+ if (!ad->i2c_bus0 || !ad->i2c_bus1)
+ return -ENOMEM;
+ return 0;
+};
- cnt = 0;
- while (cnt < len) {
- int wlen = len - cnt;
+static void clean_i2c_bus(struct hfi1_i2c_bus *bus)
+{
+ if (bus) {
+ i2c_del_adapter(&bus->adapter);
+ kfree(bus);
+ }
+}
- ret = hfi1_twsi_blk_wr(dd, target, i2c_addr, offset,
- buff + cnt, wlen);
- if (ret) {
- /* hfi1_twsi_blk_wr() 1 for error, else 0 */
- return -EIO;
- }
- offset += wlen;
- cnt += wlen;
+void clean_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad)
+{
+ clean_i2c_bus(ad->i2c_bus0);
+ ad->i2c_bus0 = NULL;
+ clean_i2c_bus(ad->i2c_bus1);
+ ad->i2c_bus1 = NULL;
+}
+
+static int i2c_bus_write(struct hfi1_devdata *dd, struct hfi1_i2c_bus *i2c,
+ u8 slave_addr, int offset, int offset_size,
+ u8 *data, u16 len)
+{
+ int ret;
+ int num_msgs;
+ u8 offset_bytes[2];
+ struct i2c_msg msgs[2];
+
+ switch (offset_size) {
+ case 0:
+ num_msgs = 1;
+ msgs[0].addr = slave_addr;
+ msgs[0].flags = 0;
+ msgs[0].len = len;
+ msgs[0].buf = data;
+ break;
+ case 2:
+ offset_bytes[1] = (offset >> 8) & 0xff;
+ /* fall through */
+ case 1:
+ num_msgs = 2;
+ offset_bytes[0] = offset & 0xff;
+
+ msgs[0].addr = slave_addr;
+ msgs[0].flags = 0;
+ msgs[0].len = offset_size;
+ msgs[0].buf = offset_bytes;
+
+ msgs[1].addr = slave_addr;
+ msgs[1].flags = I2C_M_NOSTART,
+ msgs[1].len = len;
+ msgs[1].buf = data;
+ break;
+ default:
+ return -EINVAL;
}
- /* Must wait min 20us between qsfp i2c transactions */
- udelay(20);
+ i2c->controlling_dd = dd;
+ ret = i2c_transfer(&i2c->adapter, msgs, num_msgs);
+ if (ret != num_msgs) {
+ dd_dev_err(dd, "%s: bus %d, i2c slave 0x%x, offset 0x%x, len 0x%x; write failed, ret %d\n",
+ __func__, i2c->num, slave_addr, offset, len, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ return 0;
+}
+
+static int i2c_bus_read(struct hfi1_devdata *dd, struct hfi1_i2c_bus *bus,
+ u8 slave_addr, int offset, int offset_size,
+ u8 *data, u16 len)
+{
+ int ret;
+ int num_msgs;
+ u8 offset_bytes[2];
+ struct i2c_msg msgs[2];
+
+ switch (offset_size) {
+ case 0:
+ num_msgs = 1;
+ msgs[0].addr = slave_addr;
+ msgs[0].flags = I2C_M_RD;
+ msgs[0].len = len;
+ msgs[0].buf = data;
+ break;
+ case 2:
+ offset_bytes[1] = (offset >> 8) & 0xff;
+ /* fall through */
+ case 1:
+ num_msgs = 2;
+ offset_bytes[0] = offset & 0xff;
+
+ msgs[0].addr = slave_addr;
+ msgs[0].flags = 0;
+ msgs[0].len = offset_size;
+ msgs[0].buf = offset_bytes;
+
+ msgs[1].addr = slave_addr;
+ msgs[1].flags = I2C_M_RD,
+ msgs[1].len = len;
+ msgs[1].buf = data;
+ break;
+ default:
+ return -EINVAL;
+ }
- return cnt;
+ bus->controlling_dd = dd;
+ ret = i2c_transfer(&bus->adapter, msgs, num_msgs);
+ if (ret != num_msgs) {
+ dd_dev_err(dd, "%s: bus %d, i2c slave 0x%x, offset 0x%x, len 0x%x; read failed, ret %d\n",
+ __func__, bus->num, slave_addr, offset, len, ret);
+ return ret < 0 ? ret : -EIO;
+ }
+ return 0;
+}
+
+/*
+ * Raw i2c write. No set-up or lock checking.
+ *
+ * Return 0 on success, -errno on error.
+ */
+static int __i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr,
+ int offset, void *bp, int len)
+{
+ struct hfi1_devdata *dd = ppd->dd;
+ struct hfi1_i2c_bus *bus;
+ u8 slave_addr;
+ int offset_size;
+
+ bus = target ? dd->asic_data->i2c_bus1 : dd->asic_data->i2c_bus0;
+ slave_addr = (i2c_addr & 0xff) >> 1; /* convert to 7-bit addr */
+ offset_size = (i2c_addr >> 8) & 0x3;
+ return i2c_bus_write(dd, bus, slave_addr, offset, offset_size, bp, len);
}
/*
* Caller must hold the i2c chain resource.
+ *
+ * Return number of bytes written, or -errno.
*/
int i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
void *bp, int len)
@@ -99,63 +338,36 @@ int i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
return -EACCES;
- /* make sure the TWSI bus is in a sane state */
- ret = hfi1_twsi_reset(ppd->dd, target);
- if (ret) {
- hfi1_dev_porterr(ppd->dd, ppd->port,
- "I2C chain %d write interface reset failed\n",
- target);
+ ret = __i2c_write(ppd, target, i2c_addr, offset, bp, len);
+ if (ret)
return ret;
- }
- return __i2c_write(ppd, target, i2c_addr, offset, bp, len);
+ return len;
}
/*
* Raw i2c read. No set-up or lock checking.
+ *
+ * Return 0 on success, -errno on error.
*/
static int __i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr,
int offset, void *bp, int len)
{
struct hfi1_devdata *dd = ppd->dd;
- int ret, cnt, pass = 0;
- int orig_offset = offset;
-
- cnt = 0;
- while (cnt < len) {
- int rlen = len - cnt;
-
- ret = hfi1_twsi_blk_rd(dd, target, i2c_addr, offset,
- bp + cnt, rlen);
- /* Some QSFP's fail first try. Retry as experiment */
- if (ret && cnt == 0 && ++pass < I2C_MAX_RETRY)
- continue;
- if (ret) {
- /* hfi1_twsi_blk_rd() 1 for error, else 0 */
- ret = -EIO;
- goto exit;
- }
- offset += rlen;
- cnt += rlen;
- }
-
- ret = cnt;
-
-exit:
- if (ret < 0) {
- hfi1_dev_porterr(dd, ppd->port,
- "I2C chain %d read failed, addr 0x%x, offset 0x%x, len %d\n",
- target, i2c_addr, orig_offset, len);
- }
-
- /* Must wait min 20us between qsfp i2c transactions */
- udelay(20);
-
- return ret;
+ struct hfi1_i2c_bus *bus;
+ u8 slave_addr;
+ int offset_size;
+
+ bus = target ? dd->asic_data->i2c_bus1 : dd->asic_data->i2c_bus0;
+ slave_addr = (i2c_addr & 0xff) >> 1; /* convert to 7-bit addr */
+ offset_size = (i2c_addr >> 8) & 0x3;
+ return i2c_bus_read(dd, bus, slave_addr, offset, offset_size, bp, len);
}
/*
* Caller must hold the i2c chain resource.
+ *
+ * Return number of bytes read, or -errno.
*/
int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
void *bp, int len)
@@ -165,16 +377,11 @@ int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
return -EACCES;
- /* make sure the TWSI bus is in a sane state */
- ret = hfi1_twsi_reset(ppd->dd, target);
- if (ret) {
- hfi1_dev_porterr(ppd->dd, ppd->port,
- "I2C chain %d read interface reset failed\n",
- target);
+ ret = __i2c_read(ppd, target, i2c_addr, offset, bp, len);
+ if (ret)
return ret;
- }
- return __i2c_read(ppd, target, i2c_addr, offset, bp, len);
+ return len;
}
/*
@@ -182,6 +389,8 @@ int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
* by writing @addr = ((256 * n) + m)
*
* Caller must hold the i2c chain resource.
+ *
+ * Return number of bytes written or -errno.
*/
int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int len)
@@ -189,21 +398,12 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int count = 0;
int offset;
int nwrite;
- int ret;
+ int ret = 0;
u8 page;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
return -EACCES;
- /* make sure the TWSI bus is in a sane state */
- ret = hfi1_twsi_reset(ppd->dd, target);
- if (ret) {
- hfi1_dev_porterr(ppd->dd, ppd->port,
- "QSFP chain %d write interface reset failed\n",
- target);
- return ret;
- }
-
while (count < len) {
/*
* Set the qsfp page based on a zero-based address
@@ -213,11 +413,12 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1);
- if (ret != 1) {
+ /* QSFPs require a 5-10msec delay after write operations */
+ mdelay(5);
+ if (ret) {
hfi1_dev_porterr(ppd->dd, ppd->port,
"QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
target, ret);
- ret = -EIO;
break;
}
@@ -229,11 +430,13 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
offset, bp + count, nwrite);
- if (ret <= 0) /* stop on error or nothing written */
+ /* QSFPs require a 5-10msec delay after write operations */
+ mdelay(5);
+ if (ret) /* stop on error */
break;
- count += ret;
- addr += ret;
+ count += nwrite;
+ addr += nwrite;
}
if (ret < 0)
@@ -243,7 +446,7 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
/*
* Perform a stand-alone single QSFP write. Acquire the resource, do the
- * read, then release the resource.
+ * write, then release the resource.
*/
int one_qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int len)
@@ -266,6 +469,8 @@ int one_qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
* by reading @addr = ((256 * n) + m)
*
* Caller must hold the i2c chain resource.
+ *
+ * Return the number of bytes read or -errno.
*/
int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int len)
@@ -273,21 +478,12 @@ int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int count = 0;
int offset;
int nread;
- int ret;
+ int ret = 0;
u8 page;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
return -EACCES;
- /* make sure the TWSI bus is in a sane state */
- ret = hfi1_twsi_reset(ppd->dd, target);
- if (ret) {
- hfi1_dev_porterr(ppd->dd, ppd->port,
- "QSFP chain %d read interface reset failed\n",
- target);
- return ret;
- }
-
while (count < len) {
/*
* Set the qsfp page based on a zero-based address
@@ -296,11 +492,12 @@ int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
page = (u8)(addr / QSFP_PAGESIZE);
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1);
- if (ret != 1) {
+ /* QSFPs require a 5-10msec delay after write operations */
+ mdelay(5);
+ if (ret) {
hfi1_dev_porterr(ppd->dd, ppd->port,
"QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
target, ret);
- ret = -EIO;
break;
}
@@ -310,15 +507,13 @@ int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
if (((addr % QSFP_RW_BOUNDARY) + nread) > QSFP_RW_BOUNDARY)
nread = QSFP_RW_BOUNDARY - (addr % QSFP_RW_BOUNDARY);
- /* QSFPs require a 5-10msec delay after write operations */
- mdelay(5);
ret = __i2c_read(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
offset, bp + count, nread);
- if (ret <= 0) /* stop on error or nothing read */
+ if (ret) /* stop on error */
break;
- count += ret;
- addr += ret;
+ count += nread;
+ addr += nread;
}
if (ret < 0)
diff --git a/drivers/infiniband/hw/hfi1/qsfp.h b/drivers/infiniband/hw/hfi1/qsfp.h
index dadc66c442b9..69275ebd9597 100644
--- a/drivers/infiniband/hw/hfi1/qsfp.h
+++ b/drivers/infiniband/hw/hfi1/qsfp.h
@@ -238,3 +238,6 @@ int one_qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int len);
int one_qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
int len);
+struct hfi1_asic_data;
+int set_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad);
+void clean_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad);
diff --git a/drivers/infiniband/hw/hfi1/rc.c b/drivers/infiniband/hw/hfi1/rc.c
index 792f15eb8efe..5da190e6011b 100644
--- a/drivers/infiniband/hw/hfi1/rc.c
+++ b/drivers/infiniband/hw/hfi1/rc.c
@@ -477,6 +477,37 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
qp->s_flags |= RVT_S_WAIT_FENCE;
goto bail;
}
+ /*
+ * Local operations are processed immediately
+ * after all prior requests have completed
+ */
+ if (wqe->wr.opcode == IB_WR_REG_MR ||
+ wqe->wr.opcode == IB_WR_LOCAL_INV) {
+ int local_ops = 0;
+ int err = 0;
+
+ if (qp->s_last != qp->s_cur)
+ goto bail;
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ if (++qp->s_tail == qp->s_size)
+ qp->s_tail = 0;
+ if (!(wqe->wr.send_flags &
+ RVT_SEND_COMPLETION_ONLY)) {
+ err = rvt_invalidate_rkey(
+ qp,
+ wqe->wr.ex.invalidate_rkey);
+ local_ops = 1;
+ }
+ hfi1_send_complete(qp, wqe,
+ err ? IB_WC_LOC_PROT_ERR
+ : IB_WC_SUCCESS);
+ if (local_ops)
+ atomic_dec(&qp->local_ops_pending);
+ qp->s_hdrwords = 0;
+ goto done_free_tx;
+ }
+
newreq = 1;
qp->s_psn = wqe->psn;
}
@@ -491,6 +522,7 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
switch (wqe->wr.opcode) {
case IB_WR_SEND:
case IB_WR_SEND_WITH_IMM:
+ case IB_WR_SEND_WITH_INV:
/* If no credit, return. */
if (!(qp->s_flags & RVT_S_UNLIMITED_CREDIT) &&
cmp_msn(wqe->ssn, qp->s_lsn + 1) > 0) {
@@ -504,11 +536,17 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
}
if (wqe->wr.opcode == IB_WR_SEND) {
qp->s_state = OP(SEND_ONLY);
- } else {
+ } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_state = OP(SEND_ONLY_WITH_IMMEDIATE);
/* Immediate data comes after the BTH */
ohdr->u.imm_data = wqe->wr.ex.imm_data;
hwords += 1;
+ } else {
+ qp->s_state = OP(SEND_ONLY_WITH_INVALIDATE);
+ /* Invalidate rkey comes after the BTH */
+ ohdr->u.ieth = cpu_to_be32(
+ wqe->wr.ex.invalidate_rkey);
+ hwords += 1;
}
if (wqe->wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED;
@@ -671,11 +709,16 @@ int hfi1_make_rc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
}
if (wqe->wr.opcode == IB_WR_SEND) {
qp->s_state = OP(SEND_LAST);
- } else {
+ } else if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);
/* Immediate data comes after the BTH */
ohdr->u.imm_data = wqe->wr.ex.imm_data;
hwords += 1;
+ } else {
+ qp->s_state = OP(SEND_LAST_WITH_INVALIDATE);
+ /* invalidate data comes after the BTH */
+ ohdr->u.ieth = cpu_to_be32(wqe->wr.ex.invalidate_rkey);
+ hwords += 1;
}
if (wqe->wr.send_flags & IB_SEND_SOLICITED)
bth0 |= IB_BTH_SOLICITED;
@@ -1047,7 +1090,7 @@ void hfi1_rc_timeout(unsigned long arg)
ibp->rvp.n_rc_timeouts++;
qp->s_flags &= ~RVT_S_TIMER;
del_timer(&qp->s_timer);
- trace_hfi1_rc_timeout(qp, qp->s_last_psn + 1);
+ trace_hfi1_timeout(qp, qp->s_last_psn + 1);
restart_rc(qp, qp->s_last_psn + 1, 1);
hfi1_schedule_send(qp);
}
@@ -1171,7 +1214,7 @@ void hfi1_rc_send_complete(struct rvt_qp *qp, struct hfi1_ib_header *hdr)
* If we were waiting for sends to complete before re-sending,
* and they are now complete, restart sending.
*/
- trace_hfi1_rc_sendcomplete(qp, psn);
+ trace_hfi1_sendcomplete(qp, psn);
if (qp->s_flags & RVT_S_WAIT_PSN &&
cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
qp->s_flags &= ~RVT_S_WAIT_PSN;
@@ -1567,7 +1610,7 @@ static void rc_rcv_resp(struct hfi1_ibport *ibp,
spin_lock_irqsave(&qp->s_lock, flags);
- trace_hfi1_rc_ack(qp, psn);
+ trace_hfi1_ack(qp, psn);
/* Ignore invalid responses. */
smp_read_barrier_depends(); /* see post_one_send */
@@ -1782,7 +1825,7 @@ static noinline int rc_rcv_error(struct hfi1_other_headers *ohdr, void *data,
u8 i, prev;
int old_req;
- trace_hfi1_rc_rcv_error(qp, psn);
+ trace_hfi1_rcv_error(qp, psn);
if (diff > 0) {
/*
* Packet sequence error.
@@ -2086,7 +2129,6 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
u32 tlen = packet->tlen;
struct rvt_qp *qp = packet->qp;
struct hfi1_ibport *ibp = to_iport(qp->ibqp.device, qp->port_num);
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
struct hfi1_other_headers *ohdr = packet->ohdr;
u32 bth0, opcode;
u32 hdrsize = packet->hlen;
@@ -2097,30 +2139,15 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
int diff;
struct ib_reth *reth;
unsigned long flags;
- u32 bth1;
int ret, is_fecn = 0;
int copy_last = 0;
+ u32 rkey;
bth0 = be32_to_cpu(ohdr->bth[0]);
if (hfi1_ruc_check_hdr(ibp, hdr, rcv_flags & HFI1_HAS_GRH, qp, bth0))
return;
- bth1 = be32_to_cpu(ohdr->bth[1]);
- if (unlikely(bth1 & (HFI1_BECN_SMASK | HFI1_FECN_SMASK))) {
- if (bth1 & HFI1_BECN_SMASK) {
- u16 rlid = qp->remote_ah_attr.dlid;
- u32 lqpn, rqpn;
-
- lqpn = qp->ibqp.qp_num;
- rqpn = qp->remote_qpn;
- process_becn(
- ppd,
- qp->remote_ah_attr.sl,
- rlid, lqpn, rqpn,
- IB_CC_SVCTYPE_RC);
- }
- is_fecn = bth1 & HFI1_FECN_SMASK;
- }
+ is_fecn = process_ecn(qp, packet, false);
psn = be32_to_cpu(ohdr->bth[2]);
opcode = (bth0 >> 24) & 0xff;
@@ -2154,7 +2181,8 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
case OP(SEND_MIDDLE):
if (opcode == OP(SEND_MIDDLE) ||
opcode == OP(SEND_LAST) ||
- opcode == OP(SEND_LAST_WITH_IMMEDIATE))
+ opcode == OP(SEND_LAST_WITH_IMMEDIATE) ||
+ opcode == OP(SEND_LAST_WITH_INVALIDATE))
break;
goto nack_inv;
@@ -2170,6 +2198,7 @@ void hfi1_rc_rcv(struct hfi1_packet *packet)
if (opcode == OP(SEND_MIDDLE) ||
opcode == OP(SEND_LAST) ||
opcode == OP(SEND_LAST_WITH_IMMEDIATE) ||
+ opcode == OP(SEND_LAST_WITH_INVALIDATE) ||
opcode == OP(RDMA_WRITE_MIDDLE) ||
opcode == OP(RDMA_WRITE_LAST) ||
opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))
@@ -2218,6 +2247,7 @@ send_middle:
case OP(SEND_ONLY):
case OP(SEND_ONLY_WITH_IMMEDIATE):
+ case OP(SEND_ONLY_WITH_INVALIDATE):
ret = hfi1_rvt_get_rwqe(qp, 0);
if (ret < 0)
goto nack_op_err;
@@ -2226,12 +2256,22 @@ send_middle:
qp->r_rcv_len = 0;
if (opcode == OP(SEND_ONLY))
goto no_immediate_data;
+ if (opcode == OP(SEND_ONLY_WITH_INVALIDATE))
+ goto send_last_inv;
/* FALLTHROUGH for SEND_ONLY_WITH_IMMEDIATE */
case OP(SEND_LAST_WITH_IMMEDIATE):
send_last_imm:
wc.ex.imm_data = ohdr->u.imm_data;
wc.wc_flags = IB_WC_WITH_IMM;
goto send_last;
+ case OP(SEND_LAST_WITH_INVALIDATE):
+send_last_inv:
+ rkey = be32_to_cpu(ohdr->u.ieth);
+ if (rvt_invalidate_rkey(qp, rkey))
+ goto no_immediate_data;
+ wc.ex.invalidate_rkey = rkey;
+ wc.wc_flags = IB_WC_WITH_INVALIDATE;
+ goto send_last;
case OP(RDMA_WRITE_LAST):
copy_last = ibpd_to_rvtpd(qp->ibqp.pd)->user;
/* fall through */
diff --git a/drivers/infiniband/hw/hfi1/ruc.c b/drivers/infiniband/hw/hfi1/ruc.c
index a659aec3c3c6..48d5094f98e2 100644
--- a/drivers/infiniband/hw/hfi1/ruc.c
+++ b/drivers/infiniband/hw/hfi1/ruc.c
@@ -372,6 +372,7 @@ static void ruc_loopback(struct rvt_qp *sqp)
int ret;
int copy_last = 0;
u32 to;
+ int local_ops = 0;
rcu_read_lock();
@@ -440,11 +441,31 @@ again:
sqp->s_sge.num_sge = wqe->wr.num_sge;
sqp->s_len = wqe->length;
switch (wqe->wr.opcode) {
+ case IB_WR_REG_MR:
+ goto send_comp;
+
+ case IB_WR_LOCAL_INV:
+ if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) {
+ if (rvt_invalidate_rkey(sqp,
+ wqe->wr.ex.invalidate_rkey))
+ send_status = IB_WC_LOC_PROT_ERR;
+ local_ops = 1;
+ }
+ goto send_comp;
+
+ case IB_WR_SEND_WITH_INV:
+ if (!rvt_invalidate_rkey(qp, wqe->wr.ex.invalidate_rkey)) {
+ wc.wc_flags = IB_WC_WITH_INVALIDATE;
+ wc.ex.invalidate_rkey = wqe->wr.ex.invalidate_rkey;
+ }
+ goto send;
+
case IB_WR_SEND_WITH_IMM:
wc.wc_flags = IB_WC_WITH_IMM;
wc.ex.imm_data = wqe->wr.ex.imm_data;
/* FALLTHROUGH */
case IB_WR_SEND:
+send:
ret = hfi1_rvt_get_rwqe(qp, 0);
if (ret < 0)
goto op_err;
@@ -583,6 +604,10 @@ send_comp:
flush_send:
sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
hfi1_send_complete(sqp, wqe, send_status);
+ if (local_ops) {
+ atomic_dec(&sqp->local_ops_pending);
+ local_ops = 0;
+ }
goto again;
rnr_nak:
@@ -683,10 +708,10 @@ u32 hfi1_make_grh(struct hfi1_ibport *ibp, struct ib_grh *hdr,
return sizeof(struct ib_grh) / sizeof(u32);
}
-#define BTH2_OFFSET (offsetof(struct hfi1_pio_header, hdr.u.oth.bth[2]) / 4)
+#define BTH2_OFFSET (offsetof(struct hfi1_sdma_header, hdr.u.oth.bth[2]) / 4)
/**
- * build_ahg - create ahg in s_hdr
+ * build_ahg - create ahg in s_ahg
* @qp: a pointer to QP
* @npsn: the next PSN for the request/response
*
@@ -708,19 +733,18 @@ static inline void build_ahg(struct rvt_qp *qp, u32 npsn)
qp->s_ahgidx = sdma_ahg_alloc(priv->s_sde);
if (qp->s_ahgidx >= 0) {
qp->s_ahgpsn = npsn;
- priv->s_hdr->tx_flags |= SDMA_TXREQ_F_AHG_COPY;
+ priv->s_ahg->tx_flags |= SDMA_TXREQ_F_AHG_COPY;
/* save to protect a change in another thread */
- priv->s_hdr->sde = priv->s_sde;
- priv->s_hdr->ahgidx = qp->s_ahgidx;
+ priv->s_ahg->ahgidx = qp->s_ahgidx;
qp->s_flags |= RVT_S_AHG_VALID;
}
} else {
/* subsequent middle after valid */
if (qp->s_ahgidx >= 0) {
- priv->s_hdr->tx_flags |= SDMA_TXREQ_F_USE_AHG;
- priv->s_hdr->ahgidx = qp->s_ahgidx;
- priv->s_hdr->ahgcount++;
- priv->s_hdr->ahgdesc[0] =
+ priv->s_ahg->tx_flags |= SDMA_TXREQ_F_USE_AHG;
+ priv->s_ahg->ahgidx = qp->s_ahgidx;
+ priv->s_ahg->ahgcount++;
+ priv->s_ahg->ahgdesc[0] =
sdma_build_ahg_descriptor(
(__force u16)cpu_to_be16((u16)npsn),
BTH2_OFFSET,
@@ -728,8 +752,8 @@ static inline void build_ahg(struct rvt_qp *qp, u32 npsn)
16);
if ((npsn & 0xffff0000) !=
(qp->s_ahgpsn & 0xffff0000)) {
- priv->s_hdr->ahgcount++;
- priv->s_hdr->ahgdesc[1] =
+ priv->s_ahg->ahgcount++;
+ priv->s_ahg->ahgdesc[1] =
sdma_build_ahg_descriptor(
(__force u16)cpu_to_be16(
(u16)(npsn >> 16)),
@@ -766,7 +790,7 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct hfi1_other_headers *ohdr,
}
lrh0 |= (priv->s_sc & 0xf) << 12 | (qp->remote_ah_attr.sl & 0xf) << 4;
/*
- * reset s_hdr/AHG fields
+ * reset s_ahg/AHG fields
*
* This insures that the ahgentry/ahgcount
* are at a non-AHG default to protect
@@ -776,10 +800,9 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct hfi1_other_headers *ohdr,
* build_ahg() will modify as appropriate
* to use the AHG feature.
*/
- priv->s_hdr->tx_flags = 0;
- priv->s_hdr->ahgcount = 0;
- priv->s_hdr->ahgidx = 0;
- priv->s_hdr->sde = NULL;
+ priv->s_ahg->tx_flags = 0;
+ priv->s_ahg->ahgcount = 0;
+ priv->s_ahg->ahgidx = 0;
if (qp->s_mig_state == IB_MIG_MIGRATED)
bth0 |= IB_BTH_MIG_REQ;
else
@@ -890,7 +913,7 @@ void hfi1_do_send(struct rvt_qp *qp)
*/
if (hfi1_verbs_send(qp, &ps))
return;
- /* Record that s_hdr is empty. */
+ /* Record that s_ahg is empty. */
qp->s_hdrwords = 0;
/* allow other tasks to run */
if (unlikely(time_after(jiffies, timeout))) {
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index 91fc2aed6aed..74c84c655f7e 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -49,6 +49,7 @@
#include "hfi.h"
#include "mad.h"
#include "trace.h"
+#include "affinity.h"
/*
* Start of per-port congestion control structures and support code
@@ -622,6 +623,27 @@ static ssize_t show_tempsense(struct device *device,
return ret;
}
+static ssize_t show_sdma_affinity(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct hfi1_ibdev *dev =
+ container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
+ struct hfi1_devdata *dd = dd_from_dev(dev);
+
+ return hfi1_get_sdma_affinity(dd, buf);
+}
+
+static ssize_t store_sdma_affinity(struct device *device,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hfi1_ibdev *dev =
+ container_of(device, struct hfi1_ibdev, rdi.ibdev.dev);
+ struct hfi1_devdata *dd = dd_from_dev(dev);
+
+ return hfi1_set_sdma_affinity(dd, buf, count);
+}
+
/*
* end of per-unit (or driver, in some cases, but replicated
* per unit) functions
@@ -636,6 +658,8 @@ static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL);
static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset);
+static DEVICE_ATTR(sdma_affinity, S_IWUSR | S_IRUGO, show_sdma_affinity,
+ store_sdma_affinity);
static struct device_attribute *hfi1_attributes[] = {
&dev_attr_hw_rev,
@@ -646,6 +670,7 @@ static struct device_attribute *hfi1_attributes[] = {
&dev_attr_boardversion,
&dev_attr_tempsense,
&dev_attr_chip_reset,
+ &dev_attr_sdma_affinity,
};
int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,
diff --git a/drivers/infiniband/hw/hfi1/trace.h b/drivers/infiniband/hw/hfi1/trace.h
index 28c1d0832886..92dc88f013c9 100644
--- a/drivers/infiniband/hw/hfi1/trace.h
+++ b/drivers/infiniband/hw/hfi1/trace.h
@@ -44,1329 +44,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
-#undef TRACE_SYSTEM_VAR
-#define TRACE_SYSTEM_VAR hfi1
-
-#if !defined(__HFI1_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define __HFI1_TRACE_H
-
-#include <linux/tracepoint.h>
-#include <linux/trace_seq.h>
-
-#include "hfi.h"
-#include "mad.h"
-#include "sdma.h"
-
-#define DD_DEV_ENTRY(dd) __string(dev, dev_name(&(dd)->pcidev->dev))
-#define DD_DEV_ASSIGN(dd) __assign_str(dev, dev_name(&(dd)->pcidev->dev))
-
-#define packettype_name(etype) { RHF_RCV_TYPE_##etype, #etype }
-#define show_packettype(etype) \
-__print_symbolic(etype, \
- packettype_name(EXPECTED), \
- packettype_name(EAGER), \
- packettype_name(IB), \
- packettype_name(ERROR), \
- packettype_name(BYPASS))
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_rx
-
-TRACE_EVENT(hfi1_rcvhdr,
- TP_PROTO(struct hfi1_devdata *dd,
- u32 ctxt,
- u64 eflags,
- u32 etype,
- u32 hlen,
- u32 tlen,
- u32 updegr,
- u32 etail
- ),
- TP_ARGS(dd, ctxt, eflags, etype, hlen, tlen, updegr, etail),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __field(u64, eflags)
- __field(u32, ctxt)
- __field(u32, etype)
- __field(u32, hlen)
- __field(u32, tlen)
- __field(u32, updegr)
- __field(u32, etail)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- __entry->eflags = eflags;
- __entry->ctxt = ctxt;
- __entry->etype = etype;
- __entry->hlen = hlen;
- __entry->tlen = tlen;
- __entry->updegr = updegr;
- __entry->etail = etail;
- ),
- TP_printk(
- "[%s] ctxt %d eflags 0x%llx etype %d,%s hlen %d tlen %d updegr %d etail %d",
- __get_str(dev),
- __entry->ctxt,
- __entry->eflags,
- __entry->etype, show_packettype(__entry->etype),
- __entry->hlen,
- __entry->tlen,
- __entry->updegr,
- __entry->etail
- )
-);
-
-TRACE_EVENT(hfi1_receive_interrupt,
- TP_PROTO(struct hfi1_devdata *dd, u32 ctxt),
- TP_ARGS(dd, ctxt),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __field(u32, ctxt)
- __field(u8, slow_path)
- __field(u8, dma_rtail)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- if (dd->rcd[ctxt]->do_interrupt ==
- &handle_receive_interrupt) {
- __entry->slow_path = 1;
- __entry->dma_rtail = 0xFF;
- } else if (dd->rcd[ctxt]->do_interrupt ==
- &handle_receive_interrupt_dma_rtail){
- __entry->dma_rtail = 1;
- __entry->slow_path = 0;
- } else if (dd->rcd[ctxt]->do_interrupt ==
- &handle_receive_interrupt_nodma_rtail) {
- __entry->dma_rtail = 0;
- __entry->slow_path = 0;
- }
- ),
- TP_printk("[%s] ctxt %d SlowPath: %d DmaRtail: %d",
- __get_str(dev),
- __entry->ctxt,
- __entry->slow_path,
- __entry->dma_rtail
- )
-);
-
-TRACE_EVENT(hfi1_exp_tid_reg,
- TP_PROTO(unsigned ctxt, u16 subctxt, u32 rarr,
- u32 npages, unsigned long va, unsigned long pa,
- dma_addr_t dma),
- TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma),
- TP_STRUCT__entry(
- __field(unsigned, ctxt)
- __field(u16, subctxt)
- __field(u32, rarr)
- __field(u32, npages)
- __field(unsigned long, va)
- __field(unsigned long, pa)
- __field(dma_addr_t, dma)
- ),
- TP_fast_assign(
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->rarr = rarr;
- __entry->npages = npages;
- __entry->va = va;
- __entry->pa = pa;
- __entry->dma = dma;
- ),
- TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx, va:0x%lx dma:0x%llx",
- __entry->ctxt,
- __entry->subctxt,
- __entry->rarr,
- __entry->npages,
- __entry->pa,
- __entry->va,
- __entry->dma
- )
- );
-
-TRACE_EVENT(hfi1_exp_tid_unreg,
- TP_PROTO(unsigned ctxt, u16 subctxt, u32 rarr, u32 npages,
- unsigned long va, unsigned long pa, dma_addr_t dma),
- TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma),
- TP_STRUCT__entry(
- __field(unsigned, ctxt)
- __field(u16, subctxt)
- __field(u32, rarr)
- __field(u32, npages)
- __field(unsigned long, va)
- __field(unsigned long, pa)
- __field(dma_addr_t, dma)
- ),
- TP_fast_assign(
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->rarr = rarr;
- __entry->npages = npages;
- __entry->va = va;
- __entry->pa = pa;
- __entry->dma = dma;
- ),
- TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx, va:0x%lx dma:0x%llx",
- __entry->ctxt,
- __entry->subctxt,
- __entry->rarr,
- __entry->npages,
- __entry->pa,
- __entry->va,
- __entry->dma
- )
- );
-
-TRACE_EVENT(hfi1_exp_tid_inval,
- TP_PROTO(unsigned ctxt, u16 subctxt, unsigned long va, u32 rarr,
- u32 npages, dma_addr_t dma),
- TP_ARGS(ctxt, subctxt, va, rarr, npages, dma),
- TP_STRUCT__entry(
- __field(unsigned, ctxt)
- __field(u16, subctxt)
- __field(unsigned long, va)
- __field(u32, rarr)
- __field(u32, npages)
- __field(dma_addr_t, dma)
- ),
- TP_fast_assign(
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->va = va;
- __entry->rarr = rarr;
- __entry->npages = npages;
- __entry->dma = dma;
- ),
- TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx dma: 0x%llx",
- __entry->ctxt,
- __entry->subctxt,
- __entry->rarr,
- __entry->npages,
- __entry->va,
- __entry->dma
- )
- );
-
-TRACE_EVENT(hfi1_mmu_invalidate,
- TP_PROTO(unsigned ctxt, u16 subctxt, const char *type,
- unsigned long start, unsigned long end),
- TP_ARGS(ctxt, subctxt, type, start, end),
- TP_STRUCT__entry(
- __field(unsigned, ctxt)
- __field(u16, subctxt)
- __string(type, type)
- __field(unsigned long, start)
- __field(unsigned long, end)
- ),
- TP_fast_assign(
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __assign_str(type, type);
- __entry->start = start;
- __entry->end = end;
- ),
- TP_printk("[%3u:%02u] MMU Invalidate (%s) 0x%lx - 0x%lx",
- __entry->ctxt,
- __entry->subctxt,
- __get_str(type),
- __entry->start,
- __entry->end
- )
- );
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_tx
-
-TRACE_EVENT(hfi1_piofree,
- TP_PROTO(struct send_context *sc, int extra),
- TP_ARGS(sc, extra),
- TP_STRUCT__entry(DD_DEV_ENTRY(sc->dd)
- __field(u32, sw_index)
- __field(u32, hw_context)
- __field(int, extra)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sc->dd);
- __entry->sw_index = sc->sw_index;
- __entry->hw_context = sc->hw_context;
- __entry->extra = extra;
- ),
- TP_printk("[%s] ctxt %u(%u) extra %d",
- __get_str(dev),
- __entry->sw_index,
- __entry->hw_context,
- __entry->extra
- )
-);
-
-TRACE_EVENT(hfi1_wantpiointr,
- TP_PROTO(struct send_context *sc, u32 needint, u64 credit_ctrl),
- TP_ARGS(sc, needint, credit_ctrl),
- TP_STRUCT__entry(DD_DEV_ENTRY(sc->dd)
- __field(u32, sw_index)
- __field(u32, hw_context)
- __field(u32, needint)
- __field(u64, credit_ctrl)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sc->dd);
- __entry->sw_index = sc->sw_index;
- __entry->hw_context = sc->hw_context;
- __entry->needint = needint;
- __entry->credit_ctrl = credit_ctrl;
- ),
- TP_printk("[%s] ctxt %u(%u) on %d credit_ctrl 0x%llx",
- __get_str(dev),
- __entry->sw_index,
- __entry->hw_context,
- __entry->needint,
- (unsigned long long)__entry->credit_ctrl
- )
-);
-
-DECLARE_EVENT_CLASS(hfi1_qpsleepwakeup_template,
- TP_PROTO(struct rvt_qp *qp, u32 flags),
- TP_ARGS(qp, flags),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
- __field(u32, qpn)
- __field(u32, flags)
- __field(u32, s_flags)
- ),
- TP_fast_assign(
- DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
- __entry->flags = flags;
- __entry->qpn = qp->ibqp.qp_num;
- __entry->s_flags = qp->s_flags;
- ),
- TP_printk(
- "[%s] qpn 0x%x flags 0x%x s_flags 0x%x",
- __get_str(dev),
- __entry->qpn,
- __entry->flags,
- __entry->s_flags
- )
-);
-
-DEFINE_EVENT(hfi1_qpsleepwakeup_template, hfi1_qpwakeup,
- TP_PROTO(struct rvt_qp *qp, u32 flags),
- TP_ARGS(qp, flags));
-
-DEFINE_EVENT(hfi1_qpsleepwakeup_template, hfi1_qpsleep,
- TP_PROTO(struct rvt_qp *qp, u32 flags),
- TP_ARGS(qp, flags));
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_ibhdrs
-
-u8 ibhdr_exhdr_len(struct hfi1_ib_header *hdr);
-const char *parse_everbs_hdrs(struct trace_seq *p, u8 opcode, void *ehdrs);
-
-#define __parse_ib_ehdrs(op, ehdrs) parse_everbs_hdrs(p, op, ehdrs)
-
-const char *parse_sdma_flags(struct trace_seq *p, u64 desc0, u64 desc1);
-
-#define __parse_sdma_flags(desc0, desc1) parse_sdma_flags(p, desc0, desc1)
-
-#define lrh_name(lrh) { HFI1_##lrh, #lrh }
-#define show_lnh(lrh) \
-__print_symbolic(lrh, \
- lrh_name(LRH_BTH), \
- lrh_name(LRH_GRH))
-
-#define ib_opcode_name(opcode) { IB_OPCODE_##opcode, #opcode }
-#define show_ib_opcode(opcode) \
-__print_symbolic(opcode, \
- ib_opcode_name(RC_SEND_FIRST), \
- ib_opcode_name(RC_SEND_MIDDLE), \
- ib_opcode_name(RC_SEND_LAST), \
- ib_opcode_name(RC_SEND_LAST_WITH_IMMEDIATE), \
- ib_opcode_name(RC_SEND_ONLY), \
- ib_opcode_name(RC_SEND_ONLY_WITH_IMMEDIATE), \
- ib_opcode_name(RC_RDMA_WRITE_FIRST), \
- ib_opcode_name(RC_RDMA_WRITE_MIDDLE), \
- ib_opcode_name(RC_RDMA_WRITE_LAST), \
- ib_opcode_name(RC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \
- ib_opcode_name(RC_RDMA_WRITE_ONLY), \
- ib_opcode_name(RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \
- ib_opcode_name(RC_RDMA_READ_REQUEST), \
- ib_opcode_name(RC_RDMA_READ_RESPONSE_FIRST), \
- ib_opcode_name(RC_RDMA_READ_RESPONSE_MIDDLE), \
- ib_opcode_name(RC_RDMA_READ_RESPONSE_LAST), \
- ib_opcode_name(RC_RDMA_READ_RESPONSE_ONLY), \
- ib_opcode_name(RC_ACKNOWLEDGE), \
- ib_opcode_name(RC_ATOMIC_ACKNOWLEDGE), \
- ib_opcode_name(RC_COMPARE_SWAP), \
- ib_opcode_name(RC_FETCH_ADD), \
- ib_opcode_name(RC_SEND_LAST_WITH_INVALIDATE), \
- ib_opcode_name(RC_SEND_ONLY_WITH_INVALIDATE), \
- ib_opcode_name(UC_SEND_FIRST), \
- ib_opcode_name(UC_SEND_MIDDLE), \
- ib_opcode_name(UC_SEND_LAST), \
- ib_opcode_name(UC_SEND_LAST_WITH_IMMEDIATE), \
- ib_opcode_name(UC_SEND_ONLY), \
- ib_opcode_name(UC_SEND_ONLY_WITH_IMMEDIATE), \
- ib_opcode_name(UC_RDMA_WRITE_FIRST), \
- ib_opcode_name(UC_RDMA_WRITE_MIDDLE), \
- ib_opcode_name(UC_RDMA_WRITE_LAST), \
- ib_opcode_name(UC_RDMA_WRITE_LAST_WITH_IMMEDIATE), \
- ib_opcode_name(UC_RDMA_WRITE_ONLY), \
- ib_opcode_name(UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE), \
- ib_opcode_name(UD_SEND_ONLY), \
- ib_opcode_name(UD_SEND_ONLY_WITH_IMMEDIATE), \
- ib_opcode_name(CNP))
-
-#define LRH_PRN "vl %d lver %d sl %d lnh %d,%s dlid %.4x len %d slid %.4x"
-#define BTH_PRN \
- "op 0x%.2x,%s se %d m %d pad %d tver %d pkey 0x%.4x " \
- "f %d b %d qpn 0x%.6x a %d psn 0x%.8x"
-#define EHDR_PRN "%s"
-
-DECLARE_EVENT_CLASS(hfi1_ibhdr_template,
- TP_PROTO(struct hfi1_devdata *dd,
- struct hfi1_ib_header *hdr),
- TP_ARGS(dd, hdr),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd)
- /* LRH */
- __field(u8, vl)
- __field(u8, lver)
- __field(u8, sl)
- __field(u8, lnh)
- __field(u16, dlid)
- __field(u16, len)
- __field(u16, slid)
- /* BTH */
- __field(u8, opcode)
- __field(u8, se)
- __field(u8, m)
- __field(u8, pad)
- __field(u8, tver)
- __field(u16, pkey)
- __field(u8, f)
- __field(u8, b)
- __field(u32, qpn)
- __field(u8, a)
- __field(u32, psn)
- /* extended headers */
- __dynamic_array(u8, ehdrs, ibhdr_exhdr_len(hdr))
- ),
- TP_fast_assign(
- struct hfi1_other_headers *ohdr;
-
- DD_DEV_ASSIGN(dd);
- /* LRH */
- __entry->vl =
- (u8)(be16_to_cpu(hdr->lrh[0]) >> 12);
- __entry->lver =
- (u8)(be16_to_cpu(hdr->lrh[0]) >> 8) & 0xf;
- __entry->sl =
- (u8)(be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf;
- __entry->lnh =
- (u8)(be16_to_cpu(hdr->lrh[0]) & 3);
- __entry->dlid =
- be16_to_cpu(hdr->lrh[1]);
- /* allow for larger len */
- __entry->len =
- be16_to_cpu(hdr->lrh[2]);
- __entry->slid =
- be16_to_cpu(hdr->lrh[3]);
- /* BTH */
- if (__entry->lnh == HFI1_LRH_BTH)
- ohdr = &hdr->u.oth;
- else
- ohdr = &hdr->u.l.oth;
- __entry->opcode =
- (be32_to_cpu(ohdr->bth[0]) >> 24) & 0xff;
- __entry->se =
- (be32_to_cpu(ohdr->bth[0]) >> 23) & 1;
- __entry->m =
- (be32_to_cpu(ohdr->bth[0]) >> 22) & 1;
- __entry->pad =
- (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
- __entry->tver =
- (be32_to_cpu(ohdr->bth[0]) >> 16) & 0xf;
- __entry->pkey =
- be32_to_cpu(ohdr->bth[0]) & 0xffff;
- __entry->f =
- (be32_to_cpu(ohdr->bth[1]) >> HFI1_FECN_SHIFT) &
- HFI1_FECN_MASK;
- __entry->b =
- (be32_to_cpu(ohdr->bth[1]) >> HFI1_BECN_SHIFT) &
- HFI1_BECN_MASK;
- __entry->qpn =
- be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
- __entry->a =
- (be32_to_cpu(ohdr->bth[2]) >> 31) & 1;
- /* allow for larger PSN */
- __entry->psn =
- be32_to_cpu(ohdr->bth[2]) & 0x7fffffff;
- /* extended headers */
- memcpy(__get_dynamic_array(ehdrs), &ohdr->u,
- ibhdr_exhdr_len(hdr));
- ),
- TP_printk("[%s] " LRH_PRN " " BTH_PRN " " EHDR_PRN,
- __get_str(dev),
- /* LRH */
- __entry->vl,
- __entry->lver,
- __entry->sl,
- __entry->lnh, show_lnh(__entry->lnh),
- __entry->dlid,
- __entry->len,
- __entry->slid,
- /* BTH */
- __entry->opcode, show_ib_opcode(__entry->opcode),
- __entry->se,
- __entry->m,
- __entry->pad,
- __entry->tver,
- __entry->pkey,
- __entry->f,
- __entry->b,
- __entry->qpn,
- __entry->a,
- __entry->psn,
- /* extended headers */
- __parse_ib_ehdrs(
- __entry->opcode,
- (void *)__get_dynamic_array(ehdrs))
- )
-);
-
-DEFINE_EVENT(hfi1_ibhdr_template, input_ibhdr,
- TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
- TP_ARGS(dd, hdr));
-
-DEFINE_EVENT(hfi1_ibhdr_template, pio_output_ibhdr,
- TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
- TP_ARGS(dd, hdr));
-
-DEFINE_EVENT(hfi1_ibhdr_template, ack_output_ibhdr,
- TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
- TP_ARGS(dd, hdr));
-
-DEFINE_EVENT(hfi1_ibhdr_template, sdma_output_ibhdr,
- TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
- TP_ARGS(dd, hdr));
-
-#define SNOOP_PRN \
- "slid %.4x dlid %.4x qpn 0x%.6x opcode 0x%.2x,%s " \
- "svc lvl %d pkey 0x%.4x [header = %d bytes] [data = %d bytes]"
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_snoop
-
-TRACE_EVENT(snoop_capture,
- TP_PROTO(struct hfi1_devdata *dd,
- int hdr_len,
- struct hfi1_ib_header *hdr,
- int data_len,
- void *data),
- TP_ARGS(dd, hdr_len, hdr, data_len, data),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd)
- __field(u16, slid)
- __field(u16, dlid)
- __field(u32, qpn)
- __field(u8, opcode)
- __field(u8, sl)
- __field(u16, pkey)
- __field(u32, hdr_len)
- __field(u32, data_len)
- __field(u8, lnh)
- __dynamic_array(u8, raw_hdr, hdr_len)
- __dynamic_array(u8, raw_pkt, data_len)
- ),
- TP_fast_assign(
- struct hfi1_other_headers *ohdr;
-
- __entry->lnh = (u8)(be16_to_cpu(hdr->lrh[0]) & 3);
- if (__entry->lnh == HFI1_LRH_BTH)
- ohdr = &hdr->u.oth;
- else
- ohdr = &hdr->u.l.oth;
- DD_DEV_ASSIGN(dd);
- __entry->slid = be16_to_cpu(hdr->lrh[3]);
- __entry->dlid = be16_to_cpu(hdr->lrh[1]);
- __entry->qpn = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
- __entry->opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0xff;
- __entry->sl = (u8)(be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf;
- __entry->pkey = be32_to_cpu(ohdr->bth[0]) & 0xffff;
- __entry->hdr_len = hdr_len;
- __entry->data_len = data_len;
- memcpy(__get_dynamic_array(raw_hdr), hdr, hdr_len);
- memcpy(__get_dynamic_array(raw_pkt), data, data_len);
- ),
- TP_printk(
- "[%s] " SNOOP_PRN,
- __get_str(dev),
- __entry->slid,
- __entry->dlid,
- __entry->qpn,
- __entry->opcode,
- show_ib_opcode(__entry->opcode),
- __entry->sl,
- __entry->pkey,
- __entry->hdr_len,
- __entry->data_len
- )
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_ctxts
-
-#define UCTXT_FMT \
- "cred:%u, credaddr:0x%llx, piobase:0x%llx, rcvhdr_cnt:%u, " \
- "rcvbase:0x%llx, rcvegrc:%u, rcvegrb:0x%llx"
-TRACE_EVENT(hfi1_uctxtdata,
- TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt),
- TP_ARGS(dd, uctxt),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __field(unsigned, ctxt)
- __field(u32, credits)
- __field(u64, hw_free)
- __field(u64, piobase)
- __field(u16, rcvhdrq_cnt)
- __field(u64, rcvhdrq_phys)
- __field(u32, eager_cnt)
- __field(u64, rcvegr_phys)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- __entry->ctxt = uctxt->ctxt;
- __entry->credits = uctxt->sc->credits;
- __entry->hw_free = (u64)uctxt->sc->hw_free;
- __entry->piobase = (u64)uctxt->sc->base_addr;
- __entry->rcvhdrq_cnt = uctxt->rcvhdrq_cnt;
- __entry->rcvhdrq_phys = uctxt->rcvhdrq_phys;
- __entry->eager_cnt = uctxt->egrbufs.alloced;
- __entry->rcvegr_phys =
- uctxt->egrbufs.rcvtids[0].phys;
- ),
- TP_printk("[%s] ctxt %u " UCTXT_FMT,
- __get_str(dev),
- __entry->ctxt,
- __entry->credits,
- __entry->hw_free,
- __entry->piobase,
- __entry->rcvhdrq_cnt,
- __entry->rcvhdrq_phys,
- __entry->eager_cnt,
- __entry->rcvegr_phys
- )
-);
-
-#define CINFO_FMT \
- "egrtids:%u, egr_size:%u, hdrq_cnt:%u, hdrq_size:%u, sdma_ring_size:%u"
-TRACE_EVENT(hfi1_ctxt_info,
- TP_PROTO(struct hfi1_devdata *dd, unsigned ctxt, unsigned subctxt,
- struct hfi1_ctxt_info cinfo),
- TP_ARGS(dd, ctxt, subctxt, cinfo),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __field(unsigned, ctxt)
- __field(unsigned, subctxt)
- __field(u16, egrtids)
- __field(u16, rcvhdrq_cnt)
- __field(u16, rcvhdrq_size)
- __field(u16, sdma_ring_size)
- __field(u32, rcvegr_size)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->egrtids = cinfo.egrtids;
- __entry->rcvhdrq_cnt = cinfo.rcvhdrq_cnt;
- __entry->rcvhdrq_size = cinfo.rcvhdrq_entsize;
- __entry->sdma_ring_size = cinfo.sdma_ring_size;
- __entry->rcvegr_size = cinfo.rcvegr_size;
- ),
- TP_printk("[%s] ctxt %u:%u " CINFO_FMT,
- __get_str(dev),
- __entry->ctxt,
- __entry->subctxt,
- __entry->egrtids,
- __entry->rcvegr_size,
- __entry->rcvhdrq_cnt,
- __entry->rcvhdrq_size,
- __entry->sdma_ring_size
- )
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_sma
-
-#define BCT_FORMAT \
- "shared_limit %x vls 0-7 [%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x] 15 [%x,%x]"
-
-#define BCT(field) \
- be16_to_cpu( \
- ((struct buffer_control *)__get_dynamic_array(bct))->field \
- )
-
-DECLARE_EVENT_CLASS(hfi1_bct_template,
- TP_PROTO(struct hfi1_devdata *dd,
- struct buffer_control *bc),
- TP_ARGS(dd, bc),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __dynamic_array(u8, bct, sizeof(*bc))
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- memcpy(__get_dynamic_array(bct), bc,
- sizeof(*bc));
- ),
- TP_printk(BCT_FORMAT,
- BCT(overall_shared_limit),
-
- BCT(vl[0].dedicated),
- BCT(vl[0].shared),
-
- BCT(vl[1].dedicated),
- BCT(vl[1].shared),
-
- BCT(vl[2].dedicated),
- BCT(vl[2].shared),
-
- BCT(vl[3].dedicated),
- BCT(vl[3].shared),
-
- BCT(vl[4].dedicated),
- BCT(vl[4].shared),
-
- BCT(vl[5].dedicated),
- BCT(vl[5].shared),
-
- BCT(vl[6].dedicated),
- BCT(vl[6].shared),
-
- BCT(vl[7].dedicated),
- BCT(vl[7].shared),
-
- BCT(vl[15].dedicated),
- BCT(vl[15].shared)
- )
-);
-
-DEFINE_EVENT(hfi1_bct_template, bct_set,
- TP_PROTO(struct hfi1_devdata *dd, struct buffer_control *bc),
- TP_ARGS(dd, bc));
-
-DEFINE_EVENT(hfi1_bct_template, bct_get,
- TP_PROTO(struct hfi1_devdata *dd, struct buffer_control *bc),
- TP_ARGS(dd, bc));
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_sdma
-
-TRACE_EVENT(hfi1_sdma_descriptor,
- TP_PROTO(struct sdma_engine *sde,
- u64 desc0,
- u64 desc1,
- u16 e,
- void *descp),
- TP_ARGS(sde, desc0, desc1, e, descp),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(void *, descp)
- __field(u64, desc0)
- __field(u64, desc1)
- __field(u16, e)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->desc0 = desc0;
- __entry->desc1 = desc1;
- __entry->idx = sde->this_idx;
- __entry->descp = descp;
- __entry->e = e;
- ),
- TP_printk(
- "[%s] SDE(%u) flags:%s addr:0x%016llx gen:%u len:%u d0:%016llx d1:%016llx to %p,%u",
- __get_str(dev),
- __entry->idx,
- __parse_sdma_flags(__entry->desc0, __entry->desc1),
- (__entry->desc0 >> SDMA_DESC0_PHY_ADDR_SHIFT) &
- SDMA_DESC0_PHY_ADDR_MASK,
- (u8)((__entry->desc1 >> SDMA_DESC1_GENERATION_SHIFT) &
- SDMA_DESC1_GENERATION_MASK),
- (u16)((__entry->desc0 >> SDMA_DESC0_BYTE_COUNT_SHIFT) &
- SDMA_DESC0_BYTE_COUNT_MASK),
- __entry->desc0,
- __entry->desc1,
- __entry->descp,
- __entry->e
- )
-);
-
-TRACE_EVENT(hfi1_sdma_engine_select,
- TP_PROTO(struct hfi1_devdata *dd, u32 sel, u8 vl, u8 idx),
- TP_ARGS(dd, sel, vl, idx),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __field(u32, sel)
- __field(u8, vl)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd);
- __entry->sel = sel;
- __entry->vl = vl;
- __entry->idx = idx;
- ),
- TP_printk("[%s] selecting SDE %u sel 0x%x vl %u",
- __get_str(dev),
- __entry->idx,
- __entry->sel,
- __entry->vl
- )
-);
-
-DECLARE_EVENT_CLASS(hfi1_sdma_engine_class,
- TP_PROTO(struct sdma_engine *sde, u64 status),
- TP_ARGS(sde, status),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(u64, status)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->status = status;
- __entry->idx = sde->this_idx;
- ),
- TP_printk("[%s] SDE(%u) status %llx",
- __get_str(dev),
- __entry->idx,
- (unsigned long long)__entry->status
- )
-);
-
-DEFINE_EVENT(hfi1_sdma_engine_class, hfi1_sdma_engine_interrupt,
- TP_PROTO(struct sdma_engine *sde, u64 status),
- TP_ARGS(sde, status)
-);
-
-DEFINE_EVENT(hfi1_sdma_engine_class, hfi1_sdma_engine_progress,
- TP_PROTO(struct sdma_engine *sde, u64 status),
- TP_ARGS(sde, status)
-);
-
-DECLARE_EVENT_CLASS(hfi1_sdma_ahg_ad,
- TP_PROTO(struct sdma_engine *sde, int aidx),
- TP_ARGS(sde, aidx),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(int, aidx)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->idx = sde->this_idx;
- __entry->aidx = aidx;
- ),
- TP_printk("[%s] SDE(%u) aidx %d",
- __get_str(dev),
- __entry->idx,
- __entry->aidx
- )
-);
-
-DEFINE_EVENT(hfi1_sdma_ahg_ad, hfi1_ahg_allocate,
- TP_PROTO(struct sdma_engine *sde, int aidx),
- TP_ARGS(sde, aidx));
-
-DEFINE_EVENT(hfi1_sdma_ahg_ad, hfi1_ahg_deallocate,
- TP_PROTO(struct sdma_engine *sde, int aidx),
- TP_ARGS(sde, aidx));
-
-#ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER
-TRACE_EVENT(hfi1_sdma_progress,
- TP_PROTO(struct sdma_engine *sde,
- u16 hwhead,
- u16 swhead,
- struct sdma_txreq *txp
- ),
- TP_ARGS(sde, hwhead, swhead, txp),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(u64, sn)
- __field(u16, hwhead)
- __field(u16, swhead)
- __field(u16, txnext)
- __field(u16, tx_tail)
- __field(u16, tx_head)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->hwhead = hwhead;
- __entry->swhead = swhead;
- __entry->tx_tail = sde->tx_tail;
- __entry->tx_head = sde->tx_head;
- __entry->txnext = txp ? txp->next_descq_idx : ~0;
- __entry->idx = sde->this_idx;
- __entry->sn = txp ? txp->sn : ~0;
- ),
- TP_printk(
- "[%s] SDE(%u) sn %llu hwhead %u swhead %u next_descq_idx %u tx_head %u tx_tail %u",
- __get_str(dev),
- __entry->idx,
- __entry->sn,
- __entry->hwhead,
- __entry->swhead,
- __entry->txnext,
- __entry->tx_head,
- __entry->tx_tail
- )
-);
-#else
-TRACE_EVENT(hfi1_sdma_progress,
- TP_PROTO(struct sdma_engine *sde,
- u16 hwhead, u16 swhead,
- struct sdma_txreq *txp
- ),
- TP_ARGS(sde, hwhead, swhead, txp),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(u16, hwhead)
- __field(u16, swhead)
- __field(u16, txnext)
- __field(u16, tx_tail)
- __field(u16, tx_head)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->hwhead = hwhead;
- __entry->swhead = swhead;
- __entry->tx_tail = sde->tx_tail;
- __entry->tx_head = sde->tx_head;
- __entry->txnext = txp ? txp->next_descq_idx : ~0;
- __entry->idx = sde->this_idx;
- ),
- TP_printk(
- "[%s] SDE(%u) hwhead %u swhead %u next_descq_idx %u tx_head %u tx_tail %u",
- __get_str(dev),
- __entry->idx,
- __entry->hwhead,
- __entry->swhead,
- __entry->txnext,
- __entry->tx_head,
- __entry->tx_tail
- )
-);
-#endif
-
-DECLARE_EVENT_CLASS(hfi1_sdma_sn,
- TP_PROTO(struct sdma_engine *sde, u64 sn),
- TP_ARGS(sde, sn),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __field(u64, sn)
- __field(u8, idx)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __entry->sn = sn;
- __entry->idx = sde->this_idx;
- ),
- TP_printk("[%s] SDE(%u) sn %llu",
- __get_str(dev),
- __entry->idx,
- __entry->sn
- )
-);
-
-DEFINE_EVENT(hfi1_sdma_sn, hfi1_sdma_out_sn,
- TP_PROTO(
- struct sdma_engine *sde,
- u64 sn
- ),
- TP_ARGS(sde, sn)
-);
-
-DEFINE_EVENT(hfi1_sdma_sn, hfi1_sdma_in_sn,
- TP_PROTO(struct sdma_engine *sde, u64 sn),
- TP_ARGS(sde, sn)
-);
-
-#define USDMA_HDR_FORMAT \
- "[%s:%u:%u:%u] PBC=(0x%x 0x%x) LRH=(0x%x 0x%x) BTH=(0x%x 0x%x 0x%x) KDETH=(0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x) TIDVal=0x%x"
-
-TRACE_EVENT(hfi1_sdma_user_header,
- TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 req,
- struct hfi1_pkt_header *hdr, u32 tidval),
- TP_ARGS(dd, ctxt, subctxt, req, hdr, tidval),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd)
- __field(u16, ctxt)
- __field(u8, subctxt)
- __field(u16, req)
- __field(__le32, pbc0)
- __field(__le32, pbc1)
- __field(__be32, lrh0)
- __field(__be32, lrh1)
- __field(__be32, bth0)
- __field(__be32, bth1)
- __field(__be32, bth2)
- __field(__le32, kdeth0)
- __field(__le32, kdeth1)
- __field(__le32, kdeth2)
- __field(__le32, kdeth3)
- __field(__le32, kdeth4)
- __field(__le32, kdeth5)
- __field(__le32, kdeth6)
- __field(__le32, kdeth7)
- __field(__le32, kdeth8)
- __field(u32, tidval)
- ),
- TP_fast_assign(
- __le32 *pbc = (__le32 *)hdr->pbc;
- __be32 *lrh = (__be32 *)hdr->lrh;
- __be32 *bth = (__be32 *)hdr->bth;
- __le32 *kdeth = (__le32 *)&hdr->kdeth;
-
- DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->req = req;
- __entry->pbc0 = pbc[0];
- __entry->pbc1 = pbc[1];
- __entry->lrh0 = be32_to_cpu(lrh[0]);
- __entry->lrh1 = be32_to_cpu(lrh[1]);
- __entry->bth0 = be32_to_cpu(bth[0]);
- __entry->bth1 = be32_to_cpu(bth[1]);
- __entry->bth2 = be32_to_cpu(bth[2]);
- __entry->kdeth0 = kdeth[0];
- __entry->kdeth1 = kdeth[1];
- __entry->kdeth2 = kdeth[2];
- __entry->kdeth3 = kdeth[3];
- __entry->kdeth4 = kdeth[4];
- __entry->kdeth5 = kdeth[5];
- __entry->kdeth6 = kdeth[6];
- __entry->kdeth7 = kdeth[7];
- __entry->kdeth8 = kdeth[8];
- __entry->tidval = tidval;
- ),
- TP_printk(USDMA_HDR_FORMAT,
- __get_str(dev),
- __entry->ctxt,
- __entry->subctxt,
- __entry->req,
- __entry->pbc1,
- __entry->pbc0,
- __entry->lrh0,
- __entry->lrh1,
- __entry->bth0,
- __entry->bth1,
- __entry->bth2,
- __entry->kdeth0,
- __entry->kdeth1,
- __entry->kdeth2,
- __entry->kdeth3,
- __entry->kdeth4,
- __entry->kdeth5,
- __entry->kdeth6,
- __entry->kdeth7,
- __entry->kdeth8,
- __entry->tidval
- )
- );
-
-#define SDMA_UREQ_FMT \
- "[%s:%u:%u] ver/op=0x%x, iovcnt=%u, npkts=%u, frag=%u, idx=%u"
-TRACE_EVENT(hfi1_sdma_user_reqinfo,
- TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 *i),
- TP_ARGS(dd, ctxt, subctxt, i),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd);
- __field(u16, ctxt)
- __field(u8, subctxt)
- __field(u8, ver_opcode)
- __field(u8, iovcnt)
- __field(u16, npkts)
- __field(u16, fragsize)
- __field(u16, comp_idx)
- ),
- TP_fast_assign(
- DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->ver_opcode = i[0] & 0xff;
- __entry->iovcnt = (i[0] >> 8) & 0xff;
- __entry->npkts = i[1];
- __entry->fragsize = i[2];
- __entry->comp_idx = i[3];
- ),
- TP_printk(SDMA_UREQ_FMT,
- __get_str(dev),
- __entry->ctxt,
- __entry->subctxt,
- __entry->ver_opcode,
- __entry->iovcnt,
- __entry->npkts,
- __entry->fragsize,
- __entry->comp_idx
- )
- );
-
-#define usdma_complete_name(st) { st, #st }
-#define show_usdma_complete_state(st) \
- __print_symbolic(st, \
- usdma_complete_name(FREE), \
- usdma_complete_name(QUEUED), \
- usdma_complete_name(COMPLETE), \
- usdma_complete_name(ERROR))
-
-TRACE_EVENT(hfi1_sdma_user_completion,
- TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 idx,
- u8 state, int code),
- TP_ARGS(dd, ctxt, subctxt, idx, state, code),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd)
- __field(u16, ctxt)
- __field(u8, subctxt)
- __field(u16, idx)
- __field(u8, state)
- __field(int, code)
- ),
- TP_fast_assign(
- DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->idx = idx;
- __entry->state = state;
- __entry->code = code;
- ),
- TP_printk("[%s:%u:%u:%u] SDMA completion state %s (%d)",
- __get_str(dev), __entry->ctxt, __entry->subctxt,
- __entry->idx, show_usdma_complete_state(__entry->state),
- __entry->code)
- );
-
-const char *print_u32_array(struct trace_seq *, u32 *, int);
-#define __print_u32_hex(arr, len) print_u32_array(p, arr, len)
-
-TRACE_EVENT(hfi1_sdma_user_header_ahg,
- TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 req,
- u8 sde, u8 ahgidx, u32 *ahg, int len, u32 tidval),
- TP_ARGS(dd, ctxt, subctxt, req, sde, ahgidx, ahg, len, tidval),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd)
- __field(u16, ctxt)
- __field(u8, subctxt)
- __field(u16, req)
- __field(u8, sde)
- __field(u8, idx)
- __field(int, len)
- __field(u32, tidval)
- __array(u32, ahg, 10)
- ),
- TP_fast_assign(
- DD_DEV_ASSIGN(dd);
- __entry->ctxt = ctxt;
- __entry->subctxt = subctxt;
- __entry->req = req;
- __entry->sde = sde;
- __entry->idx = ahgidx;
- __entry->len = len;
- __entry->tidval = tidval;
- memcpy(__entry->ahg, ahg, len * sizeof(u32));
- ),
- TP_printk("[%s:%u:%u:%u] (SDE%u/AHG%u) ahg[0-%d]=(%s) TIDVal=0x%x",
- __get_str(dev),
- __entry->ctxt,
- __entry->subctxt,
- __entry->req,
- __entry->sde,
- __entry->idx,
- __entry->len - 1,
- __print_u32_hex(__entry->ahg, __entry->len),
- __entry->tidval
- )
- );
-
-TRACE_EVENT(hfi1_sdma_state,
- TP_PROTO(struct sdma_engine *sde,
- const char *cstate,
- const char *nstate
- ),
- TP_ARGS(sde, cstate, nstate),
- TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
- __string(curstate, cstate)
- __string(newstate, nstate)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
- __assign_str(curstate, cstate);
- __assign_str(newstate, nstate);
- ),
- TP_printk("[%s] current state %s new state %s",
- __get_str(dev),
- __get_str(curstate),
- __get_str(newstate)
- )
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_rc
-
-DECLARE_EVENT_CLASS(hfi1_rc_template,
- TP_PROTO(struct rvt_qp *qp, u32 psn),
- TP_ARGS(qp, psn),
- TP_STRUCT__entry(
- DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
- __field(u32, qpn)
- __field(u32, s_flags)
- __field(u32, psn)
- __field(u32, s_psn)
- __field(u32, s_next_psn)
- __field(u32, s_sending_psn)
- __field(u32, s_sending_hpsn)
- __field(u32, r_psn)
- ),
- TP_fast_assign(
- DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
- __entry->qpn = qp->ibqp.qp_num;
- __entry->s_flags = qp->s_flags;
- __entry->psn = psn;
- __entry->s_psn = qp->s_psn;
- __entry->s_next_psn = qp->s_next_psn;
- __entry->s_sending_psn = qp->s_sending_psn;
- __entry->s_sending_hpsn = qp->s_sending_hpsn;
- __entry->r_psn = qp->r_psn;
- ),
- TP_printk(
- "[%s] qpn 0x%x s_flags 0x%x psn 0x%x s_psn 0x%x s_next_psn 0x%x s_sending_psn 0x%x sending_hpsn 0x%x r_psn 0x%x",
- __get_str(dev),
- __entry->qpn,
- __entry->s_flags,
- __entry->psn,
- __entry->s_psn,
- __entry->s_next_psn,
- __entry->s_sending_psn,
- __entry->s_sending_hpsn,
- __entry->r_psn
- )
-);
-
-DEFINE_EVENT(hfi1_rc_template, hfi1_rc_sendcomplete,
- TP_PROTO(struct rvt_qp *qp, u32 psn),
- TP_ARGS(qp, psn)
-);
-
-DEFINE_EVENT(hfi1_rc_template, hfi1_rc_ack,
- TP_PROTO(struct rvt_qp *qp, u32 psn),
- TP_ARGS(qp, psn)
-);
-
-DEFINE_EVENT(hfi1_rc_template, hfi1_rc_timeout,
- TP_PROTO(struct rvt_qp *qp, u32 psn),
- TP_ARGS(qp, psn)
-);
-
-DEFINE_EVENT(hfi1_rc_template, hfi1_rc_rcv_error,
- TP_PROTO(struct rvt_qp *qp, u32 psn),
- TP_ARGS(qp, psn)
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_misc
-
-TRACE_EVENT(hfi1_interrupt,
- TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry,
- int src),
- TP_ARGS(dd, is_entry, src),
- TP_STRUCT__entry(DD_DEV_ENTRY(dd)
- __array(char, buf, 64)
- __field(int, src)
- ),
- TP_fast_assign(DD_DEV_ASSIGN(dd)
- is_entry->is_name(__entry->buf, 64,
- src - is_entry->start);
- __entry->src = src;
- ),
- TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf,
- __entry->src)
-);
-
-/*
- * Note:
- * This produces a REALLY ugly trace in the console output when the string is
- * too long.
- */
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM hfi1_trace
-
-#define MAX_MSG_LEN 512
-
-DECLARE_EVENT_CLASS(hfi1_trace_template,
- TP_PROTO(const char *function, struct va_format *vaf),
- TP_ARGS(function, vaf),
- TP_STRUCT__entry(__string(function, function)
- __dynamic_array(char, msg, MAX_MSG_LEN)
- ),
- TP_fast_assign(__assign_str(function, function);
- WARN_ON_ONCE(vsnprintf
- (__get_dynamic_array(msg),
- MAX_MSG_LEN, vaf->fmt,
- *vaf->va) >=
- MAX_MSG_LEN);
- ),
- TP_printk("(%s) %s",
- __get_str(function),
- __get_str(msg))
-);
-
-/*
- * It may be nice to macroize the __hfi1_trace but the va_* stuff requires an
- * actual function to work and can not be in a macro.
- */
-#define __hfi1_trace_def(lvl) \
-void __hfi1_trace_##lvl(const char *funct, char *fmt, ...); \
- \
-DEFINE_EVENT(hfi1_trace_template, hfi1_ ##lvl, \
- TP_PROTO(const char *function, struct va_format *vaf), \
- TP_ARGS(function, vaf))
-
-#define __hfi1_trace_fn(lvl) \
-void __hfi1_trace_##lvl(const char *func, char *fmt, ...) \
-{ \
- struct va_format vaf = { \
- .fmt = fmt, \
- }; \
- va_list args; \
- \
- va_start(args, fmt); \
- vaf.va = &args; \
- trace_hfi1_ ##lvl(func, &vaf); \
- va_end(args); \
- return; \
-}
-
-/*
- * To create a new trace level simply define it below and as a __hfi1_trace_fn
- * in trace.c. This will create all the hooks for calling
- * hfi1_cdbg(LVL, fmt, ...); as well as take care of all
- * the debugfs stuff.
- */
-__hfi1_trace_def(PKT);
-__hfi1_trace_def(PROC);
-__hfi1_trace_def(SDMA);
-__hfi1_trace_def(LINKVERB);
-__hfi1_trace_def(DEBUG);
-__hfi1_trace_def(SNOOP);
-__hfi1_trace_def(CNTR);
-__hfi1_trace_def(PIO);
-__hfi1_trace_def(DC8051);
-__hfi1_trace_def(FIRMWARE);
-__hfi1_trace_def(RCVCTRL);
-__hfi1_trace_def(TID);
-__hfi1_trace_def(MMU);
-__hfi1_trace_def(IOCTL);
-
-#define hfi1_cdbg(which, fmt, ...) \
- __hfi1_trace_##which(__func__, fmt, ##__VA_ARGS__)
-
-#define hfi1_dbg(fmt, ...) \
- hfi1_cdbg(DEBUG, fmt, ##__VA_ARGS__)
-
-/*
- * Define HFI1_EARLY_DBG at compile time or here to enable early trace
- * messages. Do not check in an enablement for this.
- */
-
-#ifdef HFI1_EARLY_DBG
-#define hfi1_dbg_early(fmt, ...) \
- trace_printk(fmt, ##__VA_ARGS__)
-#else
-#define hfi1_dbg_early(fmt, ...)
-#endif
-
-#endif /* __HFI1_TRACE_H */
-
-#undef TRACE_INCLUDE_PATH
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace
-#include <trace/define_trace.h>
+#include "trace_dbg.h"
+#include "trace_misc.h"
+#include "trace_ctxts.h"
+#include "trace_ibhdrs.h"
+#include "trace_rc.h"
+#include "trace_rx.h"
+#include "trace_tx.h"
diff --git a/drivers/infiniband/hw/hfi1/trace_ctxts.h b/drivers/infiniband/hw/hfi1/trace_ctxts.h
new file mode 100644
index 000000000000..31654bbac1cf
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_ctxts.h
@@ -0,0 +1,141 @@
+/*
+* Copyright(c) 2015, 2016 Intel Corporation.
+*
+* This file is provided under a dual BSD/GPLv2 license. When using or
+* redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License 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.
+*
+* BSD LICENSE
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - 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.
+* - Neither the name of Intel Corporation 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 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.
+*
+*/
+#if !defined(__HFI1_TRACE_CTXTS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_CTXTS_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_ctxts
+
+#define UCTXT_FMT \
+ "cred:%u, credaddr:0x%llx, piobase:0x%p, rcvhdr_cnt:%u, " \
+ "rcvbase:0x%llx, rcvegrc:%u, rcvegrb:0x%llx"
+TRACE_EVENT(hfi1_uctxtdata,
+ TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt),
+ TP_ARGS(dd, uctxt),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __field(unsigned int, ctxt)
+ __field(u32, credits)
+ __field(u64, hw_free)
+ __field(void __iomem *, piobase)
+ __field(u16, rcvhdrq_cnt)
+ __field(u64, rcvhdrq_phys)
+ __field(u32, eager_cnt)
+ __field(u64, rcvegr_phys)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ __entry->ctxt = uctxt->ctxt;
+ __entry->credits = uctxt->sc->credits;
+ __entry->hw_free = le64_to_cpu(*uctxt->sc->hw_free);
+ __entry->piobase = uctxt->sc->base_addr;
+ __entry->rcvhdrq_cnt = uctxt->rcvhdrq_cnt;
+ __entry->rcvhdrq_phys = uctxt->rcvhdrq_phys;
+ __entry->eager_cnt = uctxt->egrbufs.alloced;
+ __entry->rcvegr_phys =
+ uctxt->egrbufs.rcvtids[0].phys;
+ ),
+ TP_printk("[%s] ctxt %u " UCTXT_FMT,
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->credits,
+ __entry->hw_free,
+ __entry->piobase,
+ __entry->rcvhdrq_cnt,
+ __entry->rcvhdrq_phys,
+ __entry->eager_cnt,
+ __entry->rcvegr_phys
+ )
+);
+
+#define CINFO_FMT \
+ "egrtids:%u, egr_size:%u, hdrq_cnt:%u, hdrq_size:%u, sdma_ring_size:%u"
+TRACE_EVENT(hfi1_ctxt_info,
+ TP_PROTO(struct hfi1_devdata *dd, unsigned int ctxt,
+ unsigned int subctxt,
+ struct hfi1_ctxt_info cinfo),
+ TP_ARGS(dd, ctxt, subctxt, cinfo),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __field(unsigned int, ctxt)
+ __field(unsigned int, subctxt)
+ __field(u16, egrtids)
+ __field(u16, rcvhdrq_cnt)
+ __field(u16, rcvhdrq_size)
+ __field(u16, sdma_ring_size)
+ __field(u32, rcvegr_size)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->egrtids = cinfo.egrtids;
+ __entry->rcvhdrq_cnt = cinfo.rcvhdrq_cnt;
+ __entry->rcvhdrq_size = cinfo.rcvhdrq_entsize;
+ __entry->sdma_ring_size = cinfo.sdma_ring_size;
+ __entry->rcvegr_size = cinfo.rcvegr_size;
+ ),
+ TP_printk("[%s] ctxt %u:%u " CINFO_FMT,
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->egrtids,
+ __entry->rcvegr_size,
+ __entry->rcvhdrq_cnt,
+ __entry->rcvhdrq_size,
+ __entry->sdma_ring_size
+ )
+);
+
+#endif /* __HFI1_TRACE_CTXTS_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_ctxts
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_dbg.h b/drivers/infiniband/hw/hfi1/trace_dbg.h
new file mode 100644
index 000000000000..0e7d929530c5
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_dbg.h
@@ -0,0 +1,155 @@
+/*
+* Copyright(c) 2015, 2016 Intel Corporation.
+*
+* This file is provided under a dual BSD/GPLv2 license. When using or
+* redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License 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.
+*
+* BSD LICENSE
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - 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.
+* - Neither the name of Intel Corporation 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 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.
+*
+*/
+#if !defined(__HFI1_TRACE_EXTRA_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_EXTRA_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+/*
+ * Note:
+ * This produces a REALLY ugly trace in the console output when the string is
+ * too long.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_dbg
+
+#define MAX_MSG_LEN 512
+
+DECLARE_EVENT_CLASS(hfi1_trace_template,
+ TP_PROTO(const char *function, struct va_format *vaf),
+ TP_ARGS(function, vaf),
+ TP_STRUCT__entry(__string(function, function)
+ __dynamic_array(char, msg, MAX_MSG_LEN)
+ ),
+ TP_fast_assign(__assign_str(function, function);
+ WARN_ON_ONCE(vsnprintf
+ (__get_dynamic_array(msg),
+ MAX_MSG_LEN, vaf->fmt,
+ *vaf->va) >=
+ MAX_MSG_LEN);
+ ),
+ TP_printk("(%s) %s",
+ __get_str(function),
+ __get_str(msg))
+);
+
+/*
+ * It may be nice to macroize the __hfi1_trace but the va_* stuff requires an
+ * actual function to work and can not be in a macro.
+ */
+#define __hfi1_trace_def(lvl) \
+void __hfi1_trace_##lvl(const char *funct, char *fmt, ...); \
+ \
+DEFINE_EVENT(hfi1_trace_template, hfi1_ ##lvl, \
+ TP_PROTO(const char *function, struct va_format *vaf), \
+ TP_ARGS(function, vaf))
+
+#define __hfi1_trace_fn(lvl) \
+void __hfi1_trace_##lvl(const char *func, char *fmt, ...) \
+{ \
+ struct va_format vaf = { \
+ .fmt = fmt, \
+ }; \
+ va_list args; \
+ \
+ va_start(args, fmt); \
+ vaf.va = &args; \
+ trace_hfi1_ ##lvl(func, &vaf); \
+ va_end(args); \
+ return; \
+}
+
+/*
+ * To create a new trace level simply define it below and as a __hfi1_trace_fn
+ * in trace.c. This will create all the hooks for calling
+ * hfi1_cdbg(LVL, fmt, ...); as well as take care of all
+ * the debugfs stuff.
+ */
+__hfi1_trace_def(PKT);
+__hfi1_trace_def(PROC);
+__hfi1_trace_def(SDMA);
+__hfi1_trace_def(LINKVERB);
+__hfi1_trace_def(DEBUG);
+__hfi1_trace_def(SNOOP);
+__hfi1_trace_def(CNTR);
+__hfi1_trace_def(PIO);
+__hfi1_trace_def(DC8051);
+__hfi1_trace_def(FIRMWARE);
+__hfi1_trace_def(RCVCTRL);
+__hfi1_trace_def(TID);
+__hfi1_trace_def(MMU);
+__hfi1_trace_def(IOCTL);
+
+#define hfi1_cdbg(which, fmt, ...) \
+ __hfi1_trace_##which(__func__, fmt, ##__VA_ARGS__)
+
+#define hfi1_dbg(fmt, ...) \
+ hfi1_cdbg(DEBUG, fmt, ##__VA_ARGS__)
+
+/*
+ * Define HFI1_EARLY_DBG at compile time or here to enable early trace
+ * messages. Do not check in an enablement for this.
+ */
+
+#ifdef HFI1_EARLY_DBG
+#define hfi1_dbg_early(fmt, ...) \
+ trace_printk(fmt, ##__VA_ARGS__)
+#else
+#define hfi1_dbg_early(fmt, ...)
+#endif
+
+#endif /* __HFI1_TRACE_EXTRA_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_dbg
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_ibhdrs.h b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h
new file mode 100644
index 000000000000..c3e41aed0034
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_ibhdrs.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright(c) 2015, 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Intel Corporation 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 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.
+ *
+ */
+#if !defined(__HFI1_TRACE_IBHDRS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_IBHDRS_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_ibhdrs
+
+u8 ibhdr_exhdr_len(struct hfi1_ib_header *hdr);
+const char *parse_everbs_hdrs(struct trace_seq *p, u8 opcode, void *ehdrs);
+
+#define __parse_ib_ehdrs(op, ehdrs) parse_everbs_hdrs(p, op, ehdrs)
+
+#define lrh_name(lrh) { HFI1_##lrh, #lrh }
+#define show_lnh(lrh) \
+__print_symbolic(lrh, \
+ lrh_name(LRH_BTH), \
+ lrh_name(LRH_GRH))
+
+#define LRH_PRN "vl %d lver %d sl %d lnh %d,%s dlid %.4x len %d slid %.4x"
+#define BTH_PRN \
+ "op 0x%.2x,%s se %d m %d pad %d tver %d pkey 0x%.4x " \
+ "f %d b %d qpn 0x%.6x a %d psn 0x%.8x"
+#define EHDR_PRN "%s"
+
+DECLARE_EVENT_CLASS(hfi1_ibhdr_template,
+ TP_PROTO(struct hfi1_devdata *dd,
+ struct hfi1_ib_header *hdr),
+ TP_ARGS(dd, hdr),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd)
+ /* LRH */
+ __field(u8, vl)
+ __field(u8, lver)
+ __field(u8, sl)
+ __field(u8, lnh)
+ __field(u16, dlid)
+ __field(u16, len)
+ __field(u16, slid)
+ /* BTH */
+ __field(u8, opcode)
+ __field(u8, se)
+ __field(u8, m)
+ __field(u8, pad)
+ __field(u8, tver)
+ __field(u16, pkey)
+ __field(u8, f)
+ __field(u8, b)
+ __field(u32, qpn)
+ __field(u8, a)
+ __field(u32, psn)
+ /* extended headers */
+ __dynamic_array(u8, ehdrs, ibhdr_exhdr_len(hdr))
+ ),
+ TP_fast_assign(
+ struct hfi1_other_headers *ohdr;
+
+ DD_DEV_ASSIGN(dd);
+ /* LRH */
+ __entry->vl =
+ (u8)(be16_to_cpu(hdr->lrh[0]) >> 12);
+ __entry->lver =
+ (u8)(be16_to_cpu(hdr->lrh[0]) >> 8) & 0xf;
+ __entry->sl =
+ (u8)(be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf;
+ __entry->lnh =
+ (u8)(be16_to_cpu(hdr->lrh[0]) & 3);
+ __entry->dlid =
+ be16_to_cpu(hdr->lrh[1]);
+ /* allow for larger len */
+ __entry->len =
+ be16_to_cpu(hdr->lrh[2]);
+ __entry->slid =
+ be16_to_cpu(hdr->lrh[3]);
+ /* BTH */
+ if (__entry->lnh == HFI1_LRH_BTH)
+ ohdr = &hdr->u.oth;
+ else
+ ohdr = &hdr->u.l.oth;
+ __entry->opcode =
+ (be32_to_cpu(ohdr->bth[0]) >> 24) & 0xff;
+ __entry->se =
+ (be32_to_cpu(ohdr->bth[0]) >> 23) & 1;
+ __entry->m =
+ (be32_to_cpu(ohdr->bth[0]) >> 22) & 1;
+ __entry->pad =
+ (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ __entry->tver =
+ (be32_to_cpu(ohdr->bth[0]) >> 16) & 0xf;
+ __entry->pkey =
+ be32_to_cpu(ohdr->bth[0]) & 0xffff;
+ __entry->f =
+ (be32_to_cpu(ohdr->bth[1]) >> HFI1_FECN_SHIFT) &
+ HFI1_FECN_MASK;
+ __entry->b =
+ (be32_to_cpu(ohdr->bth[1]) >> HFI1_BECN_SHIFT) &
+ HFI1_BECN_MASK;
+ __entry->qpn =
+ be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
+ __entry->a =
+ (be32_to_cpu(ohdr->bth[2]) >> 31) & 1;
+ /* allow for larger PSN */
+ __entry->psn =
+ be32_to_cpu(ohdr->bth[2]) & 0x7fffffff;
+ /* extended headers */
+ memcpy(__get_dynamic_array(ehdrs), &ohdr->u,
+ ibhdr_exhdr_len(hdr));
+ ),
+ TP_printk("[%s] " LRH_PRN " " BTH_PRN " " EHDR_PRN,
+ __get_str(dev),
+ /* LRH */
+ __entry->vl,
+ __entry->lver,
+ __entry->sl,
+ __entry->lnh, show_lnh(__entry->lnh),
+ __entry->dlid,
+ __entry->len,
+ __entry->slid,
+ /* BTH */
+ __entry->opcode, show_ib_opcode(__entry->opcode),
+ __entry->se,
+ __entry->m,
+ __entry->pad,
+ __entry->tver,
+ __entry->pkey,
+ __entry->f,
+ __entry->b,
+ __entry->qpn,
+ __entry->a,
+ __entry->psn,
+ /* extended headers */
+ __parse_ib_ehdrs(
+ __entry->opcode,
+ (void *)__get_dynamic_array(ehdrs))
+ )
+);
+
+DEFINE_EVENT(hfi1_ibhdr_template, input_ibhdr,
+ TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
+ TP_ARGS(dd, hdr));
+
+DEFINE_EVENT(hfi1_ibhdr_template, pio_output_ibhdr,
+ TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
+ TP_ARGS(dd, hdr));
+
+DEFINE_EVENT(hfi1_ibhdr_template, ack_output_ibhdr,
+ TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
+ TP_ARGS(dd, hdr));
+
+DEFINE_EVENT(hfi1_ibhdr_template, sdma_output_ibhdr,
+ TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ib_header *hdr),
+ TP_ARGS(dd, hdr));
+
+#endif /* __HFI1_TRACE_IBHDRS_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_ibhdrs
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_misc.h b/drivers/infiniband/hw/hfi1/trace_misc.h
new file mode 100644
index 000000000000..d308454af7fd
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_misc.h
@@ -0,0 +1,81 @@
+/*
+* Copyright(c) 2015, 2016 Intel Corporation.
+*
+* This file is provided under a dual BSD/GPLv2 license. When using or
+* redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License 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.
+*
+* BSD LICENSE
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - 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.
+* - Neither the name of Intel Corporation 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 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.
+*
+*/
+#if !defined(__HFI1_TRACE_MISC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_MISC_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_misc
+
+TRACE_EVENT(hfi1_interrupt,
+ TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry,
+ int src),
+ TP_ARGS(dd, is_entry, src),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __array(char, buf, 64)
+ __field(int, src)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd)
+ is_entry->is_name(__entry->buf, 64,
+ src - is_entry->start);
+ __entry->src = src;
+ ),
+ TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf,
+ __entry->src)
+);
+
+#endif /* __HFI1_TRACE_MISC_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_misc
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_rc.h b/drivers/infiniband/hw/hfi1/trace_rc.h
new file mode 100644
index 000000000000..5ea5005f9f41
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_rc.h
@@ -0,0 +1,123 @@
+/*
+* Copyright(c) 2015, 2016 Intel Corporation.
+*
+* This file is provided under a dual BSD/GPLv2 license. When using or
+* redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License 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.
+*
+* BSD LICENSE
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* - 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.
+* - Neither the name of Intel Corporation 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 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.
+*
+*/
+#if !defined(__HFI1_TRACE_RC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_RC_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_rc
+
+DECLARE_EVENT_CLASS(hfi1_rc_template,
+ TP_PROTO(struct rvt_qp *qp, u32 psn),
+ TP_ARGS(qp, psn),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
+ __field(u32, qpn)
+ __field(u32, s_flags)
+ __field(u32, psn)
+ __field(u32, s_psn)
+ __field(u32, s_next_psn)
+ __field(u32, s_sending_psn)
+ __field(u32, s_sending_hpsn)
+ __field(u32, r_psn)
+ ),
+ TP_fast_assign(
+ DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
+ __entry->qpn = qp->ibqp.qp_num;
+ __entry->s_flags = qp->s_flags;
+ __entry->psn = psn;
+ __entry->s_psn = qp->s_psn;
+ __entry->s_next_psn = qp->s_next_psn;
+ __entry->s_sending_psn = qp->s_sending_psn;
+ __entry->s_sending_hpsn = qp->s_sending_hpsn;
+ __entry->r_psn = qp->r_psn;
+ ),
+ TP_printk(
+ "[%s] qpn 0x%x s_flags 0x%x psn 0x%x s_psn 0x%x s_next_psn 0x%x s_sending_psn 0x%x sending_hpsn 0x%x r_psn 0x%x",
+ __get_str(dev),
+ __entry->qpn,
+ __entry->s_flags,
+ __entry->psn,
+ __entry->s_psn,
+ __entry->s_next_psn,
+ __entry->s_sending_psn,
+ __entry->s_sending_hpsn,
+ __entry->r_psn
+ )
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_sendcomplete,
+ TP_PROTO(struct rvt_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_ack,
+ TP_PROTO(struct rvt_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_timeout,
+ TP_PROTO(struct rvt_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+DEFINE_EVENT(hfi1_rc_template, hfi1_rcv_error,
+ TP_PROTO(struct rvt_qp *qp, u32 psn),
+ TP_ARGS(qp, psn)
+);
+
+#endif /* __HFI1_TRACE_RC_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_rc
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_rx.h b/drivers/infiniband/hw/hfi1/trace_rx.h
new file mode 100644
index 000000000000..9ba1f615ec95
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_rx.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright(c) 2015, 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Intel Corporation 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 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.
+ *
+ */
+#if !defined(__HFI1_TRACE_RX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_RX_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_rx
+
+TRACE_EVENT(hfi1_rcvhdr,
+ TP_PROTO(struct hfi1_devdata *dd,
+ u32 ctxt,
+ u64 eflags,
+ u32 etype,
+ u32 hlen,
+ u32 tlen,
+ u32 updegr,
+ u32 etail
+ ),
+ TP_ARGS(dd, ctxt, eflags, etype, hlen, tlen, updegr, etail),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __field(u64, eflags)
+ __field(u32, ctxt)
+ __field(u32, etype)
+ __field(u32, hlen)
+ __field(u32, tlen)
+ __field(u32, updegr)
+ __field(u32, etail)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ __entry->eflags = eflags;
+ __entry->ctxt = ctxt;
+ __entry->etype = etype;
+ __entry->hlen = hlen;
+ __entry->tlen = tlen;
+ __entry->updegr = updegr;
+ __entry->etail = etail;
+ ),
+ TP_printk(
+ "[%s] ctxt %d eflags 0x%llx etype %d,%s hlen %d tlen %d updegr %d etail %d",
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->eflags,
+ __entry->etype, show_packettype(__entry->etype),
+ __entry->hlen,
+ __entry->tlen,
+ __entry->updegr,
+ __entry->etail
+ )
+);
+
+TRACE_EVENT(hfi1_receive_interrupt,
+ TP_PROTO(struct hfi1_devdata *dd, u32 ctxt),
+ TP_ARGS(dd, ctxt),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __field(u32, ctxt)
+ __field(u8, slow_path)
+ __field(u8, dma_rtail)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ if (dd->rcd[ctxt]->do_interrupt ==
+ &handle_receive_interrupt) {
+ __entry->slow_path = 1;
+ __entry->dma_rtail = 0xFF;
+ } else if (dd->rcd[ctxt]->do_interrupt ==
+ &handle_receive_interrupt_dma_rtail){
+ __entry->dma_rtail = 1;
+ __entry->slow_path = 0;
+ } else if (dd->rcd[ctxt]->do_interrupt ==
+ &handle_receive_interrupt_nodma_rtail) {
+ __entry->dma_rtail = 0;
+ __entry->slow_path = 0;
+ }
+ ),
+ TP_printk("[%s] ctxt %d SlowPath: %d DmaRtail: %d",
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->slow_path,
+ __entry->dma_rtail
+ )
+);
+
+TRACE_EVENT(hfi1_exp_tid_reg,
+ TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr,
+ u32 npages, unsigned long va, unsigned long pa,
+ dma_addr_t dma),
+ TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma),
+ TP_STRUCT__entry(
+ __field(unsigned int, ctxt)
+ __field(u16, subctxt)
+ __field(u32, rarr)
+ __field(u32, npages)
+ __field(unsigned long, va)
+ __field(unsigned long, pa)
+ __field(dma_addr_t, dma)
+ ),
+ TP_fast_assign(
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->rarr = rarr;
+ __entry->npages = npages;
+ __entry->va = va;
+ __entry->pa = pa;
+ __entry->dma = dma;
+ ),
+ TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx, va:0x%lx dma:0x%llx",
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->rarr,
+ __entry->npages,
+ __entry->pa,
+ __entry->va,
+ __entry->dma
+ )
+ );
+
+TRACE_EVENT(hfi1_exp_tid_unreg,
+ TP_PROTO(unsigned int ctxt, u16 subctxt, u32 rarr, u32 npages,
+ unsigned long va, unsigned long pa, dma_addr_t dma),
+ TP_ARGS(ctxt, subctxt, rarr, npages, va, pa, dma),
+ TP_STRUCT__entry(
+ __field(unsigned int, ctxt)
+ __field(u16, subctxt)
+ __field(u32, rarr)
+ __field(u32, npages)
+ __field(unsigned long, va)
+ __field(unsigned long, pa)
+ __field(dma_addr_t, dma)
+ ),
+ TP_fast_assign(
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->rarr = rarr;
+ __entry->npages = npages;
+ __entry->va = va;
+ __entry->pa = pa;
+ __entry->dma = dma;
+ ),
+ TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx, va:0x%lx dma:0x%llx",
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->rarr,
+ __entry->npages,
+ __entry->pa,
+ __entry->va,
+ __entry->dma
+ )
+ );
+
+TRACE_EVENT(hfi1_exp_tid_inval,
+ TP_PROTO(unsigned int ctxt, u16 subctxt, unsigned long va, u32 rarr,
+ u32 npages, dma_addr_t dma),
+ TP_ARGS(ctxt, subctxt, va, rarr, npages, dma),
+ TP_STRUCT__entry(
+ __field(unsigned int, ctxt)
+ __field(u16, subctxt)
+ __field(unsigned long, va)
+ __field(u32, rarr)
+ __field(u32, npages)
+ __field(dma_addr_t, dma)
+ ),
+ TP_fast_assign(
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->va = va;
+ __entry->rarr = rarr;
+ __entry->npages = npages;
+ __entry->dma = dma;
+ ),
+ TP_printk("[%u:%u] entry:%u, %u pages @ 0x%lx dma: 0x%llx",
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->rarr,
+ __entry->npages,
+ __entry->va,
+ __entry->dma
+ )
+ );
+
+TRACE_EVENT(hfi1_mmu_invalidate,
+ TP_PROTO(unsigned int ctxt, u16 subctxt, const char *type,
+ unsigned long start, unsigned long end),
+ TP_ARGS(ctxt, subctxt, type, start, end),
+ TP_STRUCT__entry(
+ __field(unsigned int, ctxt)
+ __field(u16, subctxt)
+ __string(type, type)
+ __field(unsigned long, start)
+ __field(unsigned long, end)
+ ),
+ TP_fast_assign(
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __assign_str(type, type);
+ __entry->start = start;
+ __entry->end = end;
+ ),
+ TP_printk("[%3u:%02u] MMU Invalidate (%s) 0x%lx - 0x%lx",
+ __entry->ctxt,
+ __entry->subctxt,
+ __get_str(type),
+ __entry->start,
+ __entry->end
+ )
+ );
+
+#define SNOOP_PRN \
+ "slid %.4x dlid %.4x qpn 0x%.6x opcode 0x%.2x,%s " \
+ "svc lvl %d pkey 0x%.4x [header = %d bytes] [data = %d bytes]"
+
+TRACE_EVENT(snoop_capture,
+ TP_PROTO(struct hfi1_devdata *dd,
+ int hdr_len,
+ struct hfi1_ib_header *hdr,
+ int data_len,
+ void *data),
+ TP_ARGS(dd, hdr_len, hdr, data_len, data),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd)
+ __field(u16, slid)
+ __field(u16, dlid)
+ __field(u32, qpn)
+ __field(u8, opcode)
+ __field(u8, sl)
+ __field(u16, pkey)
+ __field(u32, hdr_len)
+ __field(u32, data_len)
+ __field(u8, lnh)
+ __dynamic_array(u8, raw_hdr, hdr_len)
+ __dynamic_array(u8, raw_pkt, data_len)
+ ),
+ TP_fast_assign(
+ struct hfi1_other_headers *ohdr;
+
+ __entry->lnh = (u8)(be16_to_cpu(hdr->lrh[0]) & 3);
+ if (__entry->lnh == HFI1_LRH_BTH)
+ ohdr = &hdr->u.oth;
+ else
+ ohdr = &hdr->u.l.oth;
+ DD_DEV_ASSIGN(dd);
+ __entry->slid = be16_to_cpu(hdr->lrh[3]);
+ __entry->dlid = be16_to_cpu(hdr->lrh[1]);
+ __entry->qpn = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
+ __entry->opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0xff;
+ __entry->sl = (u8)(be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf;
+ __entry->pkey = be32_to_cpu(ohdr->bth[0]) & 0xffff;
+ __entry->hdr_len = hdr_len;
+ __entry->data_len = data_len;
+ memcpy(__get_dynamic_array(raw_hdr), hdr, hdr_len);
+ memcpy(__get_dynamic_array(raw_pkt), data, data_len);
+ ),
+ TP_printk(
+ "[%s] " SNOOP_PRN,
+ __get_str(dev),
+ __entry->slid,
+ __entry->dlid,
+ __entry->qpn,
+ __entry->opcode,
+ show_ib_opcode(__entry->opcode),
+ __entry->sl,
+ __entry->pkey,
+ __entry->hdr_len,
+ __entry->data_len
+ )
+);
+
+#endif /* __HFI1_TRACE_RX_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_rx
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/trace_tx.h b/drivers/infiniband/hw/hfi1/trace_tx.h
new file mode 100644
index 000000000000..415d6be42c5d
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/trace_tx.h
@@ -0,0 +1,642 @@
+/*
+ * Copyright(c) 2015, 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Intel Corporation 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 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.
+ *
+ */
+#if !defined(__HFI1_TRACE_TX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __HFI1_TRACE_TX_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include "hfi.h"
+#include "mad.h"
+#include "sdma.h"
+
+const char *parse_sdma_flags(struct trace_seq *p, u64 desc0, u64 desc1);
+
+#define __parse_sdma_flags(desc0, desc1) parse_sdma_flags(p, desc0, desc1)
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hfi1_tx
+
+TRACE_EVENT(hfi1_piofree,
+ TP_PROTO(struct send_context *sc, int extra),
+ TP_ARGS(sc, extra),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sc->dd)
+ __field(u32, sw_index)
+ __field(u32, hw_context)
+ __field(int, extra)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sc->dd);
+ __entry->sw_index = sc->sw_index;
+ __entry->hw_context = sc->hw_context;
+ __entry->extra = extra;
+ ),
+ TP_printk("[%s] ctxt %u(%u) extra %d",
+ __get_str(dev),
+ __entry->sw_index,
+ __entry->hw_context,
+ __entry->extra
+ )
+);
+
+TRACE_EVENT(hfi1_wantpiointr,
+ TP_PROTO(struct send_context *sc, u32 needint, u64 credit_ctrl),
+ TP_ARGS(sc, needint, credit_ctrl),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sc->dd)
+ __field(u32, sw_index)
+ __field(u32, hw_context)
+ __field(u32, needint)
+ __field(u64, credit_ctrl)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sc->dd);
+ __entry->sw_index = sc->sw_index;
+ __entry->hw_context = sc->hw_context;
+ __entry->needint = needint;
+ __entry->credit_ctrl = credit_ctrl;
+ ),
+ TP_printk("[%s] ctxt %u(%u) on %d credit_ctrl 0x%llx",
+ __get_str(dev),
+ __entry->sw_index,
+ __entry->hw_context,
+ __entry->needint,
+ (unsigned long long)__entry->credit_ctrl
+ )
+);
+
+DECLARE_EVENT_CLASS(hfi1_qpsleepwakeup_template,
+ TP_PROTO(struct rvt_qp *qp, u32 flags),
+ TP_ARGS(qp, flags),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
+ __field(u32, qpn)
+ __field(u32, flags)
+ __field(u32, s_flags)
+ ),
+ TP_fast_assign(
+ DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
+ __entry->flags = flags;
+ __entry->qpn = qp->ibqp.qp_num;
+ __entry->s_flags = qp->s_flags;
+ ),
+ TP_printk(
+ "[%s] qpn 0x%x flags 0x%x s_flags 0x%x",
+ __get_str(dev),
+ __entry->qpn,
+ __entry->flags,
+ __entry->s_flags
+ )
+);
+
+DEFINE_EVENT(hfi1_qpsleepwakeup_template, hfi1_qpwakeup,
+ TP_PROTO(struct rvt_qp *qp, u32 flags),
+ TP_ARGS(qp, flags));
+
+DEFINE_EVENT(hfi1_qpsleepwakeup_template, hfi1_qpsleep,
+ TP_PROTO(struct rvt_qp *qp, u32 flags),
+ TP_ARGS(qp, flags));
+
+TRACE_EVENT(hfi1_sdma_descriptor,
+ TP_PROTO(struct sdma_engine *sde,
+ u64 desc0,
+ u64 desc1,
+ u16 e,
+ void *descp),
+ TP_ARGS(sde, desc0, desc1, e, descp),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(void *, descp)
+ __field(u64, desc0)
+ __field(u64, desc1)
+ __field(u16, e)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->desc0 = desc0;
+ __entry->desc1 = desc1;
+ __entry->idx = sde->this_idx;
+ __entry->descp = descp;
+ __entry->e = e;
+ ),
+ TP_printk(
+ "[%s] SDE(%u) flags:%s addr:0x%016llx gen:%u len:%u d0:%016llx d1:%016llx to %p,%u",
+ __get_str(dev),
+ __entry->idx,
+ __parse_sdma_flags(__entry->desc0, __entry->desc1),
+ (__entry->desc0 >> SDMA_DESC0_PHY_ADDR_SHIFT) &
+ SDMA_DESC0_PHY_ADDR_MASK,
+ (u8)((__entry->desc1 >> SDMA_DESC1_GENERATION_SHIFT) &
+ SDMA_DESC1_GENERATION_MASK),
+ (u16)((__entry->desc0 >> SDMA_DESC0_BYTE_COUNT_SHIFT) &
+ SDMA_DESC0_BYTE_COUNT_MASK),
+ __entry->desc0,
+ __entry->desc1,
+ __entry->descp,
+ __entry->e
+ )
+);
+
+TRACE_EVENT(hfi1_sdma_engine_select,
+ TP_PROTO(struct hfi1_devdata *dd, u32 sel, u8 vl, u8 idx),
+ TP_ARGS(dd, sel, vl, idx),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __field(u32, sel)
+ __field(u8, vl)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ __entry->sel = sel;
+ __entry->vl = vl;
+ __entry->idx = idx;
+ ),
+ TP_printk("[%s] selecting SDE %u sel 0x%x vl %u",
+ __get_str(dev),
+ __entry->idx,
+ __entry->sel,
+ __entry->vl
+ )
+);
+
+DECLARE_EVENT_CLASS(hfi1_sdma_engine_class,
+ TP_PROTO(struct sdma_engine *sde, u64 status),
+ TP_ARGS(sde, status),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(u64, status)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->status = status;
+ __entry->idx = sde->this_idx;
+ ),
+ TP_printk("[%s] SDE(%u) status %llx",
+ __get_str(dev),
+ __entry->idx,
+ (unsigned long long)__entry->status
+ )
+);
+
+DEFINE_EVENT(hfi1_sdma_engine_class, hfi1_sdma_engine_interrupt,
+ TP_PROTO(struct sdma_engine *sde, u64 status),
+ TP_ARGS(sde, status)
+);
+
+DEFINE_EVENT(hfi1_sdma_engine_class, hfi1_sdma_engine_progress,
+ TP_PROTO(struct sdma_engine *sde, u64 status),
+ TP_ARGS(sde, status)
+);
+
+DECLARE_EVENT_CLASS(hfi1_sdma_ahg_ad,
+ TP_PROTO(struct sdma_engine *sde, int aidx),
+ TP_ARGS(sde, aidx),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(int, aidx)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->idx = sde->this_idx;
+ __entry->aidx = aidx;
+ ),
+ TP_printk("[%s] SDE(%u) aidx %d",
+ __get_str(dev),
+ __entry->idx,
+ __entry->aidx
+ )
+);
+
+DEFINE_EVENT(hfi1_sdma_ahg_ad, hfi1_ahg_allocate,
+ TP_PROTO(struct sdma_engine *sde, int aidx),
+ TP_ARGS(sde, aidx));
+
+DEFINE_EVENT(hfi1_sdma_ahg_ad, hfi1_ahg_deallocate,
+ TP_PROTO(struct sdma_engine *sde, int aidx),
+ TP_ARGS(sde, aidx));
+
+#ifdef CONFIG_HFI1_DEBUG_SDMA_ORDER
+TRACE_EVENT(hfi1_sdma_progress,
+ TP_PROTO(struct sdma_engine *sde,
+ u16 hwhead,
+ u16 swhead,
+ struct sdma_txreq *txp
+ ),
+ TP_ARGS(sde, hwhead, swhead, txp),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(u64, sn)
+ __field(u16, hwhead)
+ __field(u16, swhead)
+ __field(u16, txnext)
+ __field(u16, tx_tail)
+ __field(u16, tx_head)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->hwhead = hwhead;
+ __entry->swhead = swhead;
+ __entry->tx_tail = sde->tx_tail;
+ __entry->tx_head = sde->tx_head;
+ __entry->txnext = txp ? txp->next_descq_idx : ~0;
+ __entry->idx = sde->this_idx;
+ __entry->sn = txp ? txp->sn : ~0;
+ ),
+ TP_printk(
+ "[%s] SDE(%u) sn %llu hwhead %u swhead %u next_descq_idx %u tx_head %u tx_tail %u",
+ __get_str(dev),
+ __entry->idx,
+ __entry->sn,
+ __entry->hwhead,
+ __entry->swhead,
+ __entry->txnext,
+ __entry->tx_head,
+ __entry->tx_tail
+ )
+);
+#else
+TRACE_EVENT(hfi1_sdma_progress,
+ TP_PROTO(struct sdma_engine *sde,
+ u16 hwhead, u16 swhead,
+ struct sdma_txreq *txp
+ ),
+ TP_ARGS(sde, hwhead, swhead, txp),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(u16, hwhead)
+ __field(u16, swhead)
+ __field(u16, txnext)
+ __field(u16, tx_tail)
+ __field(u16, tx_head)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->hwhead = hwhead;
+ __entry->swhead = swhead;
+ __entry->tx_tail = sde->tx_tail;
+ __entry->tx_head = sde->tx_head;
+ __entry->txnext = txp ? txp->next_descq_idx : ~0;
+ __entry->idx = sde->this_idx;
+ ),
+ TP_printk(
+ "[%s] SDE(%u) hwhead %u swhead %u next_descq_idx %u tx_head %u tx_tail %u",
+ __get_str(dev),
+ __entry->idx,
+ __entry->hwhead,
+ __entry->swhead,
+ __entry->txnext,
+ __entry->tx_head,
+ __entry->tx_tail
+ )
+);
+#endif
+
+DECLARE_EVENT_CLASS(hfi1_sdma_sn,
+ TP_PROTO(struct sdma_engine *sde, u64 sn),
+ TP_ARGS(sde, sn),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __field(u64, sn)
+ __field(u8, idx)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __entry->sn = sn;
+ __entry->idx = sde->this_idx;
+ ),
+ TP_printk("[%s] SDE(%u) sn %llu",
+ __get_str(dev),
+ __entry->idx,
+ __entry->sn
+ )
+);
+
+DEFINE_EVENT(hfi1_sdma_sn, hfi1_sdma_out_sn,
+ TP_PROTO(
+ struct sdma_engine *sde,
+ u64 sn
+ ),
+ TP_ARGS(sde, sn)
+);
+
+DEFINE_EVENT(hfi1_sdma_sn, hfi1_sdma_in_sn,
+ TP_PROTO(struct sdma_engine *sde, u64 sn),
+ TP_ARGS(sde, sn)
+);
+
+#define USDMA_HDR_FORMAT \
+ "[%s:%u:%u:%u] PBC=(0x%x 0x%x) LRH=(0x%x 0x%x) BTH=(0x%x 0x%x 0x%x) KDETH=(0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x) TIDVal=0x%x"
+
+TRACE_EVENT(hfi1_sdma_user_header,
+ TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 req,
+ struct hfi1_pkt_header *hdr, u32 tidval),
+ TP_ARGS(dd, ctxt, subctxt, req, hdr, tidval),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd)
+ __field(u16, ctxt)
+ __field(u8, subctxt)
+ __field(u16, req)
+ __field(u32, pbc0)
+ __field(u32, pbc1)
+ __field(u32, lrh0)
+ __field(u32, lrh1)
+ __field(u32, bth0)
+ __field(u32, bth1)
+ __field(u32, bth2)
+ __field(u32, kdeth0)
+ __field(u32, kdeth1)
+ __field(u32, kdeth2)
+ __field(u32, kdeth3)
+ __field(u32, kdeth4)
+ __field(u32, kdeth5)
+ __field(u32, kdeth6)
+ __field(u32, kdeth7)
+ __field(u32, kdeth8)
+ __field(u32, tidval)
+ ),
+ TP_fast_assign(
+ __le32 *pbc = (__le32 *)hdr->pbc;
+ __be32 *lrh = (__be32 *)hdr->lrh;
+ __be32 *bth = (__be32 *)hdr->bth;
+ __le32 *kdeth = (__le32 *)&hdr->kdeth;
+
+ DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->req = req;
+ __entry->pbc0 = le32_to_cpu(pbc[0]);
+ __entry->pbc1 = le32_to_cpu(pbc[1]);
+ __entry->lrh0 = be32_to_cpu(lrh[0]);
+ __entry->lrh1 = be32_to_cpu(lrh[1]);
+ __entry->bth0 = be32_to_cpu(bth[0]);
+ __entry->bth1 = be32_to_cpu(bth[1]);
+ __entry->bth2 = be32_to_cpu(bth[2]);
+ __entry->kdeth0 = le32_to_cpu(kdeth[0]);
+ __entry->kdeth1 = le32_to_cpu(kdeth[1]);
+ __entry->kdeth2 = le32_to_cpu(kdeth[2]);
+ __entry->kdeth3 = le32_to_cpu(kdeth[3]);
+ __entry->kdeth4 = le32_to_cpu(kdeth[4]);
+ __entry->kdeth5 = le32_to_cpu(kdeth[5]);
+ __entry->kdeth6 = le32_to_cpu(kdeth[6]);
+ __entry->kdeth7 = le32_to_cpu(kdeth[7]);
+ __entry->kdeth8 = le32_to_cpu(kdeth[8]);
+ __entry->tidval = tidval;
+ ),
+ TP_printk(USDMA_HDR_FORMAT,
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->req,
+ __entry->pbc1,
+ __entry->pbc0,
+ __entry->lrh0,
+ __entry->lrh1,
+ __entry->bth0,
+ __entry->bth1,
+ __entry->bth2,
+ __entry->kdeth0,
+ __entry->kdeth1,
+ __entry->kdeth2,
+ __entry->kdeth3,
+ __entry->kdeth4,
+ __entry->kdeth5,
+ __entry->kdeth6,
+ __entry->kdeth7,
+ __entry->kdeth8,
+ __entry->tidval
+ )
+);
+
+#define SDMA_UREQ_FMT \
+ "[%s:%u:%u] ver/op=0x%x, iovcnt=%u, npkts=%u, frag=%u, idx=%u"
+TRACE_EVENT(hfi1_sdma_user_reqinfo,
+ TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 *i),
+ TP_ARGS(dd, ctxt, subctxt, i),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd);
+ __field(u16, ctxt)
+ __field(u8, subctxt)
+ __field(u8, ver_opcode)
+ __field(u8, iovcnt)
+ __field(u16, npkts)
+ __field(u16, fragsize)
+ __field(u16, comp_idx)
+ ),
+ TP_fast_assign(
+ DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->ver_opcode = i[0] & 0xff;
+ __entry->iovcnt = (i[0] >> 8) & 0xff;
+ __entry->npkts = i[1];
+ __entry->fragsize = i[2];
+ __entry->comp_idx = i[3];
+ ),
+ TP_printk(SDMA_UREQ_FMT,
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->ver_opcode,
+ __entry->iovcnt,
+ __entry->npkts,
+ __entry->fragsize,
+ __entry->comp_idx
+ )
+);
+
+#define usdma_complete_name(st) { st, #st }
+#define show_usdma_complete_state(st) \
+ __print_symbolic(st, \
+ usdma_complete_name(FREE), \
+ usdma_complete_name(QUEUED), \
+ usdma_complete_name(COMPLETE), \
+ usdma_complete_name(ERROR))
+
+TRACE_EVENT(hfi1_sdma_user_completion,
+ TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 idx,
+ u8 state, int code),
+ TP_ARGS(dd, ctxt, subctxt, idx, state, code),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd)
+ __field(u16, ctxt)
+ __field(u8, subctxt)
+ __field(u16, idx)
+ __field(u8, state)
+ __field(int, code)
+ ),
+ TP_fast_assign(
+ DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->idx = idx;
+ __entry->state = state;
+ __entry->code = code;
+ ),
+ TP_printk("[%s:%u:%u:%u] SDMA completion state %s (%d)",
+ __get_str(dev), __entry->ctxt, __entry->subctxt,
+ __entry->idx, show_usdma_complete_state(__entry->state),
+ __entry->code)
+);
+
+const char *print_u32_array(struct trace_seq *, u32 *, int);
+#define __print_u32_hex(arr, len) print_u32_array(p, arr, len)
+
+TRACE_EVENT(hfi1_sdma_user_header_ahg,
+ TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 req,
+ u8 sde, u8 ahgidx, u32 *ahg, int len, u32 tidval),
+ TP_ARGS(dd, ctxt, subctxt, req, sde, ahgidx, ahg, len, tidval),
+ TP_STRUCT__entry(
+ DD_DEV_ENTRY(dd)
+ __field(u16, ctxt)
+ __field(u8, subctxt)
+ __field(u16, req)
+ __field(u8, sde)
+ __field(u8, idx)
+ __field(int, len)
+ __field(u32, tidval)
+ __array(u32, ahg, 10)
+ ),
+ TP_fast_assign(
+ DD_DEV_ASSIGN(dd);
+ __entry->ctxt = ctxt;
+ __entry->subctxt = subctxt;
+ __entry->req = req;
+ __entry->sde = sde;
+ __entry->idx = ahgidx;
+ __entry->len = len;
+ __entry->tidval = tidval;
+ memcpy(__entry->ahg, ahg, len * sizeof(u32));
+ ),
+ TP_printk("[%s:%u:%u:%u] (SDE%u/AHG%u) ahg[0-%d]=(%s) TIDVal=0x%x",
+ __get_str(dev),
+ __entry->ctxt,
+ __entry->subctxt,
+ __entry->req,
+ __entry->sde,
+ __entry->idx,
+ __entry->len - 1,
+ __print_u32_hex(__entry->ahg, __entry->len),
+ __entry->tidval
+ )
+);
+
+TRACE_EVENT(hfi1_sdma_state,
+ TP_PROTO(struct sdma_engine *sde,
+ const char *cstate,
+ const char *nstate
+ ),
+ TP_ARGS(sde, cstate, nstate),
+ TP_STRUCT__entry(DD_DEV_ENTRY(sde->dd)
+ __string(curstate, cstate)
+ __string(newstate, nstate)
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(sde->dd);
+ __assign_str(curstate, cstate);
+ __assign_str(newstate, nstate);
+ ),
+ TP_printk("[%s] current state %s new state %s",
+ __get_str(dev),
+ __get_str(curstate),
+ __get_str(newstate)
+ )
+);
+
+#define BCT_FORMAT \
+ "shared_limit %x vls 0-7 [%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x][%x,%x] 15 [%x,%x]"
+
+#define BCT(field) \
+ be16_to_cpu( \
+ ((struct buffer_control *)__get_dynamic_array(bct))->field \
+ )
+
+DECLARE_EVENT_CLASS(hfi1_bct_template,
+ TP_PROTO(struct hfi1_devdata *dd,
+ struct buffer_control *bc),
+ TP_ARGS(dd, bc),
+ TP_STRUCT__entry(DD_DEV_ENTRY(dd)
+ __dynamic_array(u8, bct, sizeof(*bc))
+ ),
+ TP_fast_assign(DD_DEV_ASSIGN(dd);
+ memcpy(__get_dynamic_array(bct), bc,
+ sizeof(*bc));
+ ),
+ TP_printk(BCT_FORMAT,
+ BCT(overall_shared_limit),
+
+ BCT(vl[0].dedicated),
+ BCT(vl[0].shared),
+
+ BCT(vl[1].dedicated),
+ BCT(vl[1].shared),
+
+ BCT(vl[2].dedicated),
+ BCT(vl[2].shared),
+
+ BCT(vl[3].dedicated),
+ BCT(vl[3].shared),
+
+ BCT(vl[4].dedicated),
+ BCT(vl[4].shared),
+
+ BCT(vl[5].dedicated),
+ BCT(vl[5].shared),
+
+ BCT(vl[6].dedicated),
+ BCT(vl[6].shared),
+
+ BCT(vl[7].dedicated),
+ BCT(vl[7].shared),
+
+ BCT(vl[15].dedicated),
+ BCT(vl[15].shared)
+ )
+);
+
+DEFINE_EVENT(hfi1_bct_template, bct_set,
+ TP_PROTO(struct hfi1_devdata *dd, struct buffer_control *bc),
+ TP_ARGS(dd, bc));
+
+DEFINE_EVENT(hfi1_bct_template, bct_get,
+ TP_PROTO(struct hfi1_devdata *dd, struct buffer_control *bc),
+ TP_ARGS(dd, bc));
+
+#endif /* __HFI1_TRACE_TX_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_tx
+#include <trace/define_trace.h>
diff --git a/drivers/infiniband/hw/hfi1/twsi.c b/drivers/infiniband/hw/hfi1/twsi.c
deleted file mode 100644
index e82e52a63d35..000000000000
--- a/drivers/infiniband/hw/hfi1/twsi.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License 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.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of Intel Corporation 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 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.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-
-#include "hfi.h"
-#include "twsi.h"
-
-/*
- * "Two Wire Serial Interface" support.
- *
- * Originally written for a not-quite-i2c serial eeprom, which is
- * still used on some supported boards. Later boards have added a
- * variety of other uses, most board-specific, so the bit-boffing
- * part has been split off to this file, while the other parts
- * have been moved to chip-specific files.
- *
- * We have also dropped all pretense of fully generic (e.g. pretend
- * we don't know whether '1' is the higher voltage) interface, as
- * the restrictions of the generic i2c interface (e.g. no access from
- * driver itself) make it unsuitable for this use.
- */
-
-#define READ_CMD 1
-#define WRITE_CMD 0
-
-/**
- * i2c_wait_for_writes - wait for a write
- * @dd: the hfi1_ib device
- *
- * We use this instead of udelay directly, so we can make sure
- * that previous register writes have been flushed all the way
- * to the chip. Since we are delaying anyway, the cost doesn't
- * hurt, and makes the bit twiddling more regular
- */
-static void i2c_wait_for_writes(struct hfi1_devdata *dd, u32 target)
-{
- /*
- * implicit read of EXTStatus is as good as explicit
- * read of scratch, if all we want to do is flush
- * writes.
- */
- hfi1_gpio_mod(dd, target, 0, 0, 0);
- rmb(); /* inlined, so prevent compiler reordering */
-}
-
-/*
- * QSFP modules are allowed to hold SCL low for 500uSec. Allow twice that
- * for "almost compliant" modules
- */
-#define SCL_WAIT_USEC 1000
-
-/* BUF_WAIT is time bus must be free between STOP or ACK and to next START.
- * Should be 20, but some chips need more.
- */
-#define TWSI_BUF_WAIT_USEC 60
-
-static void scl_out(struct hfi1_devdata *dd, u32 target, u8 bit)
-{
- u32 mask;
-
- udelay(1);
-
- mask = QSFP_HFI0_I2CCLK;
-
- /* SCL is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, bit ? 0 : mask, mask);
-
- /*
- * Allow for slow slaves by simple
- * delay for falling edge, sampling on rise.
- */
- if (!bit) {
- udelay(2);
- } else {
- int rise_usec;
-
- for (rise_usec = SCL_WAIT_USEC; rise_usec > 0; rise_usec -= 2) {
- if (mask & hfi1_gpio_mod(dd, target, 0, 0, 0))
- break;
- udelay(2);
- }
- if (rise_usec <= 0)
- dd_dev_err(dd, "SCL interface stuck low > %d uSec\n",
- SCL_WAIT_USEC);
- }
- i2c_wait_for_writes(dd, target);
-}
-
-static u8 scl_in(struct hfi1_devdata *dd, u32 target, int wait)
-{
- u32 read_val, mask;
-
- mask = QSFP_HFI0_I2CCLK;
- /* SCL is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
- read_val = hfi1_gpio_mod(dd, target, 0, 0, 0);
- if (wait)
- i2c_wait_for_writes(dd, target);
- return (read_val & mask) >> GPIO_SCL_NUM;
-}
-
-static void sda_out(struct hfi1_devdata *dd, u32 target, u8 bit)
-{
- u32 mask;
-
- mask = QSFP_HFI0_I2CDAT;
-
- /* SDA is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, bit ? 0 : mask, mask);
-
- i2c_wait_for_writes(dd, target);
- udelay(2);
-}
-
-static u8 sda_in(struct hfi1_devdata *dd, u32 target, int wait)
-{
- u32 read_val, mask;
-
- mask = QSFP_HFI0_I2CDAT;
- /* SDA is meant to be bare-drain, so never set "OUT", just DIR */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
- read_val = hfi1_gpio_mod(dd, target, 0, 0, 0);
- if (wait)
- i2c_wait_for_writes(dd, target);
- return (read_val & mask) >> GPIO_SDA_NUM;
-}
-
-/**
- * i2c_ackrcv - see if ack following write is true
- * @dd: the hfi1_ib device
- */
-static int i2c_ackrcv(struct hfi1_devdata *dd, u32 target)
-{
- u8 ack_received;
-
- /* AT ENTRY SCL = LOW */
- /* change direction, ignore data */
- ack_received = sda_in(dd, target, 1);
- scl_out(dd, target, 1);
- ack_received = sda_in(dd, target, 1) == 0;
- scl_out(dd, target, 0);
- return ack_received;
-}
-
-static void stop_cmd(struct hfi1_devdata *dd, u32 target);
-
-/**
- * rd_byte - read a byte, sending STOP on last, else ACK
- * @dd: the hfi1_ib device
- *
- * Returns byte shifted out of device
- */
-static int rd_byte(struct hfi1_devdata *dd, u32 target, int last)
-{
- int bit_cntr, data;
-
- data = 0;
-
- for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) {
- data <<= 1;
- scl_out(dd, target, 1);
- data |= sda_in(dd, target, 0);
- scl_out(dd, target, 0);
- }
- if (last) {
- scl_out(dd, target, 1);
- stop_cmd(dd, target);
- } else {
- sda_out(dd, target, 0);
- scl_out(dd, target, 1);
- scl_out(dd, target, 0);
- sda_out(dd, target, 1);
- }
- return data;
-}
-
-/**
- * wr_byte - write a byte, one bit at a time
- * @dd: the hfi1_ib device
- * @data: the byte to write
- *
- * Returns 0 if we got the following ack, otherwise 1
- */
-static int wr_byte(struct hfi1_devdata *dd, u32 target, u8 data)
-{
- int bit_cntr;
- u8 bit;
-
- for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) {
- bit = (data >> bit_cntr) & 1;
- sda_out(dd, target, bit);
- scl_out(dd, target, 1);
- scl_out(dd, target, 0);
- }
- return (!i2c_ackrcv(dd, target)) ? 1 : 0;
-}
-
-/*
- * issue TWSI start sequence:
- * (both clock/data high, clock high, data low while clock is high)
- */
-static void start_seq(struct hfi1_devdata *dd, u32 target)
-{
- sda_out(dd, target, 1);
- scl_out(dd, target, 1);
- sda_out(dd, target, 0);
- udelay(1);
- scl_out(dd, target, 0);
-}
-
-/**
- * stop_seq - transmit the stop sequence
- * @dd: the hfi1_ib device
- *
- * (both clock/data low, clock high, data high while clock is high)
- */
-static void stop_seq(struct hfi1_devdata *dd, u32 target)
-{
- scl_out(dd, target, 0);
- sda_out(dd, target, 0);
- scl_out(dd, target, 1);
- sda_out(dd, target, 1);
-}
-
-/**
- * stop_cmd - transmit the stop condition
- * @dd: the hfi1_ib device
- *
- * (both clock/data low, clock high, data high while clock is high)
- */
-static void stop_cmd(struct hfi1_devdata *dd, u32 target)
-{
- stop_seq(dd, target);
- udelay(TWSI_BUF_WAIT_USEC);
-}
-
-/**
- * hfi1_twsi_reset - reset I2C communication
- * @dd: the hfi1_ib device
- * returns 0 if ok, -EIO on error
- */
-int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target)
-{
- int clock_cycles_left = 9;
- u32 mask;
-
- /* Both SCL and SDA should be high. If not, there
- * is something wrong.
- */
- mask = QSFP_HFI0_I2CCLK | QSFP_HFI0_I2CDAT;
-
- /*
- * Force pins to desired innocuous state.
- * This is the default power-on state with out=0 and dir=0,
- * So tri-stated and should be floating high (barring HW problems)
- */
- hfi1_gpio_mod(dd, target, 0, 0, mask);
-
- /* Check if SCL is low, if it is low then we have a slave device
- * misbehaving and there is not much we can do.
- */
- if (!scl_in(dd, target, 0))
- return -EIO;
-
- /* Check if SDA is low, if it is low then we have to clock SDA
- * up to 9 times for the device to release the bus
- */
- while (clock_cycles_left--) {
- if (sda_in(dd, target, 0))
- return 0;
- scl_out(dd, target, 0);
- scl_out(dd, target, 1);
- }
-
- return -EIO;
-}
-
-#define HFI1_TWSI_START 0x100
-#define HFI1_TWSI_STOP 0x200
-
-/* Write byte to TWSI, optionally prefixed with START or suffixed with
- * STOP.
- * returns 0 if OK (ACK received), else != 0
- */
-static int twsi_wr(struct hfi1_devdata *dd, u32 target, int data, int flags)
-{
- int ret = 1;
-
- if (flags & HFI1_TWSI_START)
- start_seq(dd, target);
-
- /* Leaves SCL low (from i2c_ackrcv()) */
- ret = wr_byte(dd, target, data);
-
- if (flags & HFI1_TWSI_STOP)
- stop_cmd(dd, target);
- return ret;
-}
-
-/* Added functionality for IBA7220-based cards */
-#define HFI1_TEMP_DEV 0x98
-
-/*
- * hfi1_twsi_blk_rd
- * General interface for data transfer from twsi devices.
- * One vestige of its former role is that it recognizes a device
- * HFI1_TWSI_NO_DEV and does the correct operation for the legacy part,
- * which responded to all TWSI device codes, interpreting them as
- * address within device. On all other devices found on board handled by
- * this driver, the device is followed by a N-byte "address" which selects
- * the "register" or "offset" within the device from which data should
- * be read.
- */
-int hfi1_twsi_blk_rd(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- void *buffer, int len)
-{
- u8 *bp = buffer;
- int ret = 1;
- int i;
- int offset_size;
-
- /* obtain the offset size, strip it from the device address */
- offset_size = (dev >> 8) & 0xff;
- dev &= 0xff;
-
- /* allow at most a 2 byte offset */
- if (offset_size > 2)
- goto bail;
-
- if (dev == HFI1_TWSI_NO_DEV) {
- /* legacy not-really-I2C */
- addr = (addr << 1) | READ_CMD;
- ret = twsi_wr(dd, target, addr, HFI1_TWSI_START);
- } else {
- /* Actual I2C */
- if (offset_size) {
- ret = twsi_wr(dd, target,
- dev | WRITE_CMD, HFI1_TWSI_START);
- if (ret) {
- stop_cmd(dd, target);
- goto bail;
- }
-
- for (i = 0; i < offset_size; i++) {
- ret = twsi_wr(dd, target,
- (addr >> (i * 8)) & 0xff, 0);
- udelay(TWSI_BUF_WAIT_USEC);
- if (ret) {
- dd_dev_err(dd, "Failed to write byte %d of offset 0x%04X\n",
- i, addr);
- goto bail;
- }
- }
- }
- ret = twsi_wr(dd, target, dev | READ_CMD, HFI1_TWSI_START);
- }
- if (ret) {
- stop_cmd(dd, target);
- goto bail;
- }
-
- /*
- * block devices keeps clocking data out as long as we ack,
- * automatically incrementing the address. Some have "pages"
- * whose boundaries will not be crossed, but the handling
- * of these is left to the caller, who is in a better
- * position to know.
- */
- while (len-- > 0) {
- /*
- * Get and store data, sending ACK if length remaining,
- * else STOP
- */
- *bp++ = rd_byte(dd, target, !len);
- }
-
- ret = 0;
-
-bail:
- return ret;
-}
-
-/*
- * hfi1_twsi_blk_wr
- * General interface for data transfer to twsi devices.
- * One vestige of its former role is that it recognizes a device
- * HFI1_TWSI_NO_DEV and does the correct operation for the legacy part,
- * which responded to all TWSI device codes, interpreting them as
- * address within device. On all other devices found on board handled by
- * this driver, the device is followed by a N-byte "address" which selects
- * the "register" or "offset" within the device to which data should
- * be written.
- */
-int hfi1_twsi_blk_wr(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- const void *buffer, int len)
-{
- const u8 *bp = buffer;
- int ret = 1;
- int i;
- int offset_size;
-
- /* obtain the offset size, strip it from the device address */
- offset_size = (dev >> 8) & 0xff;
- dev &= 0xff;
-
- /* allow at most a 2 byte offset */
- if (offset_size > 2)
- goto bail;
-
- if (dev == HFI1_TWSI_NO_DEV) {
- if (twsi_wr(dd, target, (addr << 1) | WRITE_CMD,
- HFI1_TWSI_START)) {
- goto failed_write;
- }
- } else {
- /* Real I2C */
- if (twsi_wr(dd, target, dev | WRITE_CMD, HFI1_TWSI_START))
- goto failed_write;
- }
-
- for (i = 0; i < offset_size; i++) {
- ret = twsi_wr(dd, target, (addr >> (i * 8)) & 0xff, 0);
- udelay(TWSI_BUF_WAIT_USEC);
- if (ret) {
- dd_dev_err(dd, "Failed to write byte %d of offset 0x%04X\n",
- i, addr);
- goto bail;
- }
- }
-
- for (i = 0; i < len; i++)
- if (twsi_wr(dd, target, *bp++, 0))
- goto failed_write;
-
- ret = 0;
-
-failed_write:
- stop_cmd(dd, target);
-
-bail:
- return ret;
-}
diff --git a/drivers/infiniband/hw/hfi1/twsi.h b/drivers/infiniband/hw/hfi1/twsi.h
deleted file mode 100644
index 5b8a5b5e7eae..000000000000
--- a/drivers/infiniband/hw/hfi1/twsi.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _TWSI_H
-#define _TWSI_H
-/*
- * Copyright(c) 2015, 2016 Intel Corporation.
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License 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.
- *
- * BSD LICENSE
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - 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.
- * - Neither the name of Intel Corporation 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 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.
- *
- */
-
-#define HFI1_TWSI_NO_DEV 0xFF
-
-struct hfi1_devdata;
-
-/* Bit position of SDA/SCL pins in ASIC_QSFP* registers */
-#define GPIO_SDA_NUM 1
-#define GPIO_SCL_NUM 0
-
-/* these functions must be called with qsfp_lock held */
-int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target);
-int hfi1_twsi_blk_rd(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- void *buffer, int len);
-int hfi1_twsi_blk_wr(struct hfi1_devdata *dd, u32 target, int dev, int addr,
- const void *buffer, int len);
-
-#endif /* _TWSI_H */
diff --git a/drivers/infiniband/hw/hfi1/uc.c b/drivers/infiniband/hw/hfi1/uc.c
index df773d433297..a726d96d185f 100644
--- a/drivers/infiniband/hw/hfi1/uc.c
+++ b/drivers/infiniband/hw/hfi1/uc.c
@@ -119,6 +119,31 @@ int hfi1_make_uc_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
goto bail;
}
/*
+ * Local operations are processed immediately
+ * after all prior requests have completed.
+ */
+ if (wqe->wr.opcode == IB_WR_REG_MR ||
+ wqe->wr.opcode == IB_WR_LOCAL_INV) {
+ int local_ops = 0;
+ int err = 0;
+
+ if (qp->s_last != qp->s_cur)
+ goto bail;
+ if (++qp->s_cur == qp->s_size)
+ qp->s_cur = 0;
+ if (!(wqe->wr.send_flags & RVT_SEND_COMPLETION_ONLY)) {
+ err = rvt_invalidate_rkey(
+ qp, wqe->wr.ex.invalidate_rkey);
+ local_ops = 1;
+ }
+ hfi1_send_complete(qp, wqe, err ? IB_WC_LOC_PROT_ERR
+ : IB_WC_SUCCESS);
+ if (local_ops)
+ atomic_dec(&qp->local_ops_pending);
+ qp->s_hdrwords = 0;
+ goto done_free_tx;
+ }
+ /*
* Start a new request.
*/
qp->s_psn = wqe->psn;
@@ -294,46 +319,12 @@ void hfi1_uc_rcv(struct hfi1_packet *packet)
struct ib_reth *reth;
int has_grh = rcv_flags & HFI1_HAS_GRH;
int ret;
- u32 bth1;
bth0 = be32_to_cpu(ohdr->bth[0]);
if (hfi1_ruc_check_hdr(ibp, hdr, has_grh, qp, bth0))
return;
- bth1 = be32_to_cpu(ohdr->bth[1]);
- if (unlikely(bth1 & (HFI1_BECN_SMASK | HFI1_FECN_SMASK))) {
- if (bth1 & HFI1_BECN_SMASK) {
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
- u32 rqpn, lqpn;
- u16 rlid = be16_to_cpu(hdr->lrh[3]);
- u8 sl, sc5;
-
- lqpn = bth1 & RVT_QPN_MASK;
- rqpn = qp->remote_qpn;
-
- sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl];
- sl = ibp->sc_to_sl[sc5];
-
- process_becn(ppd, sl, rlid, lqpn, rqpn,
- IB_CC_SVCTYPE_UC);
- }
-
- if (bth1 & HFI1_FECN_SMASK) {
- struct ib_grh *grh = NULL;
- u16 pkey = (u16)be32_to_cpu(ohdr->bth[0]);
- u16 slid = be16_to_cpu(hdr->lrh[3]);
- u16 dlid = be16_to_cpu(hdr->lrh[1]);
- u32 src_qp = qp->remote_qpn;
- u8 sc5;
-
- sc5 = ibp->sl_to_sc[qp->remote_ah_attr.sl];
- if (has_grh)
- grh = &hdr->u.l.grh;
-
- return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5,
- grh);
- }
- }
+ process_ecn(qp, packet, true);
psn = be32_to_cpu(ohdr->bth[2]);
opcode = (bth0 >> 24) & 0xff;
diff --git a/drivers/infiniband/hw/hfi1/ud.c b/drivers/infiniband/hw/hfi1/ud.c
index be91f6fa1c87..f01e8e1d62d3 100644
--- a/drivers/infiniband/hw/hfi1/ud.c
+++ b/drivers/infiniband/hw/hfi1/ud.c
@@ -184,8 +184,12 @@ static void ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe)
}
if (ah_attr->ah_flags & IB_AH_GRH) {
- hfi1_copy_sge(&qp->r_sge, &ah_attr->grh,
- sizeof(struct ib_grh), 1, 0);
+ struct ib_grh grh;
+ struct ib_global_route grd = ah_attr->grh;
+
+ hfi1_make_grh(ibp, &grh, &grd, 0, 0);
+ hfi1_copy_sge(&qp->r_sge, &grh,
+ sizeof(grh), 1, 0);
wc.wc_flags |= IB_WC_GRH;
} else {
hfi1_skip_sge(&qp->r_sge, sizeof(struct ib_grh), 1);
@@ -430,10 +434,9 @@ int hfi1_make_ud_req(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
qp->qkey : wqe->ud_wr.remote_qkey);
ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num);
/* disarm any ahg */
- priv->s_hdr->ahgcount = 0;
- priv->s_hdr->ahgidx = 0;
- priv->s_hdr->tx_flags = 0;
- priv->s_hdr->sde = NULL;
+ priv->s_ahg->ahgcount = 0;
+ priv->s_ahg->ahgidx = 0;
+ priv->s_ahg->tx_flags = 0;
/* pbc */
ps->s_txreq->hdr_dwords = qp->s_hdrwords + 2;
@@ -665,13 +668,13 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
struct hfi1_other_headers *ohdr = packet->ohdr;
int opcode;
u32 hdrsize = packet->hlen;
- u32 pad;
struct ib_wc wc;
u32 qkey;
u32 src_qp;
u16 dlid, pkey;
int mgmt_pkey_idx = -1;
struct hfi1_ibport *ibp = &packet->rcd->ppd->ibport_data;
+ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
struct hfi1_ib_header *hdr = packet->hdr;
u32 rcv_flags = packet->rcv_flags;
void *data = packet->ebuf;
@@ -680,52 +683,33 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
bool has_grh = rcv_flags & HFI1_HAS_GRH;
u8 sc5 = hdr2sc((struct hfi1_message_header *)hdr, packet->rhf);
u32 bth1;
- int is_mcast;
- struct ib_grh *grh = NULL;
+ u8 sl_from_sc, sl;
+ u16 slid;
+ u8 extra_bytes;
qkey = be32_to_cpu(ohdr->u.ud.deth[0]);
src_qp = be32_to_cpu(ohdr->u.ud.deth[1]) & RVT_QPN_MASK;
dlid = be16_to_cpu(hdr->lrh[1]);
- is_mcast = (dlid > be16_to_cpu(IB_MULTICAST_LID_BASE)) &&
- (dlid != be16_to_cpu(IB_LID_PERMISSIVE));
bth1 = be32_to_cpu(ohdr->bth[1]);
- if (unlikely(bth1 & HFI1_BECN_SMASK)) {
- /*
- * In pre-B0 h/w the CNP_OPCODE is handled via an
- * error path.
- */
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
- u32 lqpn = be32_to_cpu(ohdr->bth[1]) & RVT_QPN_MASK;
- u8 sl;
-
- sl = ibp->sc_to_sl[sc5];
-
- process_becn(ppd, sl, 0, lqpn, 0, IB_CC_SVCTYPE_UD);
- }
+ slid = be16_to_cpu(hdr->lrh[3]);
+ pkey = (u16)be32_to_cpu(ohdr->bth[0]);
+ sl = (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xf;
+ extra_bytes = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
+ extra_bytes += (SIZE_OF_CRC << 2);
+ sl_from_sc = ibp->sc_to_sl[sc5];
- /*
- * The opcode is in the low byte when its in network order
- * (top byte when in host order).
- */
opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
opcode &= 0xff;
- pkey = (u16)be32_to_cpu(ohdr->bth[0]);
-
- if (!is_mcast && (opcode != IB_OPCODE_CNP) && bth1 & HFI1_FECN_SMASK) {
- u16 slid = be16_to_cpu(hdr->lrh[3]);
-
- return_cnp(ibp, qp, src_qp, pkey, dlid, slid, sc5, grh);
- }
+ process_ecn(qp, packet, (opcode != IB_OPCODE_CNP));
/*
* Get the number of bytes the message was padded by
* and drop incomplete packets.
*/
- pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;
- if (unlikely(tlen < (hdrsize + pad + 4)))
+ if (unlikely(tlen < (hdrsize + extra_bytes)))
goto drop;
- tlen -= hdrsize + pad + 4;
+ tlen -= hdrsize + extra_bytes;
/*
* Check that the permissive LID is only used on QP0
@@ -736,10 +720,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
hdr->lrh[3] == IB_LID_PERMISSIVE))
goto drop;
if (qp->ibqp.qp_num > 1) {
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
- u16 slid;
-
- slid = be16_to_cpu(hdr->lrh[3]);
if (unlikely(rcv_pkey_check(ppd, pkey, sc5, slid))) {
/*
* Traps will not be sent for packets dropped
@@ -748,12 +728,9 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
* IB spec (release 1.3, section 10.9.4)
*/
hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_P_KEY,
- pkey,
- (be16_to_cpu(hdr->lrh[0]) >> 4) &
- 0xF,
+ pkey, sl,
src_qp, qp->ibqp.qp_num,
- be16_to_cpu(hdr->lrh[3]),
- be16_to_cpu(hdr->lrh[1]));
+ slid, dlid);
return;
}
} else {
@@ -763,22 +740,18 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
goto drop;
}
if (unlikely(qkey != qp->qkey)) {
- hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_Q_KEY, qkey,
- (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF,
+ hfi1_bad_pqkey(ibp, OPA_TRAP_BAD_Q_KEY, qkey, sl,
src_qp, qp->ibqp.qp_num,
- be16_to_cpu(hdr->lrh[3]),
- be16_to_cpu(hdr->lrh[1]));
+ slid, dlid);
return;
}
/* Drop invalid MAD packets (see 13.5.3.1). */
if (unlikely(qp->ibqp.qp_num == 1 &&
- (tlen > 2048 ||
- (be16_to_cpu(hdr->lrh[0]) >> 12) == 15)))
+ (tlen > 2048 || (sc5 == 0xF))))
goto drop;
} else {
/* Received on QP0, and so by definition, this is an SMP */
struct opa_smp *smp = (struct opa_smp *)data;
- u16 slid = be16_to_cpu(hdr->lrh[3]);
if (opa_smp_check(ibp, pkey, sc5, qp, slid, smp))
goto drop;
@@ -861,7 +834,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
qp->ibqp.qp_type == IB_QPT_SMI) {
if (mgmt_pkey_idx < 0) {
if (net_ratelimit()) {
- struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
struct hfi1_devdata *dd = ppd->dd;
dd_dev_err(dd, "QP type %d mgmt_pkey_idx < 0 and packet not dropped???\n",
@@ -874,8 +846,8 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
wc.pkey_index = 0;
}
- wc.slid = be16_to_cpu(hdr->lrh[3]);
- wc.sl = ibp->sc_to_sl[sc5];
+ wc.slid = slid;
+ wc.sl = sl_from_sc;
/*
* Save the LMC lower bits if the destination LID is a unicast LID.
diff --git a/drivers/infiniband/hw/hfi1/user_exp_rcv.c b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
index 1b640a35b3fe..64d26525435a 100644
--- a/drivers/infiniband/hw/hfi1/user_exp_rcv.c
+++ b/drivers/infiniband/hw/hfi1/user_exp_rcv.c
@@ -82,24 +82,25 @@ struct tid_pageset {
((unsigned long)vaddr & PAGE_MASK)) >> PAGE_SHIFT))
static void unlock_exp_tids(struct hfi1_ctxtdata *, struct exp_tid_set *,
- struct rb_root *);
+ struct hfi1_filedata *);
static u32 find_phys_blocks(struct page **, unsigned, struct tid_pageset *);
static int set_rcvarray_entry(struct file *, unsigned long, u32,
struct tid_group *, struct page **, unsigned);
-static int mmu_rb_insert(struct rb_root *, struct mmu_rb_node *);
-static void mmu_rb_remove(struct rb_root *, struct mmu_rb_node *,
- struct mm_struct *);
-static int mmu_rb_invalidate(struct rb_root *, struct mmu_rb_node *);
+static int tid_rb_insert(void *, struct mmu_rb_node *);
+static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
+ struct tid_rb_node *tnode);
+static void tid_rb_remove(void *, struct mmu_rb_node *);
+static int tid_rb_invalidate(void *, struct mmu_rb_node *);
static int program_rcvarray(struct file *, unsigned long, struct tid_group *,
struct tid_pageset *, unsigned, u16, struct page **,
u32 *, unsigned *, unsigned *);
static int unprogram_rcvarray(struct file *, u32, struct tid_group **);
-static void clear_tid_node(struct hfi1_filedata *, u16, struct tid_rb_node *);
+static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node);
static struct mmu_rb_ops tid_rb_ops = {
- .insert = mmu_rb_insert,
- .remove = mmu_rb_remove,
- .invalidate = mmu_rb_invalidate
+ .insert = tid_rb_insert,
+ .remove = tid_rb_remove,
+ .invalidate = tid_rb_invalidate
};
static inline u32 rcventry2tidinfo(u32 rcventry)
@@ -162,7 +163,6 @@ int hfi1_user_exp_rcv_init(struct file *fp)
spin_lock_init(&fd->tid_lock);
spin_lock_init(&fd->invalid_lock);
- fd->tid_rb_root = RB_ROOT;
if (!uctxt->subctxt_cnt || !fd->subctxt) {
exp_tid_group_init(&uctxt->tid_group_list);
@@ -197,7 +197,7 @@ int hfi1_user_exp_rcv_init(struct file *fp)
if (!fd->entry_to_rb)
return -ENOMEM;
- if (!HFI1_CAP_IS_USET(TID_UNMAP)) {
+ if (!HFI1_CAP_UGET_MASK(uctxt->flags, TID_UNMAP)) {
fd->invalid_tid_idx = 0;
fd->invalid_tids = kzalloc(uctxt->expected_count *
sizeof(u32), GFP_KERNEL);
@@ -208,15 +208,15 @@ int hfi1_user_exp_rcv_init(struct file *fp)
/*
* Register MMU notifier callbacks. If the registration
- * fails, continue but turn off the TID caching for
- * all user contexts.
+ * fails, continue without TID caching for this context.
*/
- ret = hfi1_mmu_rb_register(&fd->tid_rb_root, &tid_rb_ops);
+ ret = hfi1_mmu_rb_register(fd, fd->mm, &tid_rb_ops,
+ dd->pport->hfi1_wq,
+ &fd->handler);
if (ret) {
dd_dev_info(dd,
"Failed MMU notifier registration %d\n",
ret);
- HFI1_CAP_USET(TID_UNMAP);
ret = 0;
}
}
@@ -235,7 +235,7 @@ int hfi1_user_exp_rcv_init(struct file *fp)
* init.
*/
spin_lock(&fd->tid_lock);
- if (uctxt->subctxt_cnt && !HFI1_CAP_IS_USET(TID_UNMAP)) {
+ if (uctxt->subctxt_cnt && fd->handler) {
u16 remainder;
fd->tid_limit = uctxt->expected_count / uctxt->subctxt_cnt;
@@ -261,18 +261,16 @@ int hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
* The notifier would have been removed when the process'es mm
* was freed.
*/
- if (!HFI1_CAP_IS_USET(TID_UNMAP))
- hfi1_mmu_rb_unregister(&fd->tid_rb_root);
+ if (fd->handler)
+ hfi1_mmu_rb_unregister(fd->handler);
kfree(fd->invalid_tids);
if (!uctxt->cnt) {
if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
- unlock_exp_tids(uctxt, &uctxt->tid_full_list,
- &fd->tid_rb_root);
+ unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
- unlock_exp_tids(uctxt, &uctxt->tid_used_list,
- &fd->tid_rb_root);
+ unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
list) {
list_del_init(&grp->list);
@@ -399,12 +397,12 @@ int hfi1_user_exp_rcv_setup(struct file *fp, struct hfi1_tid_info *tinfo)
* pages, accept the amount pinned so far and program only that.
* User space knows how to deal with partially programmed buffers.
*/
- if (!hfi1_can_pin_pages(dd, fd->tid_n_pinned, npages)) {
+ if (!hfi1_can_pin_pages(dd, fd->mm, fd->tid_n_pinned, npages)) {
ret = -ENOMEM;
goto bail;
}
- pinned = hfi1_acquire_user_pages(vaddr, npages, true, pages);
+ pinned = hfi1_acquire_user_pages(fd->mm, vaddr, npages, true, pages);
if (pinned <= 0) {
ret = pinned;
goto bail;
@@ -559,7 +557,7 @@ nomem:
* for example), unpin all unmapped pages so we can pin them nex time.
*/
if (mapped_pages != pinned) {
- hfi1_release_user_pages(current->mm, &pages[mapped_pages],
+ hfi1_release_user_pages(fd->mm, &pages[mapped_pages],
pinned - mapped_pages,
false);
fd->tid_n_pinned -= pinned - mapped_pages;
@@ -829,7 +827,6 @@ static int set_rcvarray_entry(struct file *fp, unsigned long vaddr,
struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct tid_rb_node *node;
struct hfi1_devdata *dd = uctxt->dd;
- struct rb_root *root = &fd->tid_rb_root;
dma_addr_t phys;
/*
@@ -861,10 +858,10 @@ static int set_rcvarray_entry(struct file *fp, unsigned long vaddr,
node->freed = false;
memcpy(node->pages, pages, sizeof(struct page *) * npages);
- if (HFI1_CAP_IS_USET(TID_UNMAP))
- ret = mmu_rb_insert(root, &node->mmu);
+ if (!fd->handler)
+ ret = tid_rb_insert(fd, &node->mmu);
else
- ret = hfi1_mmu_rb_insert(root, &node->mmu);
+ ret = hfi1_mmu_rb_insert(fd->handler, &node->mmu);
if (ret) {
hfi1_cdbg(TID, "Failed to insert RB node %u 0x%lx, 0x%lx %d",
@@ -904,19 +901,19 @@ static int unprogram_rcvarray(struct file *fp, u32 tidinfo,
node = fd->entry_to_rb[rcventry];
if (!node || node->rcventry != (uctxt->expected_base + rcventry))
return -EBADF;
- if (HFI1_CAP_IS_USET(TID_UNMAP))
- mmu_rb_remove(&fd->tid_rb_root, &node->mmu, NULL);
- else
- hfi1_mmu_rb_remove(&fd->tid_rb_root, &node->mmu);
if (grp)
*grp = node->grp;
- clear_tid_node(fd, fd->subctxt, node);
+
+ if (!fd->handler)
+ cacheless_tid_rb_remove(fd, node);
+ else
+ hfi1_mmu_rb_remove(fd->handler, &node->mmu);
+
return 0;
}
-static void clear_tid_node(struct hfi1_filedata *fd, u16 subctxt,
- struct tid_rb_node *node)
+static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node)
{
struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_devdata *dd = uctxt->dd;
@@ -934,7 +931,7 @@ static void clear_tid_node(struct hfi1_filedata *fd, u16 subctxt,
pci_unmap_single(dd->pcidev, node->dma_addr, node->mmu.len,
PCI_DMA_FROMDEVICE);
- hfi1_release_user_pages(current->mm, node->pages, node->npages, true);
+ hfi1_release_user_pages(fd->mm, node->pages, node->npages, true);
fd->tid_n_pinned -= node->npages;
node->grp->used--;
@@ -949,12 +946,15 @@ static void clear_tid_node(struct hfi1_filedata *fd, u16 subctxt,
kfree(node);
}
+/*
+ * As a simple helper for hfi1_user_exp_rcv_free, this function deals with
+ * clearing nodes in the non-cached case.
+ */
static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt,
- struct exp_tid_set *set, struct rb_root *root)
+ struct exp_tid_set *set,
+ struct hfi1_filedata *fd)
{
struct tid_group *grp, *ptr;
- struct hfi1_filedata *fd = container_of(root, struct hfi1_filedata,
- tid_rb_root);
int i;
list_for_each_entry_safe(grp, ptr, &set->list, list) {
@@ -969,22 +969,23 @@ static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt,
uctxt->expected_base];
if (!node || node->rcventry != rcventry)
continue;
- if (HFI1_CAP_IS_USET(TID_UNMAP))
- mmu_rb_remove(&fd->tid_rb_root,
- &node->mmu, NULL);
- else
- hfi1_mmu_rb_remove(&fd->tid_rb_root,
- &node->mmu);
- clear_tid_node(fd, -1, node);
+
+ cacheless_tid_rb_remove(fd, node);
}
}
}
}
-static int mmu_rb_invalidate(struct rb_root *root, struct mmu_rb_node *mnode)
+/*
+ * Always return 0 from this function. A non-zero return indicates that the
+ * remove operation will be called and that memory should be unpinned.
+ * However, the driver cannot unpin out from under PSM. Instead, retain the
+ * memory (by returning 0) and inform PSM that the memory is going away. PSM
+ * will call back later when it has removed the memory from its list.
+ */
+static int tid_rb_invalidate(void *arg, struct mmu_rb_node *mnode)
{
- struct hfi1_filedata *fdata =
- container_of(root, struct hfi1_filedata, tid_rb_root);
+ struct hfi1_filedata *fdata = arg;
struct hfi1_ctxtdata *uctxt = fdata->uctxt;
struct tid_rb_node *node =
container_of(mnode, struct tid_rb_node, mmu);
@@ -1025,10 +1026,9 @@ static int mmu_rb_invalidate(struct rb_root *root, struct mmu_rb_node *mnode)
return 0;
}
-static int mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *node)
+static int tid_rb_insert(void *arg, struct mmu_rb_node *node)
{
- struct hfi1_filedata *fdata =
- container_of(root, struct hfi1_filedata, tid_rb_root);
+ struct hfi1_filedata *fdata = arg;
struct tid_rb_node *tnode =
container_of(node, struct tid_rb_node, mmu);
u32 base = fdata->uctxt->expected_base;
@@ -1037,14 +1037,20 @@ static int mmu_rb_insert(struct rb_root *root, struct mmu_rb_node *node)
return 0;
}
-static void mmu_rb_remove(struct rb_root *root, struct mmu_rb_node *node,
- struct mm_struct *mm)
+static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
+ struct tid_rb_node *tnode)
{
- struct hfi1_filedata *fdata =
- container_of(root, struct hfi1_filedata, tid_rb_root);
- struct tid_rb_node *tnode =
- container_of(node, struct tid_rb_node, mmu);
u32 base = fdata->uctxt->expected_base;
fdata->entry_to_rb[tnode->rcventry - base] = NULL;
+ clear_tid_node(fdata, tnode);
+}
+
+static void tid_rb_remove(void *arg, struct mmu_rb_node *node)
+{
+ struct hfi1_filedata *fdata = arg;
+ struct tid_rb_node *tnode =
+ container_of(node, struct tid_rb_node, mmu);
+
+ cacheless_tid_rb_remove(fdata, tnode);
}
diff --git a/drivers/infiniband/hw/hfi1/user_pages.c b/drivers/infiniband/hw/hfi1/user_pages.c
index 88e10b5f55f1..20f4ddcac3b0 100644
--- a/drivers/infiniband/hw/hfi1/user_pages.c
+++ b/drivers/infiniband/hw/hfi1/user_pages.c
@@ -68,7 +68,8 @@ MODULE_PARM_DESC(cache_size, "Send and receive side cache size limit (in MB)");
* could keeping caching buffers.
*
*/
-bool hfi1_can_pin_pages(struct hfi1_devdata *dd, u32 nlocked, u32 npages)
+bool hfi1_can_pin_pages(struct hfi1_devdata *dd, struct mm_struct *mm,
+ u32 nlocked, u32 npages)
{
unsigned long ulimit = rlimit(RLIMIT_MEMLOCK), pinned, cache_limit,
size = (cache_size * (1UL << 20)); /* convert to bytes */
@@ -89,9 +90,9 @@ bool hfi1_can_pin_pages(struct hfi1_devdata *dd, u32 nlocked, u32 npages)
/* Convert to number of pages */
size = DIV_ROUND_UP(size, PAGE_SIZE);
- down_read(&current->mm->mmap_sem);
- pinned = current->mm->pinned_vm;
- up_read(&current->mm->mmap_sem);
+ down_read(&mm->mmap_sem);
+ pinned = mm->pinned_vm;
+ up_read(&mm->mmap_sem);
/* First, check the absolute limit against all pinned pages. */
if (pinned + npages >= ulimit && !can_lock)
@@ -100,8 +101,8 @@ bool hfi1_can_pin_pages(struct hfi1_devdata *dd, u32 nlocked, u32 npages)
return ((nlocked + npages) <= size) || can_lock;
}
-int hfi1_acquire_user_pages(unsigned long vaddr, size_t npages, bool writable,
- struct page **pages)
+int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t npages,
+ bool writable, struct page **pages)
{
int ret;
@@ -109,9 +110,9 @@ int hfi1_acquire_user_pages(unsigned long vaddr, size_t npages, bool writable,
if (ret < 0)
return ret;
- down_write(&current->mm->mmap_sem);
- current->mm->pinned_vm += ret;
- up_write(&current->mm->mmap_sem);
+ down_write(&mm->mmap_sem);
+ mm->pinned_vm += ret;
+ up_write(&mm->mmap_sem);
return ret;
}
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index 47ffd273ecbd..0ecf27903dc2 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -145,7 +145,7 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
/* Last packet in the request */
#define TXREQ_FLAGS_REQ_LAST_PKT BIT(0)
-#define SDMA_REQ_IN_USE 0
+/* SDMA request flag bits */
#define SDMA_REQ_FOR_THREAD 1
#define SDMA_REQ_SEND_DONE 2
#define SDMA_REQ_HAVE_AHG 3
@@ -183,16 +183,18 @@ struct user_sdma_iovec {
struct sdma_mmu_node *node;
};
-#define SDMA_CACHE_NODE_EVICT 0
-
struct sdma_mmu_node {
struct mmu_rb_node rb;
- struct list_head list;
struct hfi1_user_sdma_pkt_q *pq;
atomic_t refcount;
struct page **pages;
unsigned npages;
- unsigned long flags;
+};
+
+/* evict operation argument */
+struct evict_data {
+ u32 cleared; /* count evicted so far */
+ u32 target; /* target count to evict */
};
struct user_sdma_request {
@@ -305,14 +307,16 @@ static int defer_packet_queue(
unsigned seq);
static void activate_packet_queue(struct iowait *, int);
static bool sdma_rb_filter(struct mmu_rb_node *, unsigned long, unsigned long);
-static int sdma_rb_insert(struct rb_root *, struct mmu_rb_node *);
-static void sdma_rb_remove(struct rb_root *, struct mmu_rb_node *,
- struct mm_struct *);
-static int sdma_rb_invalidate(struct rb_root *, struct mmu_rb_node *);
+static int sdma_rb_insert(void *, struct mmu_rb_node *);
+static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
+ void *arg2, bool *stop);
+static void sdma_rb_remove(void *, struct mmu_rb_node *);
+static int sdma_rb_invalidate(void *, struct mmu_rb_node *);
static struct mmu_rb_ops sdma_rb_ops = {
.filter = sdma_rb_filter,
.insert = sdma_rb_insert,
+ .evict = sdma_rb_evict,
.remove = sdma_rb_remove,
.invalidate = sdma_rb_invalidate
};
@@ -397,6 +401,11 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
if (!pq->reqs)
goto pq_reqs_nomem;
+ memsize = BITS_TO_LONGS(hfi1_sdma_comp_ring_size) * sizeof(long);
+ pq->req_in_use = kzalloc(memsize, GFP_KERNEL);
+ if (!pq->req_in_use)
+ goto pq_reqs_no_in_use;
+
INIT_LIST_HEAD(&pq->list);
pq->dd = dd;
pq->ctxt = uctxt->ctxt;
@@ -405,9 +414,8 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
pq->state = SDMA_PKT_Q_INACTIVE;
atomic_set(&pq->n_reqs, 0);
init_waitqueue_head(&pq->wait);
- pq->sdma_rb_root = RB_ROOT;
- INIT_LIST_HEAD(&pq->evict);
- spin_lock_init(&pq->evict_lock);
+ atomic_set(&pq->n_locked, 0);
+ pq->mm = fd->mm;
iowait_init(&pq->busy, 0, NULL, defer_packet_queue,
activate_packet_queue, NULL);
@@ -437,7 +445,8 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
cq->nentries = hfi1_sdma_comp_ring_size;
fd->cq = cq;
- ret = hfi1_mmu_rb_register(&pq->sdma_rb_root, &sdma_rb_ops);
+ ret = hfi1_mmu_rb_register(pq, pq->mm, &sdma_rb_ops, dd->pport->hfi1_wq,
+ &pq->handler);
if (ret) {
dd_dev_err(dd, "Failed to register with MMU %d", ret);
goto done;
@@ -453,6 +462,8 @@ cq_comps_nomem:
cq_nomem:
kmem_cache_destroy(pq->txreq_cache);
pq_txreq_nomem:
+ kfree(pq->req_in_use);
+pq_reqs_no_in_use:
kfree(pq->reqs);
pq_reqs_nomem:
kfree(pq);
@@ -472,8 +483,9 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd)
hfi1_cdbg(SDMA, "[%u:%u:%u] Freeing user SDMA queues", uctxt->dd->unit,
uctxt->ctxt, fd->subctxt);
pq = fd->pq;
- hfi1_mmu_rb_unregister(&pq->sdma_rb_root);
if (pq) {
+ if (pq->handler)
+ hfi1_mmu_rb_unregister(pq->handler);
spin_lock_irqsave(&uctxt->sdma_qlock, flags);
if (!list_empty(&pq->list))
list_del_init(&pq->list);
@@ -484,6 +496,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd)
pq->wait,
(ACCESS_ONCE(pq->state) == SDMA_PKT_Q_INACTIVE));
kfree(pq->reqs);
+ kfree(pq->req_in_use);
kmem_cache_destroy(pq->txreq_cache);
kfree(pq);
fd->pq = NULL;
@@ -496,10 +509,31 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd)
return 0;
}
+static u8 dlid_to_selector(u16 dlid)
+{
+ static u8 mapping[256];
+ static int initialized;
+ static u8 next;
+ int hash;
+
+ if (!initialized) {
+ memset(mapping, 0xFF, 256);
+ initialized = 1;
+ }
+
+ hash = ((dlid >> 8) ^ dlid) & 0xFF;
+ if (mapping[hash] == 0xFF) {
+ mapping[hash] = next;
+ next = (next + 1) & 0x7F;
+ }
+
+ return mapping[hash];
+}
+
int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
unsigned long dim, unsigned long *count)
{
- int ret = 0, i = 0;
+ int ret = 0, i;
struct hfi1_filedata *fd = fp->private_data;
struct hfi1_ctxtdata *uctxt = fd->uctxt;
struct hfi1_user_sdma_pkt_q *pq = fd->pq;
@@ -511,6 +545,8 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
struct user_sdma_request *req;
u8 opcode, sc, vl;
int req_queued = 0;
+ u16 dlid;
+ u8 selector;
if (iovec[idx].iov_len < sizeof(info) + sizeof(req->hdr)) {
hfi1_cdbg(
@@ -529,30 +565,48 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
trace_hfi1_sdma_user_reqinfo(dd, uctxt->ctxt, fd->subctxt,
(u16 *)&info);
- if (cq->comps[info.comp_idx].status == QUEUED ||
- test_bit(SDMA_REQ_IN_USE, &pq->reqs[info.comp_idx].flags)) {
- hfi1_cdbg(SDMA, "[%u:%u:%u] Entry %u is in QUEUED state",
- dd->unit, uctxt->ctxt, fd->subctxt,
- info.comp_idx);
- return -EBADSLT;
+
+ if (info.comp_idx >= hfi1_sdma_comp_ring_size) {
+ hfi1_cdbg(SDMA,
+ "[%u:%u:%u:%u] Invalid comp index",
+ dd->unit, uctxt->ctxt, fd->subctxt, info.comp_idx);
+ return -EINVAL;
}
+
+ /*
+ * Sanity check the header io vector count. Need at least 1 vector
+ * (header) and cannot be larger than the actual io vector count.
+ */
+ if (req_iovcnt(info.ctrl) < 1 || req_iovcnt(info.ctrl) > dim) {
+ hfi1_cdbg(SDMA,
+ "[%u:%u:%u:%u] Invalid iov count %d, dim %ld",
+ dd->unit, uctxt->ctxt, fd->subctxt, info.comp_idx,
+ req_iovcnt(info.ctrl), dim);
+ return -EINVAL;
+ }
+
if (!info.fragsize) {
hfi1_cdbg(SDMA,
"[%u:%u:%u:%u] Request does not specify fragsize",
dd->unit, uctxt->ctxt, fd->subctxt, info.comp_idx);
return -EINVAL;
}
+
+ /* Try to claim the request. */
+ if (test_and_set_bit(info.comp_idx, pq->req_in_use)) {
+ hfi1_cdbg(SDMA, "[%u:%u:%u] Entry %u is in use",
+ dd->unit, uctxt->ctxt, fd->subctxt,
+ info.comp_idx);
+ return -EBADSLT;
+ }
/*
- * We've done all the safety checks that we can up to this point,
- * "allocate" the request entry.
+ * All safety checks have been done and this request has been claimed.
*/
hfi1_cdbg(SDMA, "[%u:%u:%u] Using req/comp entry %u\n", dd->unit,
uctxt->ctxt, fd->subctxt, info.comp_idx);
req = pq->reqs + info.comp_idx;
memset(req, 0, sizeof(*req));
- /* Mark the request as IN_USE before we start filling it in. */
- set_bit(SDMA_REQ_IN_USE, &req->flags);
- req->data_iovs = req_iovcnt(info.ctrl) - 1;
+ req->data_iovs = req_iovcnt(info.ctrl) - 1; /* subtract header vector */
req->pq = pq;
req->cq = cq;
req->status = -1;
@@ -560,13 +614,22 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
memcpy(&req->info, &info, sizeof(info));
- if (req_opcode(info.ctrl) == EXPECTED)
+ if (req_opcode(info.ctrl) == EXPECTED) {
+ /* expected must have a TID info and at least one data vector */
+ if (req->data_iovs < 2) {
+ SDMA_DBG(req,
+ "Not enough vectors for expected request");
+ ret = -EINVAL;
+ goto free_req;
+ }
req->data_iovs--;
+ }
if (!info.npkts || req->data_iovs > MAX_VECTORS_PER_REQ) {
SDMA_DBG(req, "Too many vectors (%u/%u)", req->data_iovs,
MAX_VECTORS_PER_REQ);
- return -EINVAL;
+ ret = -EINVAL;
+ goto free_req;
}
/* Copy the header from the user buffer */
ret = copy_from_user(&req->hdr, iovec[idx].iov_base + sizeof(info),
@@ -634,7 +697,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
idx++;
/* Save all the IO vector structures */
- while (i < req->data_iovs) {
+ for (i = 0; i < req->data_iovs; i++) {
INIT_LIST_HEAD(&req->iovs[i].list);
memcpy(&req->iovs[i].iov, iovec + idx++, sizeof(struct iovec));
ret = pin_vector_pages(req, &req->iovs[i]);
@@ -642,7 +705,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
req->status = ret;
goto free_req;
}
- req->data_len += req->iovs[i++].iov.iov_len;
+ req->data_len += req->iovs[i].iov.iov_len;
}
SDMA_DBG(req, "total data length %u", req->data_len);
@@ -686,9 +749,13 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
idx++;
}
+ dlid = be16_to_cpu(req->hdr.lrh[1]);
+ selector = dlid_to_selector(dlid);
+
/* Have to select the engine */
req->sde = sdma_select_engine_vl(dd,
- (u32)(uctxt->ctxt + fd->subctxt),
+ (u32)(uctxt->ctxt + fd->subctxt +
+ selector),
vl);
if (!req->sde || !sdma_running(req->sde)) {
ret = -ECOMM;
@@ -766,14 +833,21 @@ static inline u32 compute_data_length(struct user_sdma_request *req,
* The size of the data of the first packet is in the header
* template. However, it includes the header and ICRC, which need
* to be subtracted.
+ * The minimum representable packet data length in a header is 4 bytes,
+ * therefore, when the data length request is less than 4 bytes, there's
+ * only one packet, and the packet data length is equal to that of the
+ * request data length.
* The size of the remaining packets is the minimum of the frag
* size (MTU) or remaining data in the request.
*/
u32 len;
if (!req->seqnum) {
- len = ((be16_to_cpu(req->hdr.lrh[2]) << 2) -
- (sizeof(tx->hdr) - 4));
+ if (req->data_len < sizeof(u32))
+ len = req->data_len;
+ else
+ len = ((be16_to_cpu(req->hdr.lrh[2]) << 2) -
+ (sizeof(tx->hdr) - 4));
} else if (req_opcode(req->info.ctrl) == EXPECTED) {
u32 tidlen = EXP_TID_GET(req->tids[req->tididx], LEN) *
PAGE_SIZE;
@@ -803,6 +877,13 @@ static inline u32 compute_data_length(struct user_sdma_request *req,
return len;
}
+static inline u32 pad_len(u32 len)
+{
+ if (len & (sizeof(u32) - 1))
+ len += sizeof(u32) - (len & (sizeof(u32) - 1));
+ return len;
+}
+
static inline u32 get_lrh_len(struct hfi1_pkt_header hdr, u32 len)
{
/* (Size of complete header - size of PBC) + 4B ICRC + data length */
@@ -894,7 +975,8 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags)) {
if (!req->seqnum) {
u16 pbclen = le16_to_cpu(req->hdr.pbc[0]);
- u32 lrhlen = get_lrh_len(req->hdr, datalen);
+ u32 lrhlen = get_lrh_len(req->hdr,
+ pad_len(datalen));
/*
* Copy the request header into the tx header
* because the HW needs a cacheline-aligned
@@ -1048,39 +1130,24 @@ static inline int num_user_pages(const struct iovec *iov)
static u32 sdma_cache_evict(struct hfi1_user_sdma_pkt_q *pq, u32 npages)
{
- u32 cleared = 0;
- struct sdma_mmu_node *node, *ptr;
- struct list_head to_evict = LIST_HEAD_INIT(to_evict);
-
- spin_lock(&pq->evict_lock);
- list_for_each_entry_safe_reverse(node, ptr, &pq->evict, list) {
- /* Make sure that no one is still using the node. */
- if (!atomic_read(&node->refcount)) {
- set_bit(SDMA_CACHE_NODE_EVICT, &node->flags);
- list_del_init(&node->list);
- list_add(&node->list, &to_evict);
- cleared += node->npages;
- if (cleared >= npages)
- break;
- }
- }
- spin_unlock(&pq->evict_lock);
-
- list_for_each_entry_safe(node, ptr, &to_evict, list)
- hfi1_mmu_rb_remove(&pq->sdma_rb_root, &node->rb);
+ struct evict_data evict_data;
- return cleared;
+ evict_data.cleared = 0;
+ evict_data.target = npages;
+ hfi1_mmu_rb_evict(pq->handler, &evict_data);
+ return evict_data.cleared;
}
static int pin_vector_pages(struct user_sdma_request *req,
- struct user_sdma_iovec *iovec) {
+ struct user_sdma_iovec *iovec)
+{
int ret = 0, pinned, npages, cleared;
struct page **pages;
struct hfi1_user_sdma_pkt_q *pq = req->pq;
struct sdma_mmu_node *node = NULL;
struct mmu_rb_node *rb_node;
- rb_node = hfi1_mmu_rb_extract(&pq->sdma_rb_root,
+ rb_node = hfi1_mmu_rb_extract(pq->handler,
(unsigned long)iovec->iov.iov_base,
iovec->iov.iov_len);
if (rb_node && !IS_ERR(rb_node))
@@ -1096,7 +1163,6 @@ static int pin_vector_pages(struct user_sdma_request *req,
node->rb.addr = (unsigned long)iovec->iov.iov_base;
node->pq = pq;
atomic_set(&node->refcount, 0);
- INIT_LIST_HEAD(&node->list);
}
npages = num_user_pages(&iovec->iov);
@@ -1111,28 +1177,14 @@ static int pin_vector_pages(struct user_sdma_request *req,
npages -= node->npages;
- /*
- * If rb_node is NULL, it means that this is brand new node
- * and, therefore not on the eviction list.
- * If, however, the rb_node is non-NULL, it means that the
- * node is already in RB tree and, therefore on the eviction
- * list (nodes are unconditionally inserted in the eviction
- * list). In that case, we have to remove the node prior to
- * calling the eviction function in order to prevent it from
- * freeing this node.
- */
- if (rb_node) {
- spin_lock(&pq->evict_lock);
- list_del_init(&node->list);
- spin_unlock(&pq->evict_lock);
- }
retry:
- if (!hfi1_can_pin_pages(pq->dd, pq->n_locked, npages)) {
+ if (!hfi1_can_pin_pages(pq->dd, pq->mm,
+ atomic_read(&pq->n_locked), npages)) {
cleared = sdma_cache_evict(pq, npages);
if (cleared >= npages)
goto retry;
}
- pinned = hfi1_acquire_user_pages(
+ pinned = hfi1_acquire_user_pages(pq->mm,
((unsigned long)iovec->iov.iov_base +
(node->npages * PAGE_SIZE)), npages, 0,
pages + node->npages);
@@ -1142,7 +1194,7 @@ retry:
goto bail;
}
if (pinned != npages) {
- unpin_vector_pages(current->mm, pages, node->npages,
+ unpin_vector_pages(pq->mm, pages, node->npages,
pinned);
ret = -EFAULT;
goto bail;
@@ -1152,28 +1204,22 @@ retry:
node->pages = pages;
node->npages += pinned;
npages = node->npages;
- spin_lock(&pq->evict_lock);
- list_add(&node->list, &pq->evict);
- pq->n_locked += pinned;
- spin_unlock(&pq->evict_lock);
+ atomic_add(pinned, &pq->n_locked);
}
iovec->pages = node->pages;
iovec->npages = npages;
iovec->node = node;
- ret = hfi1_mmu_rb_insert(&req->pq->sdma_rb_root, &node->rb);
+ ret = hfi1_mmu_rb_insert(req->pq->handler, &node->rb);
if (ret) {
- spin_lock(&pq->evict_lock);
- if (!list_empty(&node->list))
- list_del(&node->list);
- pq->n_locked -= node->npages;
- spin_unlock(&pq->evict_lock);
+ atomic_sub(node->npages, &pq->n_locked);
+ iovec->node = NULL;
goto bail;
}
return 0;
bail:
if (rb_node)
- unpin_vector_pages(current->mm, node->pages, 0, node->npages);
+ unpin_vector_pages(pq->mm, node->pages, 0, node->npages);
kfree(node);
return ret;
}
@@ -1181,7 +1227,7 @@ bail:
static void unpin_vector_pages(struct mm_struct *mm, struct page **pages,
unsigned start, unsigned npages)
{
- hfi1_release_user_pages(mm, pages + start, npages, 0);
+ hfi1_release_user_pages(mm, pages + start, npages, false);
kfree(pages);
}
@@ -1192,16 +1238,14 @@ static int check_header_template(struct user_sdma_request *req,
/*
* Perform safety checks for any type of packet:
* - transfer size is multiple of 64bytes
- * - packet length is multiple of 4bytes
- * - entire request length is multiple of 4bytes
+ * - packet length is multiple of 4 bytes
* - packet length is not larger than MTU size
*
* These checks are only done for the first packet of the
* transfer since the header is "given" to us by user space.
* For the remainder of the packets we compute the values.
*/
- if (req->info.fragsize % PIO_BLOCK_SIZE ||
- lrhlen & 0x3 || req->data_len & 0x3 ||
+ if (req->info.fragsize % PIO_BLOCK_SIZE || lrhlen & 0x3 ||
lrhlen > get_lrh_len(*hdr, req->info.fragsize))
return -EINVAL;
@@ -1263,7 +1307,7 @@ static int set_txreq_header(struct user_sdma_request *req,
struct hfi1_pkt_header *hdr = &tx->hdr;
u16 pbclen;
int ret;
- u32 tidval = 0, lrhlen = get_lrh_len(*hdr, datalen);
+ u32 tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(datalen));
/* Copy the header template to the request before modification */
memcpy(hdr, &req->hdr, sizeof(*hdr));
@@ -1374,7 +1418,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
struct hfi1_user_sdma_pkt_q *pq = req->pq;
struct hfi1_pkt_header *hdr = &req->hdr;
u16 pbclen = le16_to_cpu(hdr->pbc[0]);
- u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, len);
+ u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(len));
if (PBC2LRH(pbclen) != lrhlen) {
/* PBC.PbcLengthDWs */
@@ -1534,14 +1578,14 @@ static void user_sdma_free_request(struct user_sdma_request *req, bool unpin)
continue;
if (unpin)
- hfi1_mmu_rb_remove(&req->pq->sdma_rb_root,
+ hfi1_mmu_rb_remove(req->pq->handler,
&node->rb);
else
atomic_dec(&node->refcount);
}
}
kfree(req->tids);
- clear_bit(SDMA_REQ_IN_USE, &req->flags);
+ clear_bit(req->info.comp_idx, req->pq->req_in_use);
}
static inline void set_comp_state(struct hfi1_user_sdma_pkt_q *pq,
@@ -1564,7 +1608,7 @@ static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr,
return (bool)(node->addr == addr);
}
-static int sdma_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode)
+static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode)
{
struct sdma_mmu_node *node =
container_of(mnode, struct sdma_mmu_node, rb);
@@ -1573,48 +1617,45 @@ static int sdma_rb_insert(struct rb_root *root, struct mmu_rb_node *mnode)
return 0;
}
-static void sdma_rb_remove(struct rb_root *root, struct mmu_rb_node *mnode,
- struct mm_struct *mm)
+/*
+ * Return 1 to remove the node from the rb tree and call the remove op.
+ *
+ * Called with the rb tree lock held.
+ */
+static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
+ void *evict_arg, bool *stop)
+{
+ struct sdma_mmu_node *node =
+ container_of(mnode, struct sdma_mmu_node, rb);
+ struct evict_data *evict_data = evict_arg;
+
+ /* is this node still being used? */
+ if (atomic_read(&node->refcount))
+ return 0; /* keep this node */
+
+ /* this node will be evicted, add its pages to our count */
+ evict_data->cleared += node->npages;
+
+ /* have enough pages been cleared? */
+ if (evict_data->cleared >= evict_data->target)
+ *stop = true;
+
+ return 1; /* remove this node */
+}
+
+static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode)
{
struct sdma_mmu_node *node =
container_of(mnode, struct sdma_mmu_node, rb);
- spin_lock(&node->pq->evict_lock);
- /*
- * We've been called by the MMU notifier but this node has been
- * scheduled for eviction. The eviction function will take care
- * of freeing this node.
- * We have to take the above lock first because we are racing
- * against the setting of the bit in the eviction function.
- */
- if (mm && test_bit(SDMA_CACHE_NODE_EVICT, &node->flags)) {
- spin_unlock(&node->pq->evict_lock);
- return;
- }
+ atomic_sub(node->npages, &node->pq->n_locked);
- if (!list_empty(&node->list))
- list_del(&node->list);
- node->pq->n_locked -= node->npages;
- spin_unlock(&node->pq->evict_lock);
+ unpin_vector_pages(node->pq->mm, node->pages, 0, node->npages);
- /*
- * If mm is set, we are being called by the MMU notifier and we
- * should not pass a mm_struct to unpin_vector_page(). This is to
- * prevent a deadlock when hfi1_release_user_pages() attempts to
- * take the mmap_sem, which the MMU notifier has already taken.
- */
- unpin_vector_pages(mm ? NULL : current->mm, node->pages, 0,
- node->npages);
- /*
- * If called by the MMU notifier, we have to adjust the pinned
- * page count ourselves.
- */
- if (mm)
- mm->pinned_vm -= node->npages;
kfree(node);
}
-static int sdma_rb_invalidate(struct rb_root *root, struct mmu_rb_node *mnode)
+static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode)
{
struct sdma_mmu_node *node =
container_of(mnode, struct sdma_mmu_node, rb);
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.h b/drivers/infiniband/hw/hfi1/user_sdma.h
index b9240e351161..39001714f551 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.h
+++ b/drivers/infiniband/hw/hfi1/user_sdma.h
@@ -63,14 +63,14 @@ struct hfi1_user_sdma_pkt_q {
struct hfi1_devdata *dd;
struct kmem_cache *txreq_cache;
struct user_sdma_request *reqs;
+ unsigned long *req_in_use;
struct iowait busy;
unsigned state;
wait_queue_head_t wait;
unsigned long unpinned;
- struct rb_root sdma_rb_root;
- u32 n_locked;
- struct list_head evict;
- spinlock_t evict_lock; /* protect evict and n_locked */
+ struct mmu_rb_handler *handler;
+ atomic_t n_locked;
+ struct mm_struct *mm;
};
struct hfi1_user_sdma_comp_q {
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index 849c4b9399d4..2b359540901d 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -306,7 +306,10 @@ const enum ib_wc_opcode ib_hfi1_wc_opcode[] = {
[IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
[IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
- [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD
+ [IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD,
+ [IB_WR_SEND_WITH_INV] = IB_WC_SEND,
+ [IB_WR_LOCAL_INV] = IB_WC_LOCAL_INV,
+ [IB_WR_REG_MR] = IB_WC_REG_MR
};
/*
@@ -378,6 +381,8 @@ static const opcode_handler opcode_handler_tbl[256] = {
[IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE] = &hfi1_rc_rcv,
[IB_OPCODE_RC_COMPARE_SWAP] = &hfi1_rc_rcv,
[IB_OPCODE_RC_FETCH_ADD] = &hfi1_rc_rcv,
+ [IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE] = &hfi1_rc_rcv,
+ [IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE] = &hfi1_rc_rcv,
/* UC */
[IB_OPCODE_UC_SEND_FIRST] = &hfi1_uc_rcv,
[IB_OPCODE_UC_SEND_MIDDLE] = &hfi1_uc_rcv,
@@ -540,19 +545,15 @@ void hfi1_skip_sge(struct rvt_sge_state *ss, u32 length, int release)
/*
* Make sure the QP is ready and able to accept the given opcode.
*/
-static inline int qp_ok(int opcode, struct hfi1_packet *packet)
+static inline opcode_handler qp_ok(int opcode, struct hfi1_packet *packet)
{
- struct hfi1_ibport *ibp;
-
if (!(ib_rvt_state_ops[packet->qp->state] & RVT_PROCESS_RECV_OK))
- goto dropit;
+ return NULL;
if (((opcode & RVT_OPCODE_QP_MASK) == packet->qp->allowed_ops) ||
(opcode == IB_OPCODE_CNP))
- return 1;
-dropit:
- ibp = &packet->rcd->ppd->ibport_data;
- ibp->rvp.n_pkt_drops++;
- return 0;
+ return opcode_handler_tbl[opcode];
+
+ return NULL;
}
/**
@@ -571,6 +572,7 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
struct hfi1_pportdata *ppd = rcd->ppd;
struct hfi1_ibport *ibp = &ppd->ibport_data;
struct rvt_dev_info *rdi = &ppd->dd->verbs_dev.rdi;
+ opcode_handler packet_handler;
unsigned long flags;
u32 qp_num;
int lnh;
@@ -616,8 +618,11 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
list_for_each_entry_rcu(p, &mcast->qp_list, list) {
packet->qp = p->qp;
spin_lock_irqsave(&packet->qp->r_lock, flags);
- if (likely((qp_ok(opcode, packet))))
- opcode_handler_tbl[opcode](packet);
+ packet_handler = qp_ok(opcode, packet);
+ if (likely(packet_handler))
+ packet_handler(packet);
+ else
+ ibp->rvp.n_pkt_drops++;
spin_unlock_irqrestore(&packet->qp->r_lock, flags);
}
/*
@@ -634,8 +639,11 @@ void hfi1_ib_rcv(struct hfi1_packet *packet)
goto drop;
}
spin_lock_irqsave(&packet->qp->r_lock, flags);
- if (likely((qp_ok(opcode, packet))))
- opcode_handler_tbl[opcode](packet);
+ packet_handler = qp_ok(opcode, packet);
+ if (likely(packet_handler))
+ packet_handler(packet);
+ else
+ ibp->rvp.n_pkt_drops++;
spin_unlock_irqrestore(&packet->qp->r_lock, flags);
rcu_read_unlock();
}
@@ -808,19 +816,19 @@ static int build_verbs_tx_desc(
struct rvt_sge_state *ss,
u32 length,
struct verbs_txreq *tx,
- struct ahg_ib_header *ahdr,
+ struct hfi1_ahg_info *ahg_info,
u64 pbc)
{
int ret = 0;
- struct hfi1_pio_header *phdr = &tx->phdr;
+ struct hfi1_sdma_header *phdr = &tx->phdr;
u16 hdrbytes = tx->hdr_dwords << 2;
- if (!ahdr->ahgcount) {
+ if (!ahg_info->ahgcount) {
ret = sdma_txinit_ahg(
&tx->txreq,
- ahdr->tx_flags,
+ ahg_info->tx_flags,
hdrbytes + length,
- ahdr->ahgidx,
+ ahg_info->ahgidx,
0,
NULL,
0,
@@ -838,11 +846,11 @@ static int build_verbs_tx_desc(
} else {
ret = sdma_txinit_ahg(
&tx->txreq,
- ahdr->tx_flags,
+ ahg_info->tx_flags,
length,
- ahdr->ahgidx,
- ahdr->ahgcount,
- ahdr->ahgdesc,
+ ahg_info->ahgidx,
+ ahg_info->ahgcount,
+ ahg_info->ahgdesc,
hdrbytes,
verbs_sdma_complete);
if (ret)
@@ -860,7 +868,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
u64 pbc)
{
struct hfi1_qp_priv *priv = qp->priv;
- struct ahg_ib_header *ahdr = priv->s_hdr;
+ struct hfi1_ahg_info *ahg_info = priv->s_ahg;
u32 hdrwords = qp->s_hdrwords;
struct rvt_sge_state *ss = qp->s_cur_sge;
u32 len = qp->s_cur_size;
@@ -888,7 +896,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
plen);
}
tx->wqe = qp->s_wqe;
- ret = build_verbs_tx_desc(tx->sde, ss, len, tx, ahdr, pbc);
+ ret = build_verbs_tx_desc(tx->sde, ss, len, tx, ahg_info, pbc);
if (unlikely(ret))
goto bail_build;
}
@@ -1291,19 +1299,24 @@ int hfi1_verbs_send(struct rvt_qp *qp, struct hfi1_pkt_state *ps)
static void hfi1_fill_device_attr(struct hfi1_devdata *dd)
{
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
+ u16 ver = dd->dc8051_ver;
memset(&rdi->dparms.props, 0, sizeof(rdi->dparms.props));
+ rdi->dparms.props.fw_ver = ((u64)(dc8051_ver_maj(ver)) << 16) |
+ (u64)dc8051_ver_min(ver);
rdi->dparms.props.device_cap_flags = IB_DEVICE_BAD_PKEY_CNTR |
IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT |
IB_DEVICE_SYS_IMAGE_GUID | IB_DEVICE_RC_RNR_NAK_GEN |
- IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE;
+ IB_DEVICE_PORT_ACTIVE_EVENT | IB_DEVICE_SRQ_RESIZE |
+ IB_DEVICE_MEM_MGT_EXTENSIONS;
rdi->dparms.props.page_size_cap = PAGE_SIZE;
rdi->dparms.props.vendor_id = dd->oui1 << 16 | dd->oui2 << 8 | dd->oui3;
rdi->dparms.props.vendor_part_id = dd->pcidev->device;
rdi->dparms.props.hw_ver = dd->minrev;
rdi->dparms.props.sys_image_guid = ib_hfi1_sys_image_guid;
- rdi->dparms.props.max_mr_size = ~0ULL;
+ rdi->dparms.props.max_mr_size = U64_MAX;
+ rdi->dparms.props.max_fast_reg_page_list_len = UINT_MAX;
rdi->dparms.props.max_qp = hfi1_max_qps;
rdi->dparms.props.max_qp_wr = hfi1_max_qp_wrs;
rdi->dparms.props.max_sge = hfi1_max_sges;
@@ -1567,6 +1580,17 @@ static void init_ibport(struct hfi1_pportdata *ppd)
RCU_INIT_POINTER(ibp->rvp.qp[1], NULL);
}
+static void hfi1_get_dev_fw_str(struct ib_device *ibdev, char *str,
+ size_t str_len)
+{
+ struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
+ struct hfi1_ibdev *dev = dev_from_rdi(rdi);
+ u16 ver = dd_from_dev(dev)->dc8051_ver;
+
+ snprintf(str, str_len, "%u.%u", dc8051_ver_maj(ver),
+ dc8051_ver_min(ver));
+}
+
/**
* hfi1_register_ib_device - register our device with the infiniband core
* @dd: the device data structure
@@ -1613,6 +1637,7 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
/* keep process mad in the driver */
ibdev->process_mad = hfi1_process_mad;
+ ibdev->get_dev_fw_str = hfi1_get_dev_fw_str;
strncpy(ibdev->node_desc, init_utsname()->nodename,
sizeof(ibdev->node_desc));
@@ -1680,6 +1705,9 @@ int hfi1_register_ib_device(struct hfi1_devdata *dd)
dd->verbs_dev.rdi.dparms.nports = dd->num_pports;
dd->verbs_dev.rdi.dparms.npkeys = hfi1_get_npkeys(dd);
+ /* post send table */
+ dd->verbs_dev.rdi.post_parms = hfi1_post_parms;
+
ppd = dd->pport;
for (i = 0; i < dd->num_pports; i++, ppd++)
rvt_init_port(&dd->verbs_dev.rdi,
@@ -1730,8 +1758,7 @@ void hfi1_cnp_rcv(struct hfi1_packet *packet)
struct rvt_qp *qp = packet->qp;
u32 lqpn, rqpn = 0;
u16 rlid = 0;
- u8 sl, sc5, sc4_bit, svc_type;
- bool sc4_set = has_sc4_bit(packet);
+ u8 sl, sc5, svc_type;
switch (packet->qp->ibqp.qp_type) {
case IB_QPT_UC:
@@ -1754,9 +1781,7 @@ void hfi1_cnp_rcv(struct hfi1_packet *packet)
return;
}
- sc4_bit = sc4_set << 4;
- sc5 = (be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf;
- sc5 |= sc4_bit;
+ sc5 = hdr2sc((struct hfi1_message_header *)hdr, packet->rhf);
sl = ibp->sc_to_sl[sc5];
lqpn = qp->ibqp.qp_num;
diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h
index 488356775627..d1b101c54828 100644
--- a/drivers/infiniband/hw/hfi1/verbs.h
+++ b/drivers/infiniband/hw/hfi1/verbs.h
@@ -178,16 +178,14 @@ struct hfi1_ib_header {
} u;
} __packed;
-struct ahg_ib_header {
- struct sdma_engine *sde;
+struct hfi1_ahg_info {
u32 ahgdesc[2];
u16 tx_flags;
u8 ahgcount;
u8 ahgidx;
- struct hfi1_ib_header ibh;
};
-struct hfi1_pio_header {
+struct hfi1_sdma_header {
__le64 pbc;
struct hfi1_ib_header hdr;
} __packed;
@@ -197,7 +195,7 @@ struct hfi1_pio_header {
* pair is made common
*/
struct hfi1_qp_priv {
- struct ahg_ib_header *s_hdr; /* next header to send */
+ struct hfi1_ahg_info *s_ahg; /* ahg info for next header */
struct sdma_engine *s_sde; /* current sde */
struct send_context *s_sendcontext; /* current sendcontext */
u8 s_sc; /* SC[0..4] for next packet */
diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.h b/drivers/infiniband/hw/hfi1/verbs_txreq.h
index a1d6e0807f97..5660897593ba 100644
--- a/drivers/infiniband/hw/hfi1/verbs_txreq.h
+++ b/drivers/infiniband/hw/hfi1/verbs_txreq.h
@@ -56,7 +56,7 @@
#include "iowait.h"
struct verbs_txreq {
- struct hfi1_pio_header phdr;
+ struct hfi1_sdma_header phdr;
struct sdma_txreq txreq;
struct rvt_qp *qp;
struct rvt_swqe *wqe;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index d2fa72516960..5026dc79978a 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -1567,12 +1567,12 @@ static enum i40iw_status_code i40iw_del_multiple_qhash(
ret = i40iw_manage_qhash(iwdev, cm_info,
I40IW_QHASH_TYPE_TCP_SYN,
I40IW_QHASH_MANAGE_TYPE_DELETE, NULL, false);
- kfree(child_listen_node);
- cm_parent_listen_node->cm_core->stats_listen_nodes_destroyed++;
i40iw_debug(&iwdev->sc_dev,
I40IW_DEBUG_CM,
"freed pointer = %p\n",
child_listen_node);
+ kfree(child_listen_node);
+ cm_parent_listen_node->cm_core->stats_listen_nodes_destroyed++;
}
spin_unlock_irqrestore(&iwdev->cm_core.listen_list_lock, flags);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_d.h b/drivers/infiniband/hw/i40iw/i40iw_d.h
index bd942da91a27..2fac1db0e0a0 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_d.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_d.h
@@ -1557,6 +1557,9 @@ enum i40iw_alignment {
#define I40IW_RING_MOVE_TAIL(_ring) \
(_ring).tail = ((_ring).tail + 1) % (_ring).size
+#define I40IW_RING_MOVE_HEAD_NOCHECK(_ring) \
+ (_ring).head = ((_ring).head + 1) % (_ring).size
+
#define I40IW_RING_MOVE_TAIL_BY_COUNT(_ring, _count) \
(_ring).tail = ((_ring).tail + (_count)) % (_ring).size
diff --git a/drivers/infiniband/hw/i40iw/i40iw_puda.c b/drivers/infiniband/hw/i40iw/i40iw_puda.c
index e9c6e82af9c7..c62d354f7810 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_puda.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_puda.c
@@ -1025,6 +1025,8 @@ static void i40iw_ieq_compl_pfpdu(struct i40iw_puda_rsrc *ieq,
u16 txoffset, bufoffset;
buf = i40iw_puda_get_listbuf(pbufl);
+ if (!buf)
+ return;
nextseqnum = buf->seqnum + fpdu_len;
txbuf->totallen = buf->hdrlen + fpdu_len;
txbuf->data = (u8 *)txbuf->mem.va + buf->hdrlen;
@@ -1048,6 +1050,8 @@ static void i40iw_ieq_compl_pfpdu(struct i40iw_puda_rsrc *ieq,
fpdu_len -= buf->datalen;
i40iw_puda_ret_bufpool(ieq, buf);
buf = i40iw_puda_get_listbuf(pbufl);
+ if (!buf)
+ return;
bufoffset = (u16)(buf->data - (u8 *)buf->mem.va);
} while (1);
diff --git a/drivers/infiniband/hw/i40iw/i40iw_type.h b/drivers/infiniband/hw/i40iw/i40iw_type.h
index 16cc61720b53..2b1a04e9ca3c 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_type.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_type.h
@@ -667,7 +667,7 @@ struct i40iw_tcp_offload_info {
bool time_stamp;
u8 cwnd_inc_limit;
bool drop_ooo_seg;
- bool dup_ack_thresh;
+ u8 dup_ack_thresh;
u8 ttl;
u8 src_mac_addr_idx;
bool avoid_stretch_ack;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_uk.c b/drivers/infiniband/hw/i40iw/i40iw_uk.c
index e35faea88c13..4d28c3cb03cc 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_uk.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_uk.c
@@ -291,9 +291,9 @@ static enum i40iw_status_code i40iw_rdma_write(struct i40iw_qp_uk *qp,
i40iw_set_fragment(wqe, 0, op_info->lo_sg_list);
- for (i = 1; i < op_info->num_lo_sges; i++) {
- byte_off = 32 + (i - 1) * 16;
+ for (i = 1, byte_off = 32; i < op_info->num_lo_sges; i++) {
i40iw_set_fragment(wqe, byte_off, &op_info->lo_sg_list[i]);
+ byte_off += 16;
}
wmb(); /* make sure WQE is populated before valid bit is set */
@@ -401,9 +401,9 @@ static enum i40iw_status_code i40iw_send(struct i40iw_qp_uk *qp,
i40iw_set_fragment(wqe, 0, op_info->sg_list);
- for (i = 1; i < op_info->num_sges; i++) {
- byte_off = 32 + (i - 1) * 16;
+ for (i = 1, byte_off = 32; i < op_info->num_sges; i++) {
i40iw_set_fragment(wqe, byte_off, &op_info->sg_list[i]);
+ byte_off += 16;
}
wmb(); /* make sure WQE is populated before valid bit is set */
@@ -685,9 +685,9 @@ static enum i40iw_status_code i40iw_post_receive(struct i40iw_qp_uk *qp,
i40iw_set_fragment(wqe, 0, info->sg_list);
- for (i = 1; i < info->num_sges; i++) {
- byte_off = 32 + (i - 1) * 16;
+ for (i = 1, byte_off = 32; i < info->num_sges; i++) {
i40iw_set_fragment(wqe, byte_off, &info->sg_list[i]);
+ byte_off += 16;
}
wmb(); /* make sure WQE is populated before valid bit is set */
@@ -753,8 +753,7 @@ static enum i40iw_status_code i40iw_cq_post_entries(struct i40iw_cq_uk *cq,
* @post_cq: update cq tail
*/
static enum i40iw_status_code i40iw_cq_poll_completion(struct i40iw_cq_uk *cq,
- struct i40iw_cq_poll_info *info,
- bool post_cq)
+ struct i40iw_cq_poll_info *info)
{
u64 comp_ctx, qword0, qword2, qword3, wqe_qword;
u64 *cqe, *sw_wqe;
@@ -762,7 +761,6 @@ static enum i40iw_status_code i40iw_cq_poll_completion(struct i40iw_cq_uk *cq,
struct i40iw_ring *pring = NULL;
u32 wqe_idx, q_type, array_idx = 0;
enum i40iw_status_code ret_code = 0;
- enum i40iw_status_code ret_code2 = 0;
bool move_cq_head = true;
u8 polarity;
u8 addl_wqes = 0;
@@ -870,19 +868,14 @@ exit:
move_cq_head = false;
if (move_cq_head) {
- I40IW_RING_MOVE_HEAD(cq->cq_ring, ret_code2);
-
- if (ret_code2 && !ret_code)
- ret_code = ret_code2;
+ I40IW_RING_MOVE_HEAD_NOCHECK(cq->cq_ring);
if (I40IW_RING_GETCURRENT_HEAD(cq->cq_ring) == 0)
cq->polarity ^= 1;
- if (post_cq) {
- I40IW_RING_MOVE_TAIL(cq->cq_ring);
- set_64bit_val(cq->shadow_area, 0,
- I40IW_RING_GETCURRENT_HEAD(cq->cq_ring));
- }
+ I40IW_RING_MOVE_TAIL(cq->cq_ring);
+ set_64bit_val(cq->shadow_area, 0,
+ I40IW_RING_GETCURRENT_HEAD(cq->cq_ring));
} else {
if (info->is_srq)
return ret_code;
diff --git a/drivers/infiniband/hw/i40iw/i40iw_user.h b/drivers/infiniband/hw/i40iw/i40iw_user.h
index 4627646fe8cd..276bcefffd7e 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_user.h
+++ b/drivers/infiniband/hw/i40iw/i40iw_user.h
@@ -327,7 +327,7 @@ struct i40iw_cq_ops {
void (*iw_cq_request_notification)(struct i40iw_cq_uk *,
enum i40iw_completion_notify);
enum i40iw_status_code (*iw_cq_poll_completion)(struct i40iw_cq_uk *,
- struct i40iw_cq_poll_info *, bool);
+ struct i40iw_cq_poll_info *);
enum i40iw_status_code (*iw_cq_post_entries)(struct i40iw_cq_uk *, u8 count);
void (*iw_cq_clean)(void *, struct i40iw_cq_uk *);
};
diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
index 283b64c942ee..2360338877bf 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -529,7 +529,7 @@ static int i40iw_setup_kmode_qp(struct i40iw_device *iwdev,
status = i40iw_get_wqe_shift(rq_size, ukinfo->max_rq_frag_cnt, 0, &rqshift);
if (status)
- return -ENOSYS;
+ return -ENOMEM;
sqdepth = sq_size << sqshift;
rqdepth = rq_size << rqshift;
@@ -671,7 +671,7 @@ static struct ib_qp *i40iw_create_qp(struct ib_pd *ibpd,
iwqp->ctx_info.qp_compl_ctx = (uintptr_t)qp;
if (init_attr->qp_type != IB_QPT_RC) {
- err_code = -ENOSYS;
+ err_code = -EINVAL;
goto error;
}
if (iwdev->push_mode)
@@ -1840,6 +1840,7 @@ struct ib_mr *i40iw_reg_phys_mr(struct ib_pd *pd,
iwmr->ibmr.lkey = stag;
iwmr->page_cnt = 1;
iwmr->pgaddrmem[0] = addr;
+ iwmr->length = size;
status = i40iw_hwreg_mr(iwdev, iwmr, access);
if (status) {
i40iw_free_stag(iwdev, stag);
@@ -1863,7 +1864,7 @@ static struct ib_mr *i40iw_get_dma_mr(struct ib_pd *pd, int acc)
{
u64 kva = 0;
- return i40iw_reg_phys_mr(pd, 0, 0xffffffffffULL, acc, &kva);
+ return i40iw_reg_phys_mr(pd, 0, 0, acc, &kva);
}
/**
@@ -1975,18 +1976,6 @@ static ssize_t i40iw_show_rev(struct device *dev,
}
/**
- * i40iw_show_fw_ver
- */
-static ssize_t i40iw_show_fw_ver(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- u32 firmware_version = I40IW_FW_VERSION;
-
- return sprintf(buf, "%u.%u\n", firmware_version,
- (firmware_version & 0x000000ff));
-}
-
-/**
* i40iw_show_hca
*/
static ssize_t i40iw_show_hca(struct device *dev,
@@ -2006,13 +1995,11 @@ static ssize_t i40iw_show_board(struct device *dev,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, i40iw_show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, i40iw_show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, i40iw_show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, i40iw_show_board, NULL);
static struct device_attribute *i40iw_dev_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id
};
@@ -2091,8 +2078,12 @@ static int i40iw_post_send(struct ib_qp *ibqp,
ret = ukqp->ops.iw_send(ukqp, &info, ib_wr->ex.invalidate_rkey, false);
}
- if (ret)
- err = -EIO;
+ if (ret) {
+ if (ret == I40IW_ERR_QP_TOOMANY_WRS_POSTED)
+ err = -ENOMEM;
+ else
+ err = -EINVAL;
+ }
break;
case IB_WR_RDMA_WRITE:
info.op_type = I40IW_OP_TYPE_RDMA_WRITE;
@@ -2113,8 +2104,12 @@ static int i40iw_post_send(struct ib_qp *ibqp,
ret = ukqp->ops.iw_rdma_write(ukqp, &info, false);
}
- if (ret)
- err = -EIO;
+ if (ret) {
+ if (ret == I40IW_ERR_QP_TOOMANY_WRS_POSTED)
+ err = -ENOMEM;
+ else
+ err = -EINVAL;
+ }
break;
case IB_WR_RDMA_READ_WITH_INV:
inv_stag = true;
@@ -2132,15 +2127,19 @@ static int i40iw_post_send(struct ib_qp *ibqp,
info.op.rdma_read.lo_addr.stag = ib_wr->sg_list->lkey;
info.op.rdma_read.lo_addr.len = ib_wr->sg_list->length;
ret = ukqp->ops.iw_rdma_read(ukqp, &info, inv_stag, false);
- if (ret)
- err = -EIO;
+ if (ret) {
+ if (ret == I40IW_ERR_QP_TOOMANY_WRS_POSTED)
+ err = -ENOMEM;
+ else
+ err = -EINVAL;
+ }
break;
case IB_WR_LOCAL_INV:
info.op_type = I40IW_OP_TYPE_INV_STAG;
info.op.inv_local_stag.target_stag = ib_wr->ex.invalidate_rkey;
ret = ukqp->ops.iw_stag_local_invalidate(ukqp, &info, true);
if (ret)
- err = -EIO;
+ err = -ENOMEM;
break;
case IB_WR_REG_MR:
{
@@ -2174,7 +2173,7 @@ static int i40iw_post_send(struct ib_qp *ibqp,
ret = dev->iw_priv_qp_ops->iw_mr_fast_register(&iwqp->sc_qp, &info, true);
if (ret)
- err = -EIO;
+ err = -ENOMEM;
break;
}
default:
@@ -2214,6 +2213,7 @@ static int i40iw_post_recv(struct ib_qp *ibqp,
struct i40iw_sge sg_list[I40IW_MAX_WQ_FRAGMENT_COUNT];
enum i40iw_status_code ret = 0;
unsigned long flags;
+ int err = 0;
iwqp = (struct i40iw_qp *)ibqp;
ukqp = &iwqp->sc_qp.qp_uk;
@@ -2228,6 +2228,10 @@ static int i40iw_post_recv(struct ib_qp *ibqp,
ret = ukqp->ops.iw_post_receive(ukqp, &post_recv);
if (ret) {
i40iw_pr_err(" post_recv err %d\n", ret);
+ if (ret == I40IW_ERR_QP_TOOMANY_WRS_POSTED)
+ err = -ENOMEM;
+ else
+ err = -EINVAL;
*bad_wr = ib_wr;
goto out;
}
@@ -2235,9 +2239,7 @@ static int i40iw_post_recv(struct ib_qp *ibqp,
}
out:
spin_unlock_irqrestore(&iwqp->lock, flags);
- if (ret)
- return -ENOSYS;
- return 0;
+ return err;
}
/**
@@ -2264,7 +2266,7 @@ static int i40iw_poll_cq(struct ib_cq *ibcq,
spin_lock_irqsave(&iwcq->lock, flags);
while (cqe_count < num_entries) {
- ret = ukcq->ops.iw_cq_poll_completion(ukcq, &cq_poll_info, true);
+ ret = ukcq->ops.iw_cq_poll_completion(ukcq, &cq_poll_info);
if (ret == I40IW_ERR_QUEUE_EMPTY) {
break;
} else if (ret == I40IW_ERR_QUEUE_DESTROYED) {
@@ -2437,6 +2439,15 @@ static const char * const i40iw_hw_stat_names[] = {
"iwRdmaInv"
};
+static void i40iw_get_dev_fw_str(struct ib_device *dev, char *str,
+ size_t str_len)
+{
+ u32 firmware_version = I40IW_FW_VERSION;
+
+ snprintf(str, str_len, "%u.%u", firmware_version,
+ (firmware_version & 0x000000ff));
+}
+
/**
* i40iw_alloc_hw_stats - Allocate a hw stats structure
* @ibdev: device pointer from stack
@@ -2528,7 +2539,7 @@ static int i40iw_modify_port(struct ib_device *ibdev,
int port_modify_mask,
struct ib_port_modify *props)
{
- return 0;
+ return -ENOSYS;
}
/**
@@ -2660,6 +2671,7 @@ static struct i40iw_ib_device *i40iw_init_rdma_device(struct i40iw_device *iwdev
memcpy(iwibdev->ibdev.iwcm->ifname, netdev->name,
sizeof(iwibdev->ibdev.iwcm->ifname));
iwibdev->ibdev.get_port_immutable = i40iw_port_immutable;
+ iwibdev->ibdev.get_dev_fw_str = i40iw_get_dev_fw_str;
iwibdev->ibdev.poll_cq = i40iw_poll_cq;
iwibdev->ibdev.req_notify_cq = i40iw_req_notify_cq;
iwibdev->ibdev.post_send = i40iw_post_send;
@@ -2723,7 +2735,7 @@ int i40iw_register_rdma_device(struct i40iw_device *iwdev)
iwdev->iwibdev = i40iw_init_rdma_device(iwdev);
if (!iwdev->iwibdev)
- return -ENOSYS;
+ return -ENOMEM;
iwibdev = iwdev->iwibdev;
ret = ib_register_device(&iwibdev->ibdev, NULL);
@@ -2748,5 +2760,5 @@ error:
kfree(iwdev->iwibdev->ibdev.iwcm);
iwdev->iwibdev->ibdev.iwcm = NULL;
ib_dealloc_device(&iwdev->iwibdev->ibdev);
- return -ENOSYS;
+ return ret;
}
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 9f8b516eb2b0..d6fc8a6e8c33 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -288,7 +288,7 @@ static int mlx4_alloc_resize_buf(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq,
if (cq->resize_buf)
return -EBUSY;
- cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
+ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_KERNEL);
if (!cq->resize_buf)
return -ENOMEM;
@@ -316,7 +316,7 @@ static int mlx4_alloc_resize_umem(struct mlx4_ib_dev *dev, struct mlx4_ib_cq *cq
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
return -EFAULT;
- cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
+ cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_KERNEL);
if (!cq->resize_buf)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 42a46078d7d5..2af44c2de262 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -2025,16 +2025,6 @@ static ssize_t show_hca(struct device *device, struct device_attribute *attr,
return sprintf(buf, "MT%d\n", dev->dev->persist->pdev->device);
}
-static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct mlx4_ib_dev *dev =
- container_of(device, struct mlx4_ib_dev, ib_dev.dev);
- return sprintf(buf, "%d.%d.%d\n", (int) (dev->dev->caps.fw_ver >> 32),
- (int) (dev->dev->caps.fw_ver >> 16) & 0xffff,
- (int) dev->dev->caps.fw_ver & 0xffff);
-}
-
static ssize_t show_rev(struct device *device, struct device_attribute *attr,
char *buf)
{
@@ -2053,17 +2043,204 @@ static ssize_t show_board(struct device *device, struct device_attribute *attr,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct device_attribute *mlx4_class_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id
};
+struct diag_counter {
+ const char *name;
+ u32 offset;
+};
+
+#define DIAG_COUNTER(_name, _offset) \
+ { .name = #_name, .offset = _offset }
+
+static const struct diag_counter diag_basic[] = {
+ DIAG_COUNTER(rq_num_lle, 0x00),
+ DIAG_COUNTER(sq_num_lle, 0x04),
+ DIAG_COUNTER(rq_num_lqpoe, 0x08),
+ DIAG_COUNTER(sq_num_lqpoe, 0x0C),
+ DIAG_COUNTER(rq_num_lpe, 0x18),
+ DIAG_COUNTER(sq_num_lpe, 0x1C),
+ DIAG_COUNTER(rq_num_wrfe, 0x20),
+ DIAG_COUNTER(sq_num_wrfe, 0x24),
+ DIAG_COUNTER(sq_num_mwbe, 0x2C),
+ DIAG_COUNTER(sq_num_bre, 0x34),
+ DIAG_COUNTER(sq_num_rire, 0x44),
+ DIAG_COUNTER(rq_num_rire, 0x48),
+ DIAG_COUNTER(sq_num_rae, 0x4C),
+ DIAG_COUNTER(rq_num_rae, 0x50),
+ DIAG_COUNTER(sq_num_roe, 0x54),
+ DIAG_COUNTER(sq_num_tree, 0x5C),
+ DIAG_COUNTER(sq_num_rree, 0x64),
+ DIAG_COUNTER(rq_num_rnr, 0x68),
+ DIAG_COUNTER(sq_num_rnr, 0x6C),
+ DIAG_COUNTER(rq_num_oos, 0x100),
+ DIAG_COUNTER(sq_num_oos, 0x104),
+};
+
+static const struct diag_counter diag_ext[] = {
+ DIAG_COUNTER(rq_num_dup, 0x130),
+ DIAG_COUNTER(sq_num_to, 0x134),
+};
+
+static const struct diag_counter diag_device_only[] = {
+ DIAG_COUNTER(num_cqovf, 0x1A0),
+ DIAG_COUNTER(rq_num_udsdprd, 0x118),
+};
+
+static struct rdma_hw_stats *mlx4_ib_alloc_hw_stats(struct ib_device *ibdev,
+ u8 port_num)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ struct mlx4_ib_diag_counters *diag = dev->diag_counters;
+
+ if (!diag[!!port_num].name)
+ return NULL;
+
+ return rdma_alloc_hw_stats_struct(diag[!!port_num].name,
+ diag[!!port_num].num_counters,
+ RDMA_HW_STATS_DEFAULT_LIFESPAN);
+}
+
+static int mlx4_ib_get_hw_stats(struct ib_device *ibdev,
+ struct rdma_hw_stats *stats,
+ u8 port, int index)
+{
+ struct mlx4_ib_dev *dev = to_mdev(ibdev);
+ struct mlx4_ib_diag_counters *diag = dev->diag_counters;
+ u32 hw_value[ARRAY_SIZE(diag_device_only) +
+ ARRAY_SIZE(diag_ext) + ARRAY_SIZE(diag_basic)] = {};
+ int ret;
+ int i;
+
+ ret = mlx4_query_diag_counters(dev->dev,
+ MLX4_OP_MOD_QUERY_TRANSPORT_CI_ERRORS,
+ diag[!!port].offset, hw_value,
+ diag[!!port].num_counters, port);
+
+ if (ret)
+ return ret;
+
+ for (i = 0; i < diag[!!port].num_counters; i++)
+ stats->value[i] = hw_value[i];
+
+ return diag[!!port].num_counters;
+}
+
+static int __mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev,
+ const char ***name,
+ u32 **offset,
+ u32 *num,
+ bool port)
+{
+ u32 num_counters;
+
+ num_counters = ARRAY_SIZE(diag_basic);
+
+ if (ibdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT)
+ num_counters += ARRAY_SIZE(diag_ext);
+
+ if (!port)
+ num_counters += ARRAY_SIZE(diag_device_only);
+
+ *name = kcalloc(num_counters, sizeof(**name), GFP_KERNEL);
+ if (!*name)
+ return -ENOMEM;
+
+ *offset = kcalloc(num_counters, sizeof(**offset), GFP_KERNEL);
+ if (!*offset)
+ goto err_name;
+
+ *num = num_counters;
+
+ return 0;
+
+err_name:
+ kfree(*name);
+ return -ENOMEM;
+}
+
+static void mlx4_ib_fill_diag_counters(struct mlx4_ib_dev *ibdev,
+ const char **name,
+ u32 *offset,
+ bool port)
+{
+ int i;
+ int j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(diag_basic); i++, j++) {
+ name[i] = diag_basic[i].name;
+ offset[i] = diag_basic[i].offset;
+ }
+
+ if (ibdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT) {
+ for (i = 0; i < ARRAY_SIZE(diag_ext); i++, j++) {
+ name[j] = diag_ext[i].name;
+ offset[j] = diag_ext[i].offset;
+ }
+ }
+
+ if (!port) {
+ for (i = 0; i < ARRAY_SIZE(diag_device_only); i++, j++) {
+ name[j] = diag_device_only[i].name;
+ offset[j] = diag_device_only[i].offset;
+ }
+ }
+}
+
+static int mlx4_ib_alloc_diag_counters(struct mlx4_ib_dev *ibdev)
+{
+ struct mlx4_ib_diag_counters *diag = ibdev->diag_counters;
+ int i;
+ int ret;
+ bool per_port = !!(ibdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT);
+
+ for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) {
+ /* i == 1 means we are building port counters */
+ if (i && !per_port)
+ continue;
+
+ ret = __mlx4_ib_alloc_diag_counters(ibdev, &diag[i].name,
+ &diag[i].offset,
+ &diag[i].num_counters, i);
+ if (ret)
+ goto err_alloc;
+
+ mlx4_ib_fill_diag_counters(ibdev, diag[i].name,
+ diag[i].offset, i);
+ }
+
+ ibdev->ib_dev.get_hw_stats = mlx4_ib_get_hw_stats;
+ ibdev->ib_dev.alloc_hw_stats = mlx4_ib_alloc_hw_stats;
+
+ return 0;
+
+err_alloc:
+ if (i) {
+ kfree(diag[i - 1].name);
+ kfree(diag[i - 1].offset);
+ }
+
+ return ret;
+}
+
+static void mlx4_ib_diag_cleanup(struct mlx4_ib_dev *ibdev)
+{
+ int i;
+
+ for (i = 0; i < MLX4_DIAG_COUNTERS_TYPES; i++) {
+ kfree(ibdev->diag_counters[i].offset);
+ kfree(ibdev->diag_counters[i].name);
+ }
+}
+
#define MLX4_IB_INVALID_MAC ((u64)-1)
static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev,
struct net_device *dev,
@@ -2280,6 +2457,17 @@ static int mlx4_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_fw_ver_str(struct ib_device *device, char *str,
+ size_t str_len)
+{
+ struct mlx4_ib_dev *dev =
+ container_of(device, struct mlx4_ib_dev, ib_dev);
+ snprintf(str, str_len, "%d.%d.%d",
+ (int) (dev->dev->caps.fw_ver >> 32),
+ (int) (dev->dev->caps.fw_ver >> 16) & 0xffff,
+ (int) dev->dev->caps.fw_ver & 0xffff);
+}
+
static void *mlx4_ib_add(struct mlx4_dev *dev)
{
struct mlx4_ib_dev *ibdev;
@@ -2413,6 +2601,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach;
ibdev->ib_dev.process_mad = mlx4_ib_process_mad;
ibdev->ib_dev.get_port_immutable = mlx4_port_immutable;
+ ibdev->ib_dev.get_dev_fw_str = get_fw_ver_str;
ibdev->ib_dev.disassociate_ucontext = mlx4_ib_disassociate_ucontext;
if (!mlx4_is_slave(ibdev->dev)) {
@@ -2555,9 +2744,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
for (j = 1; j <= ibdev->dev->caps.num_ports; j++)
atomic64_set(&iboe->mac[j - 1], ibdev->dev->caps.def_mac[j]);
- if (ib_register_device(&ibdev->ib_dev, NULL))
+ if (mlx4_ib_alloc_diag_counters(ibdev))
goto err_steer_free_bitmap;
+ if (ib_register_device(&ibdev->ib_dev, NULL))
+ goto err_diag_counters;
+
if (mlx4_ib_mad_init(ibdev))
goto err_reg;
@@ -2623,6 +2815,9 @@ err_mad:
err_reg:
ib_unregister_device(&ibdev->ib_dev);
+err_diag_counters:
+ mlx4_ib_diag_cleanup(ibdev);
+
err_steer_free_bitmap:
kfree(ibdev->ib_uc_qpns_bitmap);
@@ -2726,6 +2921,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
mlx4_ib_close_sriov(ibdev);
mlx4_ib_mad_cleanup(ibdev);
ib_unregister_device(&ibdev->ib_dev);
+ mlx4_ib_diag_cleanup(ibdev);
if (ibdev->iboe.nb.notifier_call) {
if (unregister_netdevice_notifier(&ibdev->iboe.nb))
pr_warn("failure unregistering notifier\n");
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index 29acda249612..7c5832ede4bd 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -549,6 +549,14 @@ struct mlx4_ib_counters {
u32 default_counter;
};
+#define MLX4_DIAG_COUNTERS_TYPES 2
+
+struct mlx4_ib_diag_counters {
+ const char **name;
+ u32 *offset;
+ u32 num_counters;
+};
+
struct mlx4_ib_dev {
struct ib_device ib_dev;
struct mlx4_dev *dev;
@@ -585,6 +593,7 @@ struct mlx4_ib_dev {
/* protect resources needed as part of reset flow */
spinlock_t reset_flow_resource_lock;
struct list_head qp_list;
+ struct mlx4_ib_diag_counters diag_counters[MLX4_DIAG_COUNTERS_TYPES];
};
struct ib_event_work {
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
index 9c0e67bd2ba7..308a358e5b46 100644
--- a/drivers/infiniband/hw/mlx5/cq.c
+++ b/drivers/infiniband/hw/mlx5/cq.c
@@ -424,6 +424,83 @@ static void get_sig_err_item(struct mlx5_sig_err_cqe *cqe,
item->key = be32_to_cpu(cqe->mkey);
}
+static void sw_send_comp(struct mlx5_ib_qp *qp, int num_entries,
+ struct ib_wc *wc, int *npolled)
+{
+ struct mlx5_ib_wq *wq;
+ unsigned int cur;
+ unsigned int idx;
+ int np;
+ int i;
+
+ wq = &qp->sq;
+ cur = wq->head - wq->tail;
+ np = *npolled;
+
+ if (cur == 0)
+ return;
+
+ for (i = 0; i < cur && np < num_entries; i++) {
+ idx = wq->last_poll & (wq->wqe_cnt - 1);
+ wc->wr_id = wq->wrid[idx];
+ wc->status = IB_WC_WR_FLUSH_ERR;
+ wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
+ wq->tail++;
+ np++;
+ wc->qp = &qp->ibqp;
+ wc++;
+ wq->last_poll = wq->w_list[idx].next;
+ }
+ *npolled = np;
+}
+
+static void sw_recv_comp(struct mlx5_ib_qp *qp, int num_entries,
+ struct ib_wc *wc, int *npolled)
+{
+ struct mlx5_ib_wq *wq;
+ unsigned int cur;
+ int np;
+ int i;
+
+ wq = &qp->rq;
+ cur = wq->head - wq->tail;
+ np = *npolled;
+
+ if (cur == 0)
+ return;
+
+ for (i = 0; i < cur && np < num_entries; i++) {
+ wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
+ wc->status = IB_WC_WR_FLUSH_ERR;
+ wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
+ wq->tail++;
+ np++;
+ wc->qp = &qp->ibqp;
+ wc++;
+ }
+ *npolled = np;
+}
+
+static void mlx5_ib_poll_sw_comp(struct mlx5_ib_cq *cq, int num_entries,
+ struct ib_wc *wc, int *npolled)
+{
+ struct mlx5_ib_qp *qp;
+
+ *npolled = 0;
+ /* Find uncompleted WQEs belonging to that cq and retrun mmics ones */
+ list_for_each_entry(qp, &cq->list_send_qp, cq_send_list) {
+ sw_send_comp(qp, num_entries, wc + *npolled, npolled);
+ if (*npolled >= num_entries)
+ return;
+ }
+
+ list_for_each_entry(qp, &cq->list_recv_qp, cq_recv_list) {
+ sw_recv_comp(qp, num_entries, wc + *npolled, npolled);
+ if (*npolled >= num_entries)
+ return;
+ }
+}
+
static int mlx5_poll_one(struct mlx5_ib_cq *cq,
struct mlx5_ib_qp **cur_qp,
struct ib_wc *wc)
@@ -594,12 +671,18 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
{
struct mlx5_ib_cq *cq = to_mcq(ibcq);
struct mlx5_ib_qp *cur_qp = NULL;
+ struct mlx5_ib_dev *dev = to_mdev(cq->ibcq.device);
+ struct mlx5_core_dev *mdev = dev->mdev;
unsigned long flags;
int soft_polled = 0;
int npolled;
int err = 0;
spin_lock_irqsave(&cq->lock, flags);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ mlx5_ib_poll_sw_comp(cq, num_entries, wc, &npolled);
+ goto out;
+ }
if (unlikely(!list_empty(&cq->wc_list)))
soft_polled = poll_soft_wc(cq, num_entries, wc);
@@ -612,7 +695,7 @@ int mlx5_ib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
if (npolled)
mlx5_cq_set_ci(&cq->mcq);
-
+out:
spin_unlock_irqrestore(&cq->lock, flags);
if (err == 0 || err == -EAGAIN)
@@ -843,6 +926,8 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
cq->resize_buf = NULL;
cq->resize_umem = NULL;
cq->create_flags = attr->flags;
+ INIT_LIST_HEAD(&cq->list_send_qp);
+ INIT_LIST_HEAD(&cq->list_recv_qp);
if (context) {
err = create_cq_user(dev, udata, context, cq, entries,
diff --git a/drivers/infiniband/hw/mlx5/gsi.c b/drivers/infiniband/hw/mlx5/gsi.c
index 53e03c8ede79..79e6309460dc 100644
--- a/drivers/infiniband/hw/mlx5/gsi.c
+++ b/drivers/infiniband/hw/mlx5/gsi.c
@@ -69,15 +69,6 @@ static bool mlx5_ib_deth_sqpn_cap(struct mlx5_ib_dev *dev)
return MLX5_CAP_GEN(dev->mdev, set_deth_sqpn);
}
-static u32 next_outstanding(struct mlx5_ib_gsi_qp *gsi, u32 index)
-{
- return ++index % gsi->cap.max_send_wr;
-}
-
-#define for_each_outstanding_wr(gsi, index) \
- for (index = gsi->outstanding_ci; index != gsi->outstanding_pi; \
- index = next_outstanding(gsi, index))
-
/* Call with gsi->lock locked */
static void generate_completions(struct mlx5_ib_gsi_qp *gsi)
{
@@ -85,8 +76,9 @@ static void generate_completions(struct mlx5_ib_gsi_qp *gsi)
struct mlx5_ib_gsi_wr *wr;
u32 index;
- for_each_outstanding_wr(gsi, index) {
- wr = &gsi->outstanding_wrs[index];
+ for (index = gsi->outstanding_ci; index != gsi->outstanding_pi;
+ index++) {
+ wr = &gsi->outstanding_wrs[index % gsi->cap.max_send_wr];
if (!wr->completed)
break;
@@ -430,8 +422,9 @@ static int mlx5_ib_add_outstanding_wr(struct mlx5_ib_gsi_qp *gsi,
return -ENOMEM;
}
- gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi];
- gsi->outstanding_pi = next_outstanding(gsi, gsi->outstanding_pi);
+ gsi_wr = &gsi->outstanding_wrs[gsi->outstanding_pi %
+ gsi->cap.max_send_wr];
+ gsi->outstanding_pi++;
if (!wc) {
memset(&gsi_wr->wc, 0, sizeof(gsi_wr->wc));
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index dad63f038bb8..a84bb766fc62 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -42,11 +42,13 @@
#include <asm/pat.h>
#endif
#include <linux/sched.h>
+#include <linux/delay.h>
#include <rdma/ib_user_verbs.h>
#include <rdma/ib_addr.h>
#include <rdma/ib_cache.h>
#include <linux/mlx5/port.h>
#include <linux/mlx5/vport.h>
+#include <linux/list.h>
#include <rdma/ib_smi.h>
#include <rdma/ib_umem.h>
#include <linux/in.h>
@@ -457,8 +459,17 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
int max_rq_sg;
int max_sq_sg;
u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
+ struct mlx5_ib_query_device_resp resp = {};
+ size_t resp_len;
+ u64 max_tso;
- if (uhw->inlen || uhw->outlen)
+ resp_len = sizeof(resp.comp_mask) + sizeof(resp.response_length);
+ if (uhw->outlen && uhw->outlen < resp_len)
+ return -EINVAL;
+ else
+ resp.response_length = resp_len;
+
+ if (uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))
return -EINVAL;
memset(props, 0, sizeof(*props));
@@ -511,10 +522,21 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
if (MLX5_CAP_GEN(mdev, block_lb_mc))
props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
- if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&
- (MLX5_CAP_ETH(dev->mdev, csum_cap)))
+ if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads)) {
+ if (MLX5_CAP_ETH(mdev, csum_cap))
props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
+ if (field_avail(typeof(resp), tso_caps, uhw->outlen)) {
+ max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);
+ if (max_tso) {
+ resp.tso_caps.max_tso = 1 << max_tso;
+ resp.tso_caps.supported_qpts |=
+ 1 << IB_QPT_RAW_PACKET;
+ resp.response_length += sizeof(resp.tso_caps);
+ }
+ }
+ }
+
if (MLX5_CAP_GEN(mdev, ipoib_basic_offloads)) {
props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
props->device_cap_flags |= IB_DEVICE_UD_TSO;
@@ -576,6 +598,13 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
if (!mlx5_core_is_pf(mdev))
props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION;
+ if (uhw->outlen) {
+ err = ib_copy_to_udata(uhw, &resp, resp.response_length);
+
+ if (err)
+ return err;
+ }
+
return 0;
}
@@ -983,6 +1012,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
goto out_uars;
}
+ INIT_LIST_HEAD(&context->vma_private_list);
INIT_LIST_HEAD(&context->db_page_list);
mutex_init(&context->db_page_mutex);
@@ -992,6 +1022,11 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
if (field_avail(typeof(resp), cqe_version, udata->outlen))
resp.response_length += sizeof(resp.cqe_version);
+ if (field_avail(typeof(resp), cmds_supp_uhw, udata->outlen)) {
+ resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE;
+ resp.response_length += sizeof(resp.cmds_supp_uhw);
+ }
+
/*
* We don't want to expose information from the PCI bar that is located
* after 4096 bytes, so if the arch only supports larger pages, let's
@@ -1006,8 +1041,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
offsetof(struct mlx5_init_seg, internal_timer_h) %
PAGE_SIZE;
resp.response_length += sizeof(resp.hca_core_clock_offset) +
- sizeof(resp.reserved2) +
- sizeof(resp.reserved3);
+ sizeof(resp.reserved2);
}
err = ib_copy_to_udata(udata, &resp, resp.response_length);
@@ -1086,6 +1120,125 @@ static int get_index(unsigned long offset)
return get_arg(offset);
}
+static void mlx5_ib_vma_open(struct vm_area_struct *area)
+{
+ /* vma_open is called when a new VMA is created on top of our VMA. This
+ * is done through either mremap flow or split_vma (usually due to
+ * mlock, madvise, munmap, etc.) We do not support a clone of the VMA,
+ * as this VMA is strongly hardware related. Therefore we set the
+ * vm_ops of the newly created/cloned VMA to NULL, to prevent it from
+ * calling us again and trying to do incorrect actions. We assume that
+ * the original VMA size is exactly a single page, and therefore all
+ * "splitting" operation will not happen to it.
+ */
+ area->vm_ops = NULL;
+}
+
+static void mlx5_ib_vma_close(struct vm_area_struct *area)
+{
+ struct mlx5_ib_vma_private_data *mlx5_ib_vma_priv_data;
+
+ /* It's guaranteed that all VMAs opened on a FD are closed before the
+ * file itself is closed, therefore no sync is needed with the regular
+ * closing flow. (e.g. mlx5 ib_dealloc_ucontext)
+ * However need a sync with accessing the vma as part of
+ * mlx5_ib_disassociate_ucontext.
+ * The close operation is usually called under mm->mmap_sem except when
+ * process is exiting.
+ * The exiting case is handled explicitly as part of
+ * mlx5_ib_disassociate_ucontext.
+ */
+ mlx5_ib_vma_priv_data = (struct mlx5_ib_vma_private_data *)area->vm_private_data;
+
+ /* setting the vma context pointer to null in the mlx5_ib driver's
+ * private data, to protect a race condition in
+ * mlx5_ib_disassociate_ucontext().
+ */
+ mlx5_ib_vma_priv_data->vma = NULL;
+ list_del(&mlx5_ib_vma_priv_data->list);
+ kfree(mlx5_ib_vma_priv_data);
+}
+
+static const struct vm_operations_struct mlx5_ib_vm_ops = {
+ .open = mlx5_ib_vma_open,
+ .close = mlx5_ib_vma_close
+};
+
+static int mlx5_ib_set_vma_data(struct vm_area_struct *vma,
+ struct mlx5_ib_ucontext *ctx)
+{
+ struct mlx5_ib_vma_private_data *vma_prv;
+ struct list_head *vma_head = &ctx->vma_private_list;
+
+ vma_prv = kzalloc(sizeof(*vma_prv), GFP_KERNEL);
+ if (!vma_prv)
+ return -ENOMEM;
+
+ vma_prv->vma = vma;
+ vma->vm_private_data = vma_prv;
+ vma->vm_ops = &mlx5_ib_vm_ops;
+
+ list_add(&vma_prv->list, vma_head);
+
+ return 0;
+}
+
+static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext)
+{
+ int ret;
+ struct vm_area_struct *vma;
+ struct mlx5_ib_vma_private_data *vma_private, *n;
+ struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
+ struct task_struct *owning_process = NULL;
+ struct mm_struct *owning_mm = NULL;
+
+ owning_process = get_pid_task(ibcontext->tgid, PIDTYPE_PID);
+ if (!owning_process)
+ return;
+
+ owning_mm = get_task_mm(owning_process);
+ if (!owning_mm) {
+ pr_info("no mm, disassociate ucontext is pending task termination\n");
+ while (1) {
+ put_task_struct(owning_process);
+ usleep_range(1000, 2000);
+ owning_process = get_pid_task(ibcontext->tgid,
+ PIDTYPE_PID);
+ if (!owning_process ||
+ owning_process->state == TASK_DEAD) {
+ pr_info("disassociate ucontext done, task was terminated\n");
+ /* in case task was dead need to release the
+ * task struct.
+ */
+ if (owning_process)
+ put_task_struct(owning_process);
+ return;
+ }
+ }
+ }
+
+ /* need to protect from a race on closing the vma as part of
+ * mlx5_ib_vma_close.
+ */
+ down_read(&owning_mm->mmap_sem);
+ list_for_each_entry_safe(vma_private, n, &context->vma_private_list,
+ list) {
+ vma = vma_private->vma;
+ ret = zap_vma_ptes(vma, vma->vm_start,
+ PAGE_SIZE);
+ WARN_ONCE(ret, "%s: zap_vma_ptes failed", __func__);
+ /* context going to be destroyed, should
+ * not access ops any more.
+ */
+ vma->vm_ops = NULL;
+ list_del(&vma_private->list);
+ kfree(vma_private);
+ }
+ up_read(&owning_mm->mmap_sem);
+ mmput(owning_mm);
+ put_task_struct(owning_process);
+}
+
static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
{
switch (cmd) {
@@ -1101,8 +1254,10 @@ static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
}
static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
- struct vm_area_struct *vma, struct mlx5_uuar_info *uuari)
+ struct vm_area_struct *vma,
+ struct mlx5_ib_ucontext *context)
{
+ struct mlx5_uuar_info *uuari = &context->uuari;
int err;
unsigned long idx;
phys_addr_t pfn, pa;
@@ -1152,14 +1307,13 @@ static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
mlx5_ib_dbg(dev, "mapped %s at 0x%lx, PA %pa\n", mmap_cmd2str(cmd),
vma->vm_start, &pa);
- return 0;
+ return mlx5_ib_set_vma_data(vma, context);
}
static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
{
struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
- struct mlx5_uuar_info *uuari = &context->uuari;
unsigned long command;
phys_addr_t pfn;
@@ -1168,7 +1322,7 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
case MLX5_IB_MMAP_WC_PAGE:
case MLX5_IB_MMAP_NC_PAGE:
case MLX5_IB_MMAP_REGULAR_PAGE:
- return uar_mmap(dev, command, vma, uuari);
+ return uar_mmap(dev, command, vma, context);
case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES:
return -ENOSYS;
@@ -1331,6 +1485,32 @@ static int parse_flow_attr(u32 *match_c, u32 *match_v,
&ib_spec->ipv4.val.dst_ip,
sizeof(ib_spec->ipv4.val.dst_ip));
break;
+ case IB_FLOW_SPEC_IPV6:
+ if (ib_spec->size != sizeof(ib_spec->ipv6))
+ return -EINVAL;
+
+ MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+ ethertype, 0xffff);
+ MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+ ethertype, ETH_P_IPV6);
+
+ memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+ src_ipv4_src_ipv6.ipv6_layout.ipv6),
+ &ib_spec->ipv6.mask.src_ip,
+ sizeof(ib_spec->ipv6.mask.src_ip));
+ memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+ src_ipv4_src_ipv6.ipv6_layout.ipv6),
+ &ib_spec->ipv6.val.src_ip,
+ sizeof(ib_spec->ipv6.val.src_ip));
+ memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+ dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+ &ib_spec->ipv6.mask.dst_ip,
+ sizeof(ib_spec->ipv6.mask.dst_ip));
+ memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+ dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
+ &ib_spec->ipv6.val.dst_ip,
+ sizeof(ib_spec->ipv6.val.dst_ip));
+ break;
case IB_FLOW_SPEC_TCP:
if (ib_spec->size != sizeof(ib_spec->tcp_udp))
return -EINVAL;
@@ -1801,15 +1981,6 @@ static ssize_t show_hca(struct device *device, struct device_attribute *attr,
return sprintf(buf, "MT%d\n", dev->mdev->pdev->device);
}
-static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct mlx5_ib_dev *dev =
- container_of(device, struct mlx5_ib_dev, ib_dev.dev);
- return sprintf(buf, "%d.%d.%04d\n", fw_rev_maj(dev->mdev),
- fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
-}
-
static ssize_t show_rev(struct device *device, struct device_attribute *attr,
char *buf)
{
@@ -1828,7 +1999,6 @@ static ssize_t show_board(struct device *device, struct device_attribute *attr,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static DEVICE_ATTR(fw_pages, S_IRUGO, show_fw_pages, NULL);
@@ -1836,7 +2006,6 @@ static DEVICE_ATTR(reg_pages, S_IRUGO, show_reg_pages, NULL);
static struct device_attribute *mlx5_class_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id,
&dev_attr_fw_pages,
@@ -1854,6 +2023,65 @@ static void pkey_change_handler(struct work_struct *work)
mutex_unlock(&ports->devr->mutex);
}
+static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev)
+{
+ struct mlx5_ib_qp *mqp;
+ struct mlx5_ib_cq *send_mcq, *recv_mcq;
+ struct mlx5_core_cq *mcq;
+ struct list_head cq_armed_list;
+ unsigned long flags_qp;
+ unsigned long flags_cq;
+ unsigned long flags;
+
+ INIT_LIST_HEAD(&cq_armed_list);
+
+ /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/
+ spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags);
+ list_for_each_entry(mqp, &ibdev->qp_list, qps_list) {
+ spin_lock_irqsave(&mqp->sq.lock, flags_qp);
+ if (mqp->sq.tail != mqp->sq.head) {
+ send_mcq = to_mcq(mqp->ibqp.send_cq);
+ spin_lock_irqsave(&send_mcq->lock, flags_cq);
+ if (send_mcq->mcq.comp &&
+ mqp->ibqp.send_cq->comp_handler) {
+ if (!send_mcq->mcq.reset_notify_added) {
+ send_mcq->mcq.reset_notify_added = 1;
+ list_add_tail(&send_mcq->mcq.reset_notify,
+ &cq_armed_list);
+ }
+ }
+ spin_unlock_irqrestore(&send_mcq->lock, flags_cq);
+ }
+ spin_unlock_irqrestore(&mqp->sq.lock, flags_qp);
+ spin_lock_irqsave(&mqp->rq.lock, flags_qp);
+ /* no handling is needed for SRQ */
+ if (!mqp->ibqp.srq) {
+ if (mqp->rq.tail != mqp->rq.head) {
+ recv_mcq = to_mcq(mqp->ibqp.recv_cq);
+ spin_lock_irqsave(&recv_mcq->lock, flags_cq);
+ if (recv_mcq->mcq.comp &&
+ mqp->ibqp.recv_cq->comp_handler) {
+ if (!recv_mcq->mcq.reset_notify_added) {
+ recv_mcq->mcq.reset_notify_added = 1;
+ list_add_tail(&recv_mcq->mcq.reset_notify,
+ &cq_armed_list);
+ }
+ }
+ spin_unlock_irqrestore(&recv_mcq->lock,
+ flags_cq);
+ }
+ }
+ spin_unlock_irqrestore(&mqp->rq.lock, flags_qp);
+ }
+ /*At that point all inflight post send were put to be executed as of we
+ * lock/unlock above locks Now need to arm all involved CQs.
+ */
+ list_for_each_entry(mcq, &cq_armed_list, reset_notify) {
+ mcq->comp(mcq);
+ }
+ spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags);
+}
+
static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
enum mlx5_dev_event event, unsigned long param)
{
@@ -1866,6 +2094,7 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
case MLX5_DEV_EVENT_SYS_ERROR:
ibdev->ib_active = false;
ibev.event = IB_EVENT_DEVICE_FATAL;
+ mlx5_ib_handle_internal_error(ibdev);
break;
case MLX5_DEV_EVENT_PORT_UP:
@@ -2272,6 +2501,15 @@ static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_str(struct ib_device *ibdev, char *str,
+ size_t str_len)
+{
+ struct mlx5_ib_dev *dev =
+ container_of(ibdev, struct mlx5_ib_dev, ib_dev);
+ snprintf(str, str_len, "%d.%d.%04d", fw_rev_maj(dev->mdev),
+ fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
+}
+
static int mlx5_enable_roce(struct mlx5_ib_dev *dev)
{
int err;
@@ -2298,6 +2536,113 @@ static void mlx5_disable_roce(struct mlx5_ib_dev *dev)
unregister_netdevice_notifier(&dev->roce.nb);
}
+static void mlx5_ib_dealloc_q_counters(struct mlx5_ib_dev *dev)
+{
+ unsigned int i;
+
+ for (i = 0; i < dev->num_ports; i++)
+ mlx5_core_dealloc_q_counter(dev->mdev,
+ dev->port[i].q_cnt_id);
+}
+
+static int mlx5_ib_alloc_q_counters(struct mlx5_ib_dev *dev)
+{
+ int i;
+ int ret;
+
+ for (i = 0; i < dev->num_ports; i++) {
+ ret = mlx5_core_alloc_q_counter(dev->mdev,
+ &dev->port[i].q_cnt_id);
+ if (ret) {
+ mlx5_ib_warn(dev,
+ "couldn't allocate queue counter for port %d, err %d\n",
+ i + 1, ret);
+ goto dealloc_counters;
+ }
+ }
+
+ return 0;
+
+dealloc_counters:
+ while (--i >= 0)
+ mlx5_core_dealloc_q_counter(dev->mdev,
+ dev->port[i].q_cnt_id);
+
+ return ret;
+}
+
+static const char * const names[] = {
+ "rx_write_requests",
+ "rx_read_requests",
+ "rx_atomic_requests",
+ "out_of_buffer",
+ "out_of_sequence",
+ "duplicate_request",
+ "rnr_nak_retry_err",
+ "packet_seq_err",
+ "implied_nak_seq_err",
+ "local_ack_timeout_err",
+};
+
+static const size_t stats_offsets[] = {
+ MLX5_BYTE_OFF(query_q_counter_out, rx_write_requests),
+ MLX5_BYTE_OFF(query_q_counter_out, rx_read_requests),
+ MLX5_BYTE_OFF(query_q_counter_out, rx_atomic_requests),
+ MLX5_BYTE_OFF(query_q_counter_out, out_of_buffer),
+ MLX5_BYTE_OFF(query_q_counter_out, out_of_sequence),
+ MLX5_BYTE_OFF(query_q_counter_out, duplicate_request),
+ MLX5_BYTE_OFF(query_q_counter_out, rnr_nak_retry_err),
+ MLX5_BYTE_OFF(query_q_counter_out, packet_seq_err),
+ MLX5_BYTE_OFF(query_q_counter_out, implied_nak_seq_err),
+ MLX5_BYTE_OFF(query_q_counter_out, local_ack_timeout_err),
+};
+
+static struct rdma_hw_stats *mlx5_ib_alloc_hw_stats(struct ib_device *ibdev,
+ u8 port_num)
+{
+ BUILD_BUG_ON(ARRAY_SIZE(names) != ARRAY_SIZE(stats_offsets));
+
+ /* We support only per port stats */
+ if (port_num == 0)
+ return NULL;
+
+ return rdma_alloc_hw_stats_struct(names, ARRAY_SIZE(names),
+ RDMA_HW_STATS_DEFAULT_LIFESPAN);
+}
+
+static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
+ struct rdma_hw_stats *stats,
+ u8 port, int index)
+{
+ struct mlx5_ib_dev *dev = to_mdev(ibdev);
+ int outlen = MLX5_ST_SZ_BYTES(query_q_counter_out);
+ void *out;
+ __be32 val;
+ int ret;
+ int i;
+
+ if (!port || !stats)
+ return -ENOSYS;
+
+ out = mlx5_vzalloc(outlen);
+ if (!out)
+ return -ENOMEM;
+
+ ret = mlx5_core_query_q_counter(dev->mdev,
+ dev->port[port - 1].q_cnt_id, 0,
+ out, outlen);
+ if (ret)
+ goto free;
+
+ for (i = 0; i < ARRAY_SIZE(names); i++) {
+ val = *(__be32 *)(out + stats_offsets[i]);
+ stats->value[i] = (u64)be32_to_cpu(val);
+ }
+free:
+ kvfree(out);
+ return ARRAY_SIZE(names);
+}
+
static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
{
struct mlx5_ib_dev *dev;
@@ -2320,10 +2665,15 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->mdev = mdev;
+ dev->port = kcalloc(MLX5_CAP_GEN(mdev, num_ports), sizeof(*dev->port),
+ GFP_KERNEL);
+ if (!dev->port)
+ goto err_dealloc;
+
rwlock_init(&dev->roce.netdev_lock);
err = get_port_caps(dev);
if (err)
- goto err_dealloc;
+ goto err_free_port;
if (mlx5_use_mad_ifc(dev))
get_ext_port_caps(dev);
@@ -2418,6 +2768,7 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.map_mr_sg = mlx5_ib_map_mr_sg;
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
dev->ib_dev.get_port_immutable = mlx5_port_immutable;
+ dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
if (mlx5_core_is_pf(mdev)) {
dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
@@ -2425,6 +2776,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.set_vf_guid = mlx5_ib_set_vf_guid;
}
+ dev->ib_dev.disassociate_ucontext = mlx5_ib_disassociate_ucontext;
+
mlx5_ib_internal_fill_odp_caps(dev);
if (MLX5_CAP_GEN(mdev, imaicl)) {
@@ -2435,6 +2788,12 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
(1ull << IB_USER_VERBS_CMD_DEALLOC_MW);
}
+ if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt) &&
+ MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) {
+ dev->ib_dev.get_hw_stats = mlx5_ib_get_hw_stats;
+ dev->ib_dev.alloc_hw_stats = mlx5_ib_alloc_hw_stats;
+ }
+
if (MLX5_CAP_GEN(mdev, xrc)) {
dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd;
dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd;
@@ -2447,9 +2806,19 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
IB_LINK_LAYER_ETHERNET) {
dev->ib_dev.create_flow = mlx5_ib_create_flow;
dev->ib_dev.destroy_flow = mlx5_ib_destroy_flow;
+ dev->ib_dev.create_wq = mlx5_ib_create_wq;
+ dev->ib_dev.modify_wq = mlx5_ib_modify_wq;
+ dev->ib_dev.destroy_wq = mlx5_ib_destroy_wq;
+ dev->ib_dev.create_rwq_ind_table = mlx5_ib_create_rwq_ind_table;
+ dev->ib_dev.destroy_rwq_ind_table = mlx5_ib_destroy_rwq_ind_table;
dev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_CREATE_FLOW) |
- (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW);
+ (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW) |
+ (1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
+ (1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
+ (1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
+ (1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) |
+ (1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL);
}
err = init_node_data(dev);
if (err)
@@ -2457,6 +2826,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
mutex_init(&dev->flow_db.lock);
mutex_init(&dev->cap_mask_mutex);
+ INIT_LIST_HEAD(&dev->qp_list);
+ spin_lock_init(&dev->reset_flow_resource_lock);
if (ll == IB_LINK_LAYER_ETHERNET) {
err = mlx5_enable_roce(dev);
@@ -2472,10 +2843,14 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
if (err)
goto err_rsrc;
- err = ib_register_device(&dev->ib_dev, NULL);
+ err = mlx5_ib_alloc_q_counters(dev);
if (err)
goto err_odp;
+ err = ib_register_device(&dev->ib_dev, NULL);
+ if (err)
+ goto err_q_cnt;
+
err = create_umr_res(dev);
if (err)
goto err_dev;
@@ -2497,6 +2872,9 @@ err_umrc:
err_dev:
ib_unregister_device(&dev->ib_dev);
+err_q_cnt:
+ mlx5_ib_dealloc_q_counters(dev);
+
err_odp:
mlx5_ib_odp_remove_one(dev);
@@ -2507,6 +2885,9 @@ err_disable_roce:
if (ll == IB_LINK_LAYER_ETHERNET)
mlx5_disable_roce(dev);
+err_free_port:
+ kfree(dev->port);
+
err_dealloc:
ib_dealloc_device((struct ib_device *)dev);
@@ -2519,11 +2900,13 @@ static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev, 1);
ib_unregister_device(&dev->ib_dev);
+ mlx5_ib_dealloc_q_counters(dev);
destroy_umrc_res(dev);
mlx5_ib_odp_remove_one(dev);
destroy_dev_resources(&dev->devr);
if (ll == IB_LINK_LAYER_ETHERNET)
mlx5_disable_roce(dev);
+ kfree(dev->port);
ib_dealloc_device(&dev->ib_dev);
}
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index c4a9825828bc..372385d0f993 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -105,6 +105,11 @@ enum {
MLX5_CQE_VERSION_V1,
};
+struct mlx5_ib_vma_private_data {
+ struct list_head list;
+ struct vm_area_struct *vma;
+};
+
struct mlx5_ib_ucontext {
struct ib_ucontext ibucontext;
struct list_head db_page_list;
@@ -116,6 +121,7 @@ struct mlx5_ib_ucontext {
u8 cqe_version;
/* Transport Domain number */
u32 tdn;
+ struct list_head vma_private_list;
};
static inline struct mlx5_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext)
@@ -217,12 +223,41 @@ struct mlx5_ib_wq {
void *qend;
};
+struct mlx5_ib_rwq {
+ struct ib_wq ibwq;
+ u32 rqn;
+ u32 rq_num_pas;
+ u32 log_rq_stride;
+ u32 log_rq_size;
+ u32 rq_page_offset;
+ u32 log_page_size;
+ struct ib_umem *umem;
+ size_t buf_size;
+ unsigned int page_shift;
+ int create_type;
+ struct mlx5_db db;
+ u32 user_index;
+ u32 wqe_count;
+ u32 wqe_shift;
+ int wq_sig;
+};
+
enum {
MLX5_QP_USER,
MLX5_QP_KERNEL,
MLX5_QP_EMPTY
};
+enum {
+ MLX5_WQ_USER,
+ MLX5_WQ_KERNEL
+};
+
+struct mlx5_ib_rwq_ind_table {
+ struct ib_rwq_ind_table ib_rwq_ind_tbl;
+ u32 rqtn;
+};
+
/*
* Connect-IB can trigger up to four concurrent pagefaults
* per-QP.
@@ -266,6 +301,10 @@ struct mlx5_ib_qp_trans {
u8 resp_depth;
};
+struct mlx5_ib_rss_qp {
+ u32 tirn;
+};
+
struct mlx5_ib_rq {
struct mlx5_ib_qp_base base;
struct mlx5_ib_wq *rq;
@@ -294,6 +333,7 @@ struct mlx5_ib_qp {
union {
struct mlx5_ib_qp_trans trans_qp;
struct mlx5_ib_raw_packet_qp raw_packet_qp;
+ struct mlx5_ib_rss_qp rss_qp;
};
struct mlx5_buf buf;
@@ -340,6 +380,9 @@ struct mlx5_ib_qp {
spinlock_t disable_page_faults_lock;
struct mlx5_ib_pfault pagefaults[MLX5_IB_PAGEFAULT_CONTEXTS];
#endif
+ struct list_head qps_list;
+ struct list_head cq_recv_list;
+ struct list_head cq_send_list;
};
struct mlx5_ib_cq_buf {
@@ -401,6 +444,8 @@ struct mlx5_ib_cq {
struct mlx5_ib_cq_buf *resize_buf;
struct ib_umem *resize_umem;
int cqe_size;
+ struct list_head list_send_qp;
+ struct list_head list_recv_qp;
u32 create_flags;
struct list_head wc_list;
enum ib_cq_notify_flags notify_flags;
@@ -546,6 +591,10 @@ struct mlx5_ib_resources {
struct mutex mutex;
};
+struct mlx5_ib_port {
+ u16 q_cnt_id;
+};
+
struct mlx5_roce {
/* Protect mlx5_ib_get_netdev from invoking dev_hold() with a NULL
* netdev pointer
@@ -581,6 +630,11 @@ struct mlx5_ib_dev {
struct srcu_struct mr_srcu;
#endif
struct mlx5_ib_flow_db flow_db;
+ /* protect resources needed as part of reset flow */
+ spinlock_t reset_flow_resource_lock;
+ struct list_head qp_list;
+ /* Array with num_ports elements */
+ struct mlx5_ib_port *port;
};
static inline struct mlx5_ib_cq *to_mibcq(struct mlx5_core_cq *mcq)
@@ -628,6 +682,16 @@ static inline struct mlx5_ib_qp *to_mqp(struct ib_qp *ibqp)
return container_of(ibqp, struct mlx5_ib_qp, ibqp);
}
+static inline struct mlx5_ib_rwq *to_mrwq(struct ib_wq *ibwq)
+{
+ return container_of(ibwq, struct mlx5_ib_rwq, ibwq);
+}
+
+static inline struct mlx5_ib_rwq_ind_table *to_mrwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl)
+{
+ return container_of(ib_rwq_ind_tbl, struct mlx5_ib_rwq_ind_table, ib_rwq_ind_tbl);
+}
+
static inline struct mlx5_ib_srq *to_mibsrq(struct mlx5_core_srq *msrq)
{
return container_of(msrq, struct mlx5_ib_srq, msrq);
@@ -762,6 +826,16 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev);
int mlx5_mr_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift);
int mlx5_ib_check_mr_status(struct ib_mr *ibmr, u32 check_mask,
struct ib_mr_status *mr_status);
+struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr,
+ struct ib_udata *udata);
+int mlx5_ib_destroy_wq(struct ib_wq *wq);
+int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
+ u32 wq_attr_mask, struct ib_udata *udata);
+struct ib_rwq_ind_table *mlx5_ib_create_rwq_ind_table(struct ib_device *device,
+ struct ib_rwq_ind_table_init_attr *init_attr,
+ struct ib_udata *udata);
+int mlx5_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *wq_ind_table);
#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
extern struct workqueue_struct *mlx5_ib_page_fault_wq;
diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
index 8cf2ce50511f..4b021305c321 100644
--- a/drivers/infiniband/hw/mlx5/mr.c
+++ b/drivers/infiniband/hw/mlx5/mr.c
@@ -1193,12 +1193,16 @@ error:
static int unreg_umr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
{
+ struct mlx5_core_dev *mdev = dev->mdev;
struct umr_common *umrc = &dev->umrc;
struct mlx5_ib_umr_context umr_context;
struct mlx5_umr_wr umrwr = {};
struct ib_send_wr *bad;
int err;
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+ return 0;
+
mlx5_ib_init_umr_context(&umr_context);
umrwr.wr.wr_cqe = &umr_context.cqe;
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index ce0a7ab35a22..0dd7d93cac95 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -77,6 +77,10 @@ struct mlx5_wqe_eth_pad {
u8 rsvd0[16];
};
+static void get_cqs(enum ib_qp_type qp_type,
+ struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
+ struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq);
+
static int is_qp0(enum ib_qp_type qp_type)
{
return qp_type == IB_QPT_SMI;
@@ -609,6 +613,11 @@ static int to_mlx5_st(enum ib_qp_type type)
}
}
+static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq,
+ struct mlx5_ib_cq *recv_cq);
+static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq,
+ struct mlx5_ib_cq *recv_cq);
+
static int uuarn_to_uar_index(struct mlx5_uuar_info *uuari, int uuarn)
{
return uuari->uars[uuarn / MLX5_BF_REGS_PER_PAGE].index;
@@ -649,6 +658,71 @@ err_umem:
return err;
}
+static void destroy_user_rq(struct ib_pd *pd, struct mlx5_ib_rwq *rwq)
+{
+ struct mlx5_ib_ucontext *context;
+
+ context = to_mucontext(pd->uobject->context);
+ mlx5_ib_db_unmap_user(context, &rwq->db);
+ if (rwq->umem)
+ ib_umem_release(rwq->umem);
+}
+
+static int create_user_rq(struct mlx5_ib_dev *dev, struct ib_pd *pd,
+ struct mlx5_ib_rwq *rwq,
+ struct mlx5_ib_create_wq *ucmd)
+{
+ struct mlx5_ib_ucontext *context;
+ int page_shift = 0;
+ int npages;
+ u32 offset = 0;
+ int ncont = 0;
+ int err;
+
+ if (!ucmd->buf_addr)
+ return -EINVAL;
+
+ context = to_mucontext(pd->uobject->context);
+ rwq->umem = ib_umem_get(pd->uobject->context, ucmd->buf_addr,
+ rwq->buf_size, 0, 0);
+ if (IS_ERR(rwq->umem)) {
+ mlx5_ib_dbg(dev, "umem_get failed\n");
+ err = PTR_ERR(rwq->umem);
+ return err;
+ }
+
+ mlx5_ib_cont_pages(rwq->umem, ucmd->buf_addr, &npages, &page_shift,
+ &ncont, NULL);
+ err = mlx5_ib_get_buf_offset(ucmd->buf_addr, page_shift,
+ &rwq->rq_page_offset);
+ if (err) {
+ mlx5_ib_warn(dev, "bad offset\n");
+ goto err_umem;
+ }
+
+ rwq->rq_num_pas = ncont;
+ rwq->page_shift = page_shift;
+ rwq->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
+ rwq->wq_sig = !!(ucmd->flags & MLX5_WQ_FLAG_SIGNATURE);
+
+ mlx5_ib_dbg(dev, "addr 0x%llx, size %zd, npages %d, page_shift %d, ncont %d, offset %d\n",
+ (unsigned long long)ucmd->buf_addr, rwq->buf_size,
+ npages, page_shift, ncont, offset);
+
+ err = mlx5_ib_db_map_user(context, ucmd->db_addr, &rwq->db);
+ if (err) {
+ mlx5_ib_dbg(dev, "map failed\n");
+ goto err_umem;
+ }
+
+ rwq->create_type = MLX5_WQ_USER;
+ return 0;
+
+err_umem:
+ ib_umem_release(rwq->umem);
+ return err;
+}
+
static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
struct mlx5_ib_qp *qp, struct ib_udata *udata,
struct ib_qp_init_attr *attr,
@@ -1201,6 +1275,187 @@ static void raw_packet_qp_copy_info(struct mlx5_ib_qp *qp,
rq->doorbell = &qp->db;
}
+static void destroy_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
+{
+ mlx5_core_destroy_tir(dev->mdev, qp->rss_qp.tirn);
+}
+
+static int create_rss_raw_qp_tir(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
+ struct ib_pd *pd,
+ struct ib_qp_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct ib_uobject *uobj = pd->uobject;
+ struct ib_ucontext *ucontext = uobj->context;
+ struct mlx5_ib_ucontext *mucontext = to_mucontext(ucontext);
+ struct mlx5_ib_create_qp_resp resp = {};
+ int inlen;
+ int err;
+ u32 *in;
+ void *tirc;
+ void *hfso;
+ u32 selected_fields = 0;
+ size_t min_resp_len;
+ u32 tdn = mucontext->tdn;
+ struct mlx5_ib_create_qp_rss ucmd = {};
+ size_t required_cmd_sz;
+
+ if (init_attr->qp_type != IB_QPT_RAW_PACKET)
+ return -EOPNOTSUPP;
+
+ if (init_attr->create_flags || init_attr->send_cq)
+ return -EINVAL;
+
+ min_resp_len = offsetof(typeof(resp), uuar_index) + sizeof(resp.uuar_index);
+ if (udata->outlen < min_resp_len)
+ return -EINVAL;
+
+ required_cmd_sz = offsetof(typeof(ucmd), reserved1) + sizeof(ucmd.reserved1);
+ if (udata->inlen < required_cmd_sz) {
+ mlx5_ib_dbg(dev, "invalid inlen\n");
+ return -EINVAL;
+ }
+
+ if (udata->inlen > sizeof(ucmd) &&
+ !ib_is_udata_cleared(udata, sizeof(ucmd),
+ udata->inlen - sizeof(ucmd))) {
+ mlx5_ib_dbg(dev, "inlen is not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return -EFAULT;
+ }
+
+ if (ucmd.comp_mask) {
+ mlx5_ib_dbg(dev, "invalid comp mask\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (memchr_inv(ucmd.reserved, 0, sizeof(ucmd.reserved)) || ucmd.reserved1) {
+ mlx5_ib_dbg(dev, "invalid reserved\n");
+ return -EOPNOTSUPP;
+ }
+
+ err = ib_copy_to_udata(udata, &resp, min_resp_len);
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return -EINVAL;
+ }
+
+ inlen = MLX5_ST_SZ_BYTES(create_tir_in);
+ in = mlx5_vzalloc(inlen);
+ if (!in)
+ return -ENOMEM;
+
+ tirc = MLX5_ADDR_OF(create_tir_in, in, ctx);
+ MLX5_SET(tirc, tirc, disp_type,
+ MLX5_TIRC_DISP_TYPE_INDIRECT);
+ MLX5_SET(tirc, tirc, indirect_table,
+ init_attr->rwq_ind_tbl->ind_tbl_num);
+ MLX5_SET(tirc, tirc, transport_domain, tdn);
+
+ hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
+ switch (ucmd.rx_hash_function) {
+ case MLX5_RX_HASH_FUNC_TOEPLITZ:
+ {
+ void *rss_key = MLX5_ADDR_OF(tirc, tirc, rx_hash_toeplitz_key);
+ size_t len = MLX5_FLD_SZ_BYTES(tirc, rx_hash_toeplitz_key);
+
+ if (len != ucmd.rx_key_len) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ MLX5_SET(tirc, tirc, rx_hash_fn, MLX5_RX_HASH_FN_TOEPLITZ);
+ MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
+ memcpy(rss_key, ucmd.rx_hash_key, len);
+ break;
+ }
+ default:
+ err = -EOPNOTSUPP;
+ goto err;
+ }
+
+ if (!ucmd.rx_hash_fields_mask) {
+ /* special case when this TIR serves as steering entry without hashing */
+ if (!init_attr->rwq_ind_tbl->log_ind_tbl_size)
+ goto create_tir;
+ err = -EINVAL;
+ goto err;
+ }
+
+ if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4)) &&
+ ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ /* If none of IPV4 & IPV6 SRC/DST was set - this bit field is ignored */
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4))
+ MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+ MLX5_L3_PROT_TYPE_IPV4);
+ else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
+ MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+ MLX5_L3_PROT_TYPE_IPV6);
+
+ if (((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP)) &&
+ ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ /* If none of TCP & UDP SRC/DST was set - this bit field is ignored */
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP))
+ MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+ MLX5_L4_PROT_TYPE_TCP);
+ else if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
+ MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+ MLX5_L4_PROT_TYPE_UDP);
+
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV4) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_IPV6))
+ selected_fields |= MLX5_HASH_FIELD_SEL_SRC_IP;
+
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV4) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_IPV6))
+ selected_fields |= MLX5_HASH_FIELD_SEL_DST_IP;
+
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_TCP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_SRC_PORT_UDP))
+ selected_fields |= MLX5_HASH_FIELD_SEL_L4_SPORT;
+
+ if ((ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_TCP) ||
+ (ucmd.rx_hash_fields_mask & MLX5_RX_HASH_DST_PORT_UDP))
+ selected_fields |= MLX5_HASH_FIELD_SEL_L4_DPORT;
+
+ MLX5_SET(rx_hash_field_select, hfso, selected_fields, selected_fields);
+
+create_tir:
+ err = mlx5_core_create_tir(dev->mdev, in, inlen, &qp->rss_qp.tirn);
+
+ if (err)
+ goto err;
+
+ kvfree(in);
+ /* qpn is reserved for that QP */
+ qp->trans_qp.base.mqp.qpn = 0;
+ return 0;
+
+err:
+ kvfree(in);
+ return err;
+}
+
static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, struct mlx5_ib_qp *qp)
@@ -1211,6 +1466,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
struct mlx5_ib_create_qp_resp resp;
struct mlx5_create_qp_mbox_in *in;
struct mlx5_ib_create_qp ucmd;
+ struct mlx5_ib_cq *send_cq;
+ struct mlx5_ib_cq *recv_cq;
+ unsigned long flags;
int inlen = sizeof(*in);
int err;
u32 uidx = MLX5_IB_DEFAULT_UIDX;
@@ -1227,6 +1485,14 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
spin_lock_init(&qp->sq.lock);
spin_lock_init(&qp->rq.lock);
+ if (init_attr->rwq_ind_tbl) {
+ if (!udata)
+ return -ENOSYS;
+
+ err = create_rss_raw_qp_tir(dev, qp, pd, init_attr, udata);
+ return err;
+ }
+
if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
if (!MLX5_CAP_GEN(mdev, block_lb_mc)) {
mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n");
@@ -1460,6 +1726,23 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
base->container_mibqp = qp;
base->mqp.event = mlx5_ib_qp_event;
+ get_cqs(init_attr->qp_type, init_attr->send_cq, init_attr->recv_cq,
+ &send_cq, &recv_cq);
+ spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
+ mlx5_ib_lock_cqs(send_cq, recv_cq);
+ /* Maintain device to QPs access, needed for further handling via reset
+ * flow
+ */
+ list_add_tail(&qp->qps_list, &dev->qp_list);
+ /* Maintain CQ to QPs access, needed for further handling via reset flow
+ */
+ if (send_cq)
+ list_add_tail(&qp->cq_send_list, &send_cq->list_send_qp);
+ if (recv_cq)
+ list_add_tail(&qp->cq_recv_list, &recv_cq->list_recv_qp);
+ mlx5_ib_unlock_cqs(send_cq, recv_cq);
+ spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
+
return 0;
err_create:
@@ -1478,23 +1761,23 @@ static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *recv
if (send_cq) {
if (recv_cq) {
if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
- spin_lock_irq(&send_cq->lock);
+ spin_lock(&send_cq->lock);
spin_lock_nested(&recv_cq->lock,
SINGLE_DEPTH_NESTING);
} else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
- spin_lock_irq(&send_cq->lock);
+ spin_lock(&send_cq->lock);
__acquire(&recv_cq->lock);
} else {
- spin_lock_irq(&recv_cq->lock);
+ spin_lock(&recv_cq->lock);
spin_lock_nested(&send_cq->lock,
SINGLE_DEPTH_NESTING);
}
} else {
- spin_lock_irq(&send_cq->lock);
+ spin_lock(&send_cq->lock);
__acquire(&recv_cq->lock);
}
} else if (recv_cq) {
- spin_lock_irq(&recv_cq->lock);
+ spin_lock(&recv_cq->lock);
__acquire(&send_cq->lock);
} else {
__acquire(&send_cq->lock);
@@ -1509,21 +1792,21 @@ static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq, struct mlx5_ib_cq *re
if (recv_cq) {
if (send_cq->mcq.cqn < recv_cq->mcq.cqn) {
spin_unlock(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ spin_unlock(&send_cq->lock);
} else if (send_cq->mcq.cqn == recv_cq->mcq.cqn) {
__release(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ spin_unlock(&send_cq->lock);
} else {
spin_unlock(&send_cq->lock);
- spin_unlock_irq(&recv_cq->lock);
+ spin_unlock(&recv_cq->lock);
}
} else {
__release(&recv_cq->lock);
- spin_unlock_irq(&send_cq->lock);
+ spin_unlock(&send_cq->lock);
}
} else if (recv_cq) {
__release(&send_cq->lock);
- spin_unlock_irq(&recv_cq->lock);
+ spin_unlock(&recv_cq->lock);
} else {
__release(&recv_cq->lock);
__release(&send_cq->lock);
@@ -1535,17 +1818,18 @@ static struct mlx5_ib_pd *get_pd(struct mlx5_ib_qp *qp)
return to_mpd(qp->ibqp.pd);
}
-static void get_cqs(struct mlx5_ib_qp *qp,
+static void get_cqs(enum ib_qp_type qp_type,
+ struct ib_cq *ib_send_cq, struct ib_cq *ib_recv_cq,
struct mlx5_ib_cq **send_cq, struct mlx5_ib_cq **recv_cq)
{
- switch (qp->ibqp.qp_type) {
+ switch (qp_type) {
case IB_QPT_XRC_TGT:
*send_cq = NULL;
*recv_cq = NULL;
break;
case MLX5_IB_QPT_REG_UMR:
case IB_QPT_XRC_INI:
- *send_cq = to_mcq(qp->ibqp.send_cq);
+ *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
*recv_cq = NULL;
break;
@@ -1557,8 +1841,8 @@ static void get_cqs(struct mlx5_ib_qp *qp,
case IB_QPT_RAW_IPV6:
case IB_QPT_RAW_ETHERTYPE:
case IB_QPT_RAW_PACKET:
- *send_cq = to_mcq(qp->ibqp.send_cq);
- *recv_cq = to_mcq(qp->ibqp.recv_cq);
+ *send_cq = ib_send_cq ? to_mcq(ib_send_cq) : NULL;
+ *recv_cq = ib_recv_cq ? to_mcq(ib_recv_cq) : NULL;
break;
case IB_QPT_MAX:
@@ -1577,8 +1861,14 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
struct mlx5_ib_cq *send_cq, *recv_cq;
struct mlx5_ib_qp_base *base = &qp->trans_qp.base;
struct mlx5_modify_qp_mbox_in *in;
+ unsigned long flags;
int err;
+ if (qp->ibqp.rwq_ind_tbl) {
+ destroy_rss_raw_qp_tir(dev, qp);
+ return;
+ }
+
base = qp->ibqp.qp_type == IB_QPT_RAW_PACKET ?
&qp->raw_packet_qp.rq.base :
&qp->trans_qp.base;
@@ -1602,17 +1892,28 @@ static void destroy_qp_common(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
base->mqp.qpn);
}
- get_cqs(qp, &send_cq, &recv_cq);
+ get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
+ &send_cq, &recv_cq);
+
+ spin_lock_irqsave(&dev->reset_flow_resource_lock, flags);
+ mlx5_ib_lock_cqs(send_cq, recv_cq);
+ /* del from lists under both locks above to protect reset flow paths */
+ list_del(&qp->qps_list);
+ if (send_cq)
+ list_del(&qp->cq_send_list);
+
+ if (recv_cq)
+ list_del(&qp->cq_recv_list);
if (qp->create_type == MLX5_QP_KERNEL) {
- mlx5_ib_lock_cqs(send_cq, recv_cq);
__mlx5_ib_cq_clean(recv_cq, base->mqp.qpn,
qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL);
if (send_cq != recv_cq)
__mlx5_ib_cq_clean(send_cq, base->mqp.qpn,
NULL);
- mlx5_ib_unlock_cqs(send_cq, recv_cq);
}
+ mlx5_ib_unlock_cqs(send_cq, recv_cq);
+ spin_unlock_irqrestore(&dev->reset_flow_resource_lock, flags);
if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
destroy_raw_packet_qp(dev, qp);
@@ -2300,7 +2601,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
}
pd = get_pd(qp);
- get_cqs(qp, &send_cq, &recv_cq);
+ get_cqs(qp->ibqp.qp_type, qp->ibqp.send_cq, qp->ibqp.recv_cq,
+ &send_cq, &recv_cq);
context->flags_pd = cpu_to_be32(pd ? pd->pdn : to_mpd(dev->devr.p0)->pdn);
context->cqn_send = send_cq ? cpu_to_be32(send_cq->mcq.cqn) : 0;
@@ -2349,6 +2651,15 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
else
sqd_event = 0;
+ if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
+ u8 port_num = (attr_mask & IB_QP_PORT ? attr->port_num :
+ qp->port) - 1;
+ struct mlx5_ib_port *mibport = &dev->port[port_num];
+
+ context->qp_counter_set_usr_page |=
+ cpu_to_be32((u32)(mibport->q_cnt_id) << 24);
+ }
+
if (!ibqp->uobject && cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT)
context->sq_crq_size |= cpu_to_be16(1 << 4);
@@ -2439,6 +2750,9 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int port;
enum rdma_link_layer ll = IB_LINK_LAYER_UNSPECIFIED;
+ if (ibqp->rwq_ind_tbl)
+ return -ENOSYS;
+
if (unlikely(ibqp->qp_type == IB_QPT_GSI))
return mlx5_ib_gsi_modify_qp(ibqp, attr, attr_mask);
@@ -3397,6 +3711,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
{
struct mlx5_wqe_ctrl_seg *ctrl = NULL; /* compiler warning */
struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
+ struct mlx5_core_dev *mdev = dev->mdev;
struct mlx5_ib_qp *qp;
struct mlx5_ib_mr *mr;
struct mlx5_wqe_data_seg *dpseg;
@@ -3424,6 +3739,13 @@ int mlx5_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
spin_lock_irqsave(&qp->sq.lock, flags);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ err = -EIO;
+ *bad_wr = wr;
+ nreq = 0;
+ goto out;
+ }
+
for (nreq = 0; wr; nreq++, wr = wr->next) {
if (unlikely(wr->opcode >= ARRAY_SIZE(mlx5_ib_opcode))) {
mlx5_ib_warn(dev, "\n");
@@ -3725,6 +4047,8 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
struct mlx5_ib_qp *qp = to_mqp(ibqp);
struct mlx5_wqe_data_seg *scat;
struct mlx5_rwqe_sig *sig;
+ struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
+ struct mlx5_core_dev *mdev = dev->mdev;
unsigned long flags;
int err = 0;
int nreq;
@@ -3736,6 +4060,13 @@ int mlx5_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
spin_lock_irqsave(&qp->rq.lock, flags);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ err = -EIO;
+ *bad_wr = wr;
+ nreq = 0;
+ goto out;
+ }
+
ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
for (nreq = 0; wr; nreq++, wr = wr->next) {
@@ -4055,6 +4386,9 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
int err = 0;
u8 raw_packet_qp_state;
+ if (ibqp->rwq_ind_tbl)
+ return -ENOSYS;
+
if (unlikely(ibqp->qp_type == IB_QPT_GSI))
return mlx5_ib_gsi_query_qp(ibqp, qp_attr, qp_attr_mask,
qp_init_attr);
@@ -4164,3 +4498,322 @@ int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
return 0;
}
+
+static int create_rq(struct mlx5_ib_rwq *rwq, struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr)
+{
+ struct mlx5_ib_dev *dev;
+ __be64 *rq_pas0;
+ void *in;
+ void *rqc;
+ void *wq;
+ int inlen;
+ int err;
+
+ dev = to_mdev(pd->device);
+
+ inlen = MLX5_ST_SZ_BYTES(create_rq_in) + sizeof(u64) * rwq->rq_num_pas;
+ in = mlx5_vzalloc(inlen);
+ if (!in)
+ return -ENOMEM;
+
+ rqc = MLX5_ADDR_OF(create_rq_in, in, ctx);
+ MLX5_SET(rqc, rqc, mem_rq_type,
+ MLX5_RQC_MEM_RQ_TYPE_MEMORY_RQ_INLINE);
+ MLX5_SET(rqc, rqc, user_index, rwq->user_index);
+ MLX5_SET(rqc, rqc, cqn, to_mcq(init_attr->cq)->mcq.cqn);
+ MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST);
+ MLX5_SET(rqc, rqc, flush_in_error_en, 1);
+ wq = MLX5_ADDR_OF(rqc, rqc, wq);
+ MLX5_SET(wq, wq, wq_type, MLX5_WQ_TYPE_CYCLIC);
+ MLX5_SET(wq, wq, end_padding_mode, MLX5_WQ_END_PAD_MODE_ALIGN);
+ MLX5_SET(wq, wq, log_wq_stride, rwq->log_rq_stride);
+ MLX5_SET(wq, wq, log_wq_sz, rwq->log_rq_size);
+ MLX5_SET(wq, wq, pd, to_mpd(pd)->pdn);
+ MLX5_SET(wq, wq, page_offset, rwq->rq_page_offset);
+ MLX5_SET(wq, wq, log_wq_pg_sz, rwq->log_page_size);
+ MLX5_SET(wq, wq, wq_signature, rwq->wq_sig);
+ MLX5_SET64(wq, wq, dbr_addr, rwq->db.dma);
+ rq_pas0 = (__be64 *)MLX5_ADDR_OF(wq, wq, pas);
+ mlx5_ib_populate_pas(dev, rwq->umem, rwq->page_shift, rq_pas0, 0);
+ err = mlx5_core_create_rq(dev->mdev, in, inlen, &rwq->rqn);
+ kvfree(in);
+ return err;
+}
+
+static int set_user_rq_size(struct mlx5_ib_dev *dev,
+ struct ib_wq_init_attr *wq_init_attr,
+ struct mlx5_ib_create_wq *ucmd,
+ struct mlx5_ib_rwq *rwq)
+{
+ /* Sanity check RQ size before proceeding */
+ if (wq_init_attr->max_wr > (1 << MLX5_CAP_GEN(dev->mdev, log_max_wq_sz)))
+ return -EINVAL;
+
+ if (!ucmd->rq_wqe_count)
+ return -EINVAL;
+
+ rwq->wqe_count = ucmd->rq_wqe_count;
+ rwq->wqe_shift = ucmd->rq_wqe_shift;
+ rwq->buf_size = (rwq->wqe_count << rwq->wqe_shift);
+ rwq->log_rq_stride = rwq->wqe_shift;
+ rwq->log_rq_size = ilog2(rwq->wqe_count);
+ return 0;
+}
+
+static int prepare_user_rq(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr,
+ struct ib_udata *udata,
+ struct mlx5_ib_rwq *rwq)
+{
+ struct mlx5_ib_dev *dev = to_mdev(pd->device);
+ struct mlx5_ib_create_wq ucmd = {};
+ int err;
+ size_t required_cmd_sz;
+
+ required_cmd_sz = offsetof(typeof(ucmd), reserved) + sizeof(ucmd.reserved);
+ if (udata->inlen < required_cmd_sz) {
+ mlx5_ib_dbg(dev, "invalid inlen\n");
+ return -EINVAL;
+ }
+
+ if (udata->inlen > sizeof(ucmd) &&
+ !ib_is_udata_cleared(udata, sizeof(ucmd),
+ udata->inlen - sizeof(ucmd))) {
+ mlx5_ib_dbg(dev, "inlen is not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen))) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return -EFAULT;
+ }
+
+ if (ucmd.comp_mask) {
+ mlx5_ib_dbg(dev, "invalid comp mask\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (ucmd.reserved) {
+ mlx5_ib_dbg(dev, "invalid reserved\n");
+ return -EOPNOTSUPP;
+ }
+
+ err = set_user_rq_size(dev, init_attr, &ucmd, rwq);
+ if (err) {
+ mlx5_ib_dbg(dev, "err %d\n", err);
+ return err;
+ }
+
+ err = create_user_rq(dev, pd, rwq, &ucmd);
+ if (err) {
+ mlx5_ib_dbg(dev, "err %d\n", err);
+ if (err)
+ return err;
+ }
+
+ rwq->user_index = ucmd.user_index;
+ return 0;
+}
+
+struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct mlx5_ib_dev *dev;
+ struct mlx5_ib_rwq *rwq;
+ struct mlx5_ib_create_wq_resp resp = {};
+ size_t min_resp_len;
+ int err;
+
+ if (!udata)
+ return ERR_PTR(-ENOSYS);
+
+ min_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
+ if (udata->outlen && udata->outlen < min_resp_len)
+ return ERR_PTR(-EINVAL);
+
+ dev = to_mdev(pd->device);
+ switch (init_attr->wq_type) {
+ case IB_WQT_RQ:
+ rwq = kzalloc(sizeof(*rwq), GFP_KERNEL);
+ if (!rwq)
+ return ERR_PTR(-ENOMEM);
+ err = prepare_user_rq(pd, init_attr, udata, rwq);
+ if (err)
+ goto err;
+ err = create_rq(rwq, pd, init_attr);
+ if (err)
+ goto err_user_rq;
+ break;
+ default:
+ mlx5_ib_dbg(dev, "unsupported wq type %d\n",
+ init_attr->wq_type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ rwq->ibwq.wq_num = rwq->rqn;
+ rwq->ibwq.state = IB_WQS_RESET;
+ if (udata->outlen) {
+ resp.response_length = offsetof(typeof(resp), response_length) +
+ sizeof(resp.response_length);
+ err = ib_copy_to_udata(udata, &resp, resp.response_length);
+ if (err)
+ goto err_copy;
+ }
+
+ return &rwq->ibwq;
+
+err_copy:
+ mlx5_core_destroy_rq(dev->mdev, rwq->rqn);
+err_user_rq:
+ destroy_user_rq(pd, rwq);
+err:
+ kfree(rwq);
+ return ERR_PTR(err);
+}
+
+int mlx5_ib_destroy_wq(struct ib_wq *wq)
+{
+ struct mlx5_ib_dev *dev = to_mdev(wq->device);
+ struct mlx5_ib_rwq *rwq = to_mrwq(wq);
+
+ mlx5_core_destroy_rq(dev->mdev, rwq->rqn);
+ destroy_user_rq(wq->pd, rwq);
+ kfree(rwq);
+
+ return 0;
+}
+
+struct ib_rwq_ind_table *mlx5_ib_create_rwq_ind_table(struct ib_device *device,
+ struct ib_rwq_ind_table_init_attr *init_attr,
+ struct ib_udata *udata)
+{
+ struct mlx5_ib_dev *dev = to_mdev(device);
+ struct mlx5_ib_rwq_ind_table *rwq_ind_tbl;
+ int sz = 1 << init_attr->log_ind_tbl_size;
+ struct mlx5_ib_create_rwq_ind_tbl_resp resp = {};
+ size_t min_resp_len;
+ int inlen;
+ int err;
+ int i;
+ u32 *in;
+ void *rqtc;
+
+ if (udata->inlen > 0 &&
+ !ib_is_udata_cleared(udata, 0,
+ udata->inlen))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ min_resp_len = offsetof(typeof(resp), reserved) + sizeof(resp.reserved);
+ if (udata->outlen && udata->outlen < min_resp_len)
+ return ERR_PTR(-EINVAL);
+
+ rwq_ind_tbl = kzalloc(sizeof(*rwq_ind_tbl), GFP_KERNEL);
+ if (!rwq_ind_tbl)
+ return ERR_PTR(-ENOMEM);
+
+ inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
+ in = mlx5_vzalloc(inlen);
+ if (!in) {
+ err = -ENOMEM;
+ goto err;
+ }
+
+ rqtc = MLX5_ADDR_OF(create_rqt_in, in, rqt_context);
+
+ MLX5_SET(rqtc, rqtc, rqt_actual_size, sz);
+ MLX5_SET(rqtc, rqtc, rqt_max_size, sz);
+
+ for (i = 0; i < sz; i++)
+ MLX5_SET(rqtc, rqtc, rq_num[i], init_attr->ind_tbl[i]->wq_num);
+
+ err = mlx5_core_create_rqt(dev->mdev, in, inlen, &rwq_ind_tbl->rqtn);
+ kvfree(in);
+
+ if (err)
+ goto err;
+
+ rwq_ind_tbl->ib_rwq_ind_tbl.ind_tbl_num = rwq_ind_tbl->rqtn;
+ if (udata->outlen) {
+ resp.response_length = offsetof(typeof(resp), response_length) +
+ sizeof(resp.response_length);
+ err = ib_copy_to_udata(udata, &resp, resp.response_length);
+ if (err)
+ goto err_copy;
+ }
+
+ return &rwq_ind_tbl->ib_rwq_ind_tbl;
+
+err_copy:
+ mlx5_core_destroy_rqt(dev->mdev, rwq_ind_tbl->rqtn);
+err:
+ kfree(rwq_ind_tbl);
+ return ERR_PTR(err);
+}
+
+int mlx5_ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *ib_rwq_ind_tbl)
+{
+ struct mlx5_ib_rwq_ind_table *rwq_ind_tbl = to_mrwq_ind_table(ib_rwq_ind_tbl);
+ struct mlx5_ib_dev *dev = to_mdev(ib_rwq_ind_tbl->device);
+
+ mlx5_core_destroy_rqt(dev->mdev, rwq_ind_tbl->rqtn);
+
+ kfree(rwq_ind_tbl);
+ return 0;
+}
+
+int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr,
+ u32 wq_attr_mask, struct ib_udata *udata)
+{
+ struct mlx5_ib_dev *dev = to_mdev(wq->device);
+ struct mlx5_ib_rwq *rwq = to_mrwq(wq);
+ struct mlx5_ib_modify_wq ucmd = {};
+ size_t required_cmd_sz;
+ int curr_wq_state;
+ int wq_state;
+ int inlen;
+ int err;
+ void *rqc;
+ void *in;
+
+ required_cmd_sz = offsetof(typeof(ucmd), reserved) + sizeof(ucmd.reserved);
+ if (udata->inlen < required_cmd_sz)
+ return -EINVAL;
+
+ if (udata->inlen > sizeof(ucmd) &&
+ !ib_is_udata_cleared(udata, sizeof(ucmd),
+ udata->inlen - sizeof(ucmd)))
+ return -EOPNOTSUPP;
+
+ if (ib_copy_from_udata(&ucmd, udata, min(sizeof(ucmd), udata->inlen)))
+ return -EFAULT;
+
+ if (ucmd.comp_mask || ucmd.reserved)
+ return -EOPNOTSUPP;
+
+ inlen = MLX5_ST_SZ_BYTES(modify_rq_in);
+ in = mlx5_vzalloc(inlen);
+ if (!in)
+ return -ENOMEM;
+
+ rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
+
+ curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE) ?
+ wq_attr->curr_wq_state : wq->state;
+ wq_state = (wq_attr_mask & IB_WQ_STATE) ?
+ wq_attr->wq_state : curr_wq_state;
+ if (curr_wq_state == IB_WQS_ERR)
+ curr_wq_state = MLX5_RQC_STATE_ERR;
+ if (wq_state == IB_WQS_ERR)
+ wq_state = MLX5_RQC_STATE_ERR;
+ MLX5_SET(modify_rq_in, in, rq_state, curr_wq_state);
+ MLX5_SET(rqc, rqc, state, wq_state);
+
+ err = mlx5_core_modify_rq(dev->mdev, rwq->rqn, in, inlen);
+ kvfree(in);
+ if (!err)
+ rwq->ibwq.state = (wq_state == MLX5_RQC_STATE_ERR) ? IB_WQS_ERR : wq_state;
+
+ return err;
+}
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 3b2ddd64a371..ed6ac52355f1 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -74,14 +74,12 @@ static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type)
}
static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
- struct mlx5_create_srq_mbox_in **in,
- struct ib_udata *udata, int buf_size, int *inlen,
- int is_xrc)
+ struct mlx5_srq_attr *in,
+ struct ib_udata *udata, int buf_size)
{
struct mlx5_ib_dev *dev = to_mdev(pd->device);
struct mlx5_ib_create_srq ucmd = {};
size_t ucmdlen;
- void *xsrqc;
int err;
int npages;
int page_shift;
@@ -104,7 +102,7 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
udata->inlen - sizeof(ucmd)))
return -EINVAL;
- if (is_xrc) {
+ if (in->type == IB_SRQT_XRC) {
err = get_srq_user_index(to_mucontext(pd->uobject->context),
&ucmd, udata->inlen, &uidx);
if (err)
@@ -130,14 +128,13 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
goto err_umem;
}
- *inlen = sizeof(**in) + sizeof(*(*in)->pas) * ncont;
- *in = mlx5_vzalloc(*inlen);
- if (!(*in)) {
+ in->pas = mlx5_vzalloc(sizeof(*in->pas) * ncont);
+ if (!in->pas) {
err = -ENOMEM;
goto err_umem;
}
- mlx5_ib_populate_pas(dev, srq->umem, page_shift, (*in)->pas, 0);
+ mlx5_ib_populate_pas(dev, srq->umem, page_shift, in->pas, 0);
err = mlx5_ib_db_map_user(to_mucontext(pd->uobject->context),
ucmd.db_addr, &srq->db);
@@ -146,20 +143,16 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
goto err_in;
}
- (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
- (*in)->ctx.pgoff_cqn = cpu_to_be32(offset << 26);
-
- if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
- is_xrc){
- xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
- xrc_srq_context_entry);
- MLX5_SET(xrc_srqc, xsrqc, user_index, uidx);
- }
+ in->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
+ in->page_offset = offset;
+ if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1 &&
+ in->type == IB_SRQT_XRC)
+ in->user_index = uidx;
return 0;
err_in:
- kvfree(*in);
+ kvfree(in->pas);
err_umem:
ib_umem_release(srq->umem);
@@ -168,15 +161,13 @@ err_umem:
}
static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
- struct mlx5_create_srq_mbox_in **in, int buf_size,
- int *inlen, int is_xrc)
+ struct mlx5_srq_attr *in, int buf_size)
{
int err;
int i;
struct mlx5_wqe_srq_next_seg *next;
int page_shift;
int npages;
- void *xsrqc;
err = mlx5_db_alloc(dev->mdev, &srq->db);
if (err) {
@@ -204,13 +195,12 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
npages = DIV_ROUND_UP(srq->buf.npages, 1 << (page_shift - PAGE_SHIFT));
mlx5_ib_dbg(dev, "buf_size %d, page_shift %d, npages %d, calc npages %d\n",
buf_size, page_shift, srq->buf.npages, npages);
- *inlen = sizeof(**in) + sizeof(*(*in)->pas) * npages;
- *in = mlx5_vzalloc(*inlen);
- if (!*in) {
+ in->pas = mlx5_vzalloc(sizeof(*in->pas) * npages);
+ if (!in->pas) {
err = -ENOMEM;
goto err_buf;
}
- mlx5_fill_page_array(&srq->buf, (*in)->pas);
+ mlx5_fill_page_array(&srq->buf, in->pas);
srq->wrid = kmalloc(srq->msrq.max * sizeof(u64), GFP_KERNEL);
if (!srq->wrid) {
@@ -221,20 +211,15 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
}
srq->wq_sig = !!srq_signature;
- (*in)->ctx.log_pg_sz = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
-
- if ((MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1) &&
- is_xrc){
- xsrqc = MLX5_ADDR_OF(create_xrc_srq_in, *in,
- xrc_srq_context_entry);
- /* 0xffffff means we ask to work with cqe version 0 */
- MLX5_SET(xrc_srqc, xsrqc, user_index, MLX5_IB_DEFAULT_UIDX);
- }
+ in->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT;
+ if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1 &&
+ in->type == IB_SRQT_XRC)
+ in->user_index = MLX5_IB_DEFAULT_UIDX;
return 0;
err_in:
- kvfree(*in);
+ kvfree(in->pas);
err_buf:
mlx5_buf_free(dev->mdev, &srq->buf);
@@ -267,10 +252,7 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
int desc_size;
int buf_size;
int err;
- struct mlx5_create_srq_mbox_in *uninitialized_var(in);
- int uninitialized_var(inlen);
- int is_xrc;
- u32 flgs, xrcdn;
+ struct mlx5_srq_attr in = {0};
__u32 max_srq_wqes = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
/* Sanity check SRQ size before proceeding */
@@ -302,14 +284,10 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs,
srq->msrq.max_avail_gather);
- is_xrc = (init_attr->srq_type == IB_SRQT_XRC);
-
if (pd->uobject)
- err = create_srq_user(pd, srq, &in, udata, buf_size, &inlen,
- is_xrc);
+ err = create_srq_user(pd, srq, &in, udata, buf_size);
else
- err = create_srq_kernel(dev, srq, &in, buf_size, &inlen,
- is_xrc);
+ err = create_srq_kernel(dev, srq, &in, buf_size);
if (err) {
mlx5_ib_warn(dev, "create srq %s failed, err %d\n",
@@ -317,23 +295,23 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
goto err_srq;
}
- in->ctx.state_log_sz = ilog2(srq->msrq.max);
- flgs = ((srq->msrq.wqe_shift - 4) | (is_xrc << 5) | (srq->wq_sig << 7)) << 24;
- xrcdn = 0;
- if (is_xrc) {
- xrcdn = to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn;
- in->ctx.pgoff_cqn |= cpu_to_be32(to_mcq(init_attr->ext.xrc.cq)->mcq.cqn);
+ in.type = init_attr->srq_type;
+ in.log_size = ilog2(srq->msrq.max);
+ in.wqe_shift = srq->msrq.wqe_shift - 4;
+ if (srq->wq_sig)
+ in.flags |= MLX5_SRQ_FLAG_WQ_SIG;
+ if (init_attr->srq_type == IB_SRQT_XRC) {
+ in.xrcd = to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn;
+ in.cqn = to_mcq(init_attr->ext.xrc.cq)->mcq.cqn;
} else if (init_attr->srq_type == IB_SRQT_BASIC) {
- xrcdn = to_mxrcd(dev->devr.x0)->xrcdn;
- in->ctx.pgoff_cqn |= cpu_to_be32(to_mcq(dev->devr.c0)->mcq.cqn);
+ in.xrcd = to_mxrcd(dev->devr.x0)->xrcdn;
+ in.cqn = to_mcq(dev->devr.c0)->mcq.cqn;
}
- in->ctx.flags_xrcd = cpu_to_be32((flgs & 0xFF000000) | (xrcdn & 0xFFFFFF));
-
- in->ctx.pd = cpu_to_be32(to_mpd(pd)->pdn);
- in->ctx.db_record = cpu_to_be64(srq->db.dma);
- err = mlx5_core_create_srq(dev->mdev, &srq->msrq, in, inlen, is_xrc);
- kvfree(in);
+ in.pd = to_mpd(pd)->pdn;
+ in.db_record = srq->db.dma;
+ err = mlx5_core_create_srq(dev->mdev, &srq->msrq, &in);
+ kvfree(in.pas);
if (err) {
mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err);
goto err_usr_kern_srq;
@@ -401,7 +379,7 @@ int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
struct mlx5_ib_dev *dev = to_mdev(ibsrq->device);
struct mlx5_ib_srq *srq = to_msrq(ibsrq);
int ret;
- struct mlx5_query_srq_mbox_out *out;
+ struct mlx5_srq_attr *out;
out = kzalloc(sizeof(*out), GFP_KERNEL);
if (!out)
@@ -411,7 +389,7 @@ int mlx5_ib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *srq_attr)
if (ret)
goto out_box;
- srq_attr->srq_limit = be16_to_cpu(out->ctx.lwm);
+ srq_attr->srq_limit = out->lwm;
srq_attr->max_wr = srq->msrq.max - 1;
srq_attr->max_sge = srq->msrq.max_gs;
@@ -458,6 +436,8 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
struct mlx5_ib_srq *srq = to_msrq(ibsrq);
struct mlx5_wqe_srq_next_seg *next;
struct mlx5_wqe_data_seg *scat;
+ struct mlx5_ib_dev *dev = to_mdev(ibsrq->device);
+ struct mlx5_core_dev *mdev = dev->mdev;
unsigned long flags;
int err = 0;
int nreq;
@@ -465,6 +445,12 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
spin_lock_irqsave(&srq->lock, flags);
+ if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+ err = -EIO;
+ *bad_wr = wr;
+ goto out;
+ }
+
for (nreq = 0; wr; nreq++, wr = wr->next) {
if (unlikely(wr->num_sge > srq->msrq.max_gs)) {
err = -EINVAL;
@@ -507,7 +493,7 @@ int mlx5_ib_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
*srq->db.db = cpu_to_be32(srq->wqe_ctr);
}
-
+out:
spin_unlock_irqrestore(&srq->lock, flags);
return err;
diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h
index 61bc308bb802..188dac4301b5 100644
--- a/drivers/infiniband/hw/mlx5/user.h
+++ b/drivers/infiniband/hw/mlx5/user.h
@@ -46,6 +46,10 @@ enum {
MLX5_SRQ_FLAG_SIGNATURE = 1 << 0,
};
+enum {
+ MLX5_WQ_FLAG_SIGNATURE = 1 << 0,
+};
+
/* Increment this value if any changes that break userspace ABI
* compatibility are made.
@@ -79,6 +83,10 @@ enum mlx5_ib_alloc_ucontext_resp_mask {
MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET = 1UL << 0,
};
+enum mlx5_user_cmds_supp_uhw {
+ MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE = 1 << 0,
+};
+
struct mlx5_ib_alloc_ucontext_resp {
__u32 qp_tab_size;
__u32 bf_reg_size;
@@ -94,8 +102,8 @@ struct mlx5_ib_alloc_ucontext_resp {
__u32 comp_mask;
__u32 response_length;
__u8 cqe_version;
- __u8 reserved2;
- __u16 reserved3;
+ __u8 cmds_supp_uhw;
+ __u16 reserved2;
__u64 hca_core_clock_offset;
};
@@ -103,6 +111,22 @@ struct mlx5_ib_alloc_pd_resp {
__u32 pdn;
};
+struct mlx5_ib_tso_caps {
+ __u32 max_tso; /* Maximum tso payload size in bytes */
+
+ /* Corresponding bit will be set if qp type from
+ * 'enum ib_qp_type' is supported, e.g.
+ * supported_qpts |= 1 << IB_QPT_UD
+ */
+ __u32 supported_qpts;
+};
+
+struct mlx5_ib_query_device_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+ struct mlx5_ib_tso_caps tso_caps;
+};
+
struct mlx5_ib_create_cq {
__u64 buf_addr;
__u64 db_addr;
@@ -148,6 +172,40 @@ struct mlx5_ib_create_qp {
__u64 sq_buf_addr;
};
+/* RX Hash function flags */
+enum mlx5_rx_hash_function_flags {
+ MLX5_RX_HASH_FUNC_TOEPLITZ = 1 << 0,
+};
+
+/*
+ * RX Hash flags, these flags allows to set which incoming packet's field should
+ * participates in RX Hash. Each flag represent certain packet's field,
+ * when the flag is set the field that is represented by the flag will
+ * participate in RX Hash calculation.
+ * Note: *IPV4 and *IPV6 flags can't be enabled together on the same QP
+ * and *TCP and *UDP flags can't be enabled together on the same QP.
+*/
+enum mlx5_rx_hash_fields {
+ MLX5_RX_HASH_SRC_IPV4 = 1 << 0,
+ MLX5_RX_HASH_DST_IPV4 = 1 << 1,
+ MLX5_RX_HASH_SRC_IPV6 = 1 << 2,
+ MLX5_RX_HASH_DST_IPV6 = 1 << 3,
+ MLX5_RX_HASH_SRC_PORT_TCP = 1 << 4,
+ MLX5_RX_HASH_DST_PORT_TCP = 1 << 5,
+ MLX5_RX_HASH_SRC_PORT_UDP = 1 << 6,
+ MLX5_RX_HASH_DST_PORT_UDP = 1 << 7
+};
+
+struct mlx5_ib_create_qp_rss {
+ __u64 rx_hash_fields_mask; /* enum mlx5_rx_hash_fields */
+ __u8 rx_hash_function; /* enum mlx5_rx_hash_function_flags */
+ __u8 rx_key_len; /* valid only for Toeplitz */
+ __u8 reserved[6];
+ __u8 rx_hash_key[128]; /* valid only for Toeplitz */
+ __u32 comp_mask;
+ __u32 reserved1;
+};
+
struct mlx5_ib_create_qp_resp {
__u32 uuar_index;
};
@@ -159,6 +217,32 @@ struct mlx5_ib_alloc_mw {
__u16 reserved2;
};
+struct mlx5_ib_create_wq {
+ __u64 buf_addr;
+ __u64 db_addr;
+ __u32 rq_wqe_count;
+ __u32 rq_wqe_shift;
+ __u32 user_index;
+ __u32 flags;
+ __u32 comp_mask;
+ __u32 reserved;
+};
+
+struct mlx5_ib_create_wq_resp {
+ __u32 response_length;
+ __u32 reserved;
+};
+
+struct mlx5_ib_create_rwq_ind_tbl_resp {
+ __u32 response_length;
+ __u32 reserved;
+};
+
+struct mlx5_ib_modify_wq {
+ __u32 comp_mask;
+ __u32 reserved;
+};
+
static inline int get_qp_user_index(struct mlx5_ib_ucontext *ucontext,
struct mlx5_ib_create_qp *ucmd,
int inlen,
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 9866c35cc977..da2335f7f7c3 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -1081,16 +1081,6 @@ static ssize_t show_rev(struct device *device, struct device_attribute *attr,
return sprintf(buf, "%x\n", dev->rev_id);
}
-static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct mthca_dev *dev =
- container_of(device, struct mthca_dev, ib_dev.dev);
- return sprintf(buf, "%d.%d.%d\n", (int) (dev->fw_ver >> 32),
- (int) (dev->fw_ver >> 16) & 0xffff,
- (int) dev->fw_ver & 0xffff);
-}
-
static ssize_t show_hca(struct device *device, struct device_attribute *attr,
char *buf)
{
@@ -1120,13 +1110,11 @@ static ssize_t show_board(struct device *device, struct device_attribute *attr,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct device_attribute *mthca_dev_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id
};
@@ -1187,6 +1175,17 @@ static int mthca_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_str(struct ib_device *device, char *str,
+ size_t str_len)
+{
+ struct mthca_dev *dev =
+ container_of(device, struct mthca_dev, ib_dev);
+ snprintf(str, str_len, "%d.%d.%d",
+ (int) (dev->fw_ver >> 32),
+ (int) (dev->fw_ver >> 16) & 0xffff,
+ (int) dev->fw_ver & 0xffff);
+}
+
int mthca_register_device(struct mthca_dev *dev)
{
int ret;
@@ -1266,6 +1265,7 @@ int mthca_register_device(struct mthca_dev *dev)
dev->ib_dev.reg_user_mr = mthca_reg_user_mr;
dev->ib_dev.dereg_mr = mthca_dereg_mr;
dev->ib_dev.get_port_immutable = mthca_port_immutable;
+ dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
if (dev->mthca_flags & MTHCA_FLAG_FMR) {
dev->ib_dev.alloc_fmr = mthca_alloc_fmr;
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 74c6a9426047..6727af27c017 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -98,7 +98,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENOMEM;
mthca_err(mdev, "Couldn't allocate memory to save HCA "
"PCI header, aborting.\n");
- goto out;
+ goto put_dev;
}
for (i = 0; i < 64; ++i) {
@@ -108,7 +108,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENODEV;
mthca_err(mdev, "Couldn't save HCA "
"PCI header, aborting.\n");
- goto out;
+ goto free_hca;
}
}
@@ -121,7 +121,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENOMEM;
mthca_err(mdev, "Couldn't allocate memory to save HCA "
"bridge PCI header, aborting.\n");
- goto out;
+ goto free_hca;
}
for (i = 0; i < 64; ++i) {
@@ -131,7 +131,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENODEV;
mthca_err(mdev, "Couldn't save HCA bridge "
"PCI header, aborting.\n");
- goto out;
+ goto free_bh;
}
}
bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
@@ -139,7 +139,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENODEV;
mthca_err(mdev, "Couldn't locate HCA bridge "
"PCI-X capability, aborting.\n");
- goto out;
+ goto free_bh;
}
}
@@ -152,7 +152,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENOMEM;
mthca_err(mdev, "Couldn't map HCA reset register, "
"aborting.\n");
- goto out;
+ goto free_bh;
}
writel(MTHCA_RESET_VALUE, reset);
@@ -172,7 +172,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENODEV;
mthca_err(mdev, "Couldn't access HCA after reset, "
"aborting.\n");
- goto out;
+ goto free_bh;
}
if (v != 0xffffffff)
@@ -184,7 +184,7 @@ int mthca_reset(struct mthca_dev *mdev)
err = -ENODEV;
mthca_err(mdev, "PCI device did not come back after reset, "
"aborting.\n");
- goto out;
+ goto free_bh;
}
good:
@@ -195,14 +195,14 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA bridge Upstream "
"split transaction control, aborting.\n");
- goto out;
+ goto free_bh;
}
if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc,
bridge_header[(bridge_pcix_cap + 0xc) / 4])) {
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA bridge Downstream "
"split transaction control, aborting.\n");
- goto out;
+ goto free_bh;
}
/*
* Bridge control register is at 0x3e, so we'll
@@ -216,7 +216,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA bridge reg %x, "
"aborting.\n", i);
- goto out;
+ goto free_bh;
}
}
@@ -225,7 +225,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA bridge COMMAND, "
"aborting.\n");
- goto out;
+ goto free_bh;
}
}
@@ -235,7 +235,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA PCI-X "
"command register, aborting.\n");
- goto out;
+ goto free_bh;
}
}
@@ -246,7 +246,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA PCI Express "
"Device Control register, aborting.\n");
- goto out;
+ goto free_bh;
}
linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
if (pcie_capability_write_word(mdev->pdev, PCI_EXP_LNKCTL,
@@ -254,7 +254,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA PCI Express "
"Link control register, aborting.\n");
- goto out;
+ goto free_bh;
}
}
@@ -266,7 +266,7 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA reg %x, "
"aborting.\n", i);
- goto out;
+ goto free_bh;
}
}
@@ -275,14 +275,12 @@ good:
err = -ENODEV;
mthca_err(mdev, "Couldn't restore HCA COMMAND, "
"aborting.\n");
- goto out;
}
-
-out:
- if (bridge)
- pci_dev_put(bridge);
+free_bh:
kfree(bridge_header);
+free_hca:
kfree(hca_header);
-
+put_dev:
+ pci_dev_put(bridge);
return err;
}
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 464d6da5fe91..bd69125731c1 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -2606,23 +2606,6 @@ static ssize_t show_rev(struct device *dev, struct device_attribute *attr,
/**
- * show_fw_ver
- */
-static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct nes_ib_device *nesibdev =
- container_of(dev, struct nes_ib_device, ibdev.dev);
- struct nes_vnic *nesvnic = nesibdev->nesvnic;
-
- nes_debug(NES_DBG_INIT, "\n");
- return sprintf(buf, "%u.%u\n",
- (nesvnic->nesdev->nesadapter->firmware_version >> 16),
- (nesvnic->nesdev->nesadapter->firmware_version & 0x000000ff));
-}
-
-
-/**
* show_hca
*/
static ssize_t show_hca(struct device *dev, struct device_attribute *attr,
@@ -2645,13 +2628,11 @@ static ssize_t show_board(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
static struct device_attribute *nes_dev_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type,
&dev_attr_board_id
};
@@ -3703,6 +3684,19 @@ static int nes_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_str(struct ib_device *dev, char *str,
+ size_t str_len)
+{
+ struct nes_ib_device *nesibdev =
+ container_of(dev, struct nes_ib_device, ibdev);
+ struct nes_vnic *nesvnic = nesibdev->nesvnic;
+
+ nes_debug(NES_DBG_INIT, "\n");
+ snprintf(str, str_len, "%u.%u",
+ (nesvnic->nesdev->nesadapter->firmware_version >> 16),
+ (nesvnic->nesdev->nesadapter->firmware_version & 0x000000ff));
+}
+
/**
* nes_init_ofa_device
*/
@@ -3802,6 +3796,7 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
nesibdev->ibdev.iwcm->create_listen = nes_create_listen;
nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen;
nesibdev->ibdev.get_port_immutable = nes_port_immutable;
+ nesibdev->ibdev.get_dev_fw_str = get_dev_fw_str;
memcpy(nesibdev->ibdev.iwcm->ifname, netdev->name,
sizeof(nesibdev->ibdev.iwcm->ifname));
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 3d75f65ce87e..07d0c6c5b046 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -107,6 +107,14 @@ static int ocrdma_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void get_dev_fw_str(struct ib_device *device, char *str,
+ size_t str_len)
+{
+ struct ocrdma_dev *dev = get_ocrdma_dev(device);
+
+ snprintf(str, str_len, "%s", &dev->attr.fw_ver[0]);
+}
+
static int ocrdma_register_device(struct ocrdma_dev *dev)
{
strlcpy(dev->ibdev.name, "ocrdma%d", IB_DEVICE_NAME_MAX);
@@ -193,6 +201,7 @@ static int ocrdma_register_device(struct ocrdma_dev *dev)
dev->ibdev.process_mad = ocrdma_process_mad;
dev->ibdev.get_port_immutable = ocrdma_port_immutable;
+ dev->ibdev.get_dev_fw_str = get_dev_fw_str;
if (ocrdma_get_asic_type(dev) == OCRDMA_ASIC_GEN_SKH_R) {
dev->ibdev.uverbs_cmd_mask |=
@@ -262,14 +271,6 @@ static ssize_t show_rev(struct device *device, struct device_attribute *attr,
return scnprintf(buf, PAGE_SIZE, "0x%x\n", dev->nic_info.pdev->vendor);
}
-static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
- char *buf)
-{
- struct ocrdma_dev *dev = dev_get_drvdata(device);
-
- return scnprintf(buf, PAGE_SIZE, "%s\n", &dev->attr.fw_ver[0]);
-}
-
static ssize_t show_hca_type(struct device *device,
struct device_attribute *attr, char *buf)
{
@@ -279,12 +280,10 @@ static ssize_t show_hca_type(struct device *device,
}
static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
-static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
static DEVICE_ATTR(hca_type, S_IRUGO, show_hca_type, NULL);
static struct device_attribute *ocrdma_attributes[] = {
&dev_attr_hw_rev,
- &dev_attr_fw_ver,
&dev_attr_hca_type
};
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 575b737d9ef3..9cc0aae1d781 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -106,6 +106,49 @@ static u32 credit_table[31] = {
32768 /* 1E */
};
+const struct rvt_operation_params qib_post_parms[RVT_OPERATION_MAX] = {
+[IB_WR_RDMA_WRITE] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_RDMA_READ] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC,
+},
+
+[IB_WR_ATOMIC_CMP_AND_SWP] = {
+ .length = sizeof(struct ib_atomic_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE,
+},
+
+[IB_WR_ATOMIC_FETCH_AND_ADD] = {
+ .length = sizeof(struct ib_atomic_wr),
+ .qpt_support = BIT(IB_QPT_RC),
+ .flags = RVT_OPERATION_ATOMIC | RVT_OPERATION_ATOMIC_SGE,
+},
+
+[IB_WR_RDMA_WRITE_WITH_IMM] = {
+ .length = sizeof(struct ib_rdma_wr),
+ .qpt_support = BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_SEND] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) |
+ BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+[IB_WR_SEND_WITH_IMM] = {
+ .length = sizeof(struct ib_send_wr),
+ .qpt_support = BIT(IB_QPT_UD) | BIT(IB_QPT_SMI) | BIT(IB_QPT_GSI) |
+ BIT(IB_QPT_UC) | BIT(IB_QPT_RC),
+},
+
+};
+
static void get_map_page(struct rvt_qpn_table *qpt, struct rvt_qpn_map *map,
gfp_t gfp)
{
diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c
index 846e6c726df7..10d062561bd9 100644
--- a/drivers/infiniband/hw/qib/qib_ud.c
+++ b/drivers/infiniband/hw/qib/qib_ud.c
@@ -169,8 +169,12 @@ static void qib_ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe)
}
if (ah_attr->ah_flags & IB_AH_GRH) {
- qib_copy_sge(&qp->r_sge, &ah_attr->grh,
- sizeof(struct ib_grh), 1);
+ struct ib_grh grh;
+ struct ib_global_route grd = ah_attr->grh;
+
+ qib_make_grh(ibp, &grh, &grd, 0, 0);
+ qib_copy_sge(&qp->r_sge, &grh,
+ sizeof(grh), 1);
wc.wc_flags |= IB_WC_GRH;
} else
qib_skip_sge(&qp->r_sge, sizeof(struct ib_grh), 1);
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index cbf6200e6afc..fd1dfbce5539 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -1582,6 +1582,8 @@ static void qib_fill_device_attr(struct qib_devdata *dd)
rdi->dparms.props.max_total_mcast_qp_attach =
rdi->dparms.props.max_mcast_qp_attach *
rdi->dparms.props.max_mcast_grp;
+ /* post send table */
+ dd->verbs_dev.rdi.post_parms = qib_post_parms;
}
/**
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index 4f878151f81f..736ced684842 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -497,4 +497,6 @@ extern unsigned int ib_qib_max_srq_wrs;
extern const u32 ib_qib_rnr_table[];
+extern const struct rvt_operation_params qib_post_parms[];
+
#endif /* QIB_VERBS_H */
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index 565c881a44ba..c229b9f4a52d 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -331,6 +331,21 @@ static int usnic_port_immutable(struct ib_device *ibdev, u8 port_num,
return 0;
}
+static void usnic_get_dev_fw_str(struct ib_device *device,
+ char *str,
+ size_t str_len)
+{
+ struct usnic_ib_dev *us_ibdev =
+ container_of(device, struct usnic_ib_dev, ib_dev);
+ struct ethtool_drvinfo info;
+
+ mutex_lock(&us_ibdev->usdev_lock);
+ us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
+ mutex_unlock(&us_ibdev->usdev_lock);
+
+ snprintf(str, str_len, "%s", info.fw_version);
+}
+
/* Start of PF discovery section */
static void *usnic_ib_device_add(struct pci_dev *dev)
{
@@ -414,6 +429,7 @@ static void *usnic_ib_device_add(struct pci_dev *dev)
us_ibdev->ib_dev.req_notify_cq = usnic_ib_req_notify_cq;
us_ibdev->ib_dev.get_dma_mr = usnic_ib_get_dma_mr;
us_ibdev->ib_dev.get_port_immutable = usnic_port_immutable;
+ us_ibdev->ib_dev.get_dev_fw_str = usnic_get_dev_fw_str;
if (ib_register_device(&us_ibdev->ib_dev, NULL))
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index 3412ea06116e..80ef3f8998c8 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -45,21 +45,6 @@
#include "usnic_ib_verbs.h"
#include "usnic_log.h"
-static ssize_t usnic_ib_show_fw_ver(struct device *device,
- struct device_attribute *attr,
- char *buf)
-{
- struct usnic_ib_dev *us_ibdev =
- container_of(device, struct usnic_ib_dev, ib_dev.dev);
- struct ethtool_drvinfo info;
-
- mutex_lock(&us_ibdev->usdev_lock);
- us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
- mutex_unlock(&us_ibdev->usdev_lock);
-
- return scnprintf(buf, PAGE_SIZE, "%s\n", info.fw_version);
-}
-
static ssize_t usnic_ib_show_board(struct device *device,
struct device_attribute *attr,
char *buf)
@@ -192,7 +177,6 @@ usnic_ib_show_cq_per_vf(struct device *device, struct device_attribute *attr,
us_ibdev->vf_res_cnt[USNIC_VNIC_RES_TYPE_CQ]);
}
-static DEVICE_ATTR(fw_ver, S_IRUGO, usnic_ib_show_fw_ver, NULL);
static DEVICE_ATTR(board_id, S_IRUGO, usnic_ib_show_board, NULL);
static DEVICE_ATTR(config, S_IRUGO, usnic_ib_show_config, NULL);
static DEVICE_ATTR(iface, S_IRUGO, usnic_ib_show_iface, NULL);
@@ -201,7 +185,6 @@ static DEVICE_ATTR(qp_per_vf, S_IRUGO, usnic_ib_show_qp_per_vf, NULL);
static DEVICE_ATTR(cq_per_vf, S_IRUGO, usnic_ib_show_cq_per_vf, NULL);
static struct device_attribute *usnic_class_attributes[] = {
- &dev_attr_fw_ver,
&dev_attr_board_id,
&dev_attr_config,
&dev_attr_iface,
diff --git a/drivers/infiniband/sw/Makefile b/drivers/infiniband/sw/Makefile
index 988b6a0101a4..8b095b27db87 100644
--- a/drivers/infiniband/sw/Makefile
+++ b/drivers/infiniband/sw/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_INFINIBAND_RDMAVT) += rdmavt/
+obj-$(CONFIG_RDMA_RXE) += rxe/
diff --git a/drivers/infiniband/sw/rdmavt/Kconfig b/drivers/infiniband/sw/rdmavt/Kconfig
index 11aa6a34bd71..1da8d01a6855 100644
--- a/drivers/infiniband/sw/rdmavt/Kconfig
+++ b/drivers/infiniband/sw/rdmavt/Kconfig
@@ -1,6 +1,5 @@
config INFINIBAND_RDMAVT
tristate "RDMA verbs transport library"
depends on 64BIT
- default m
---help---
This is a common software verbs provider for RDMA networks.
diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c
index 6ca6fa80dd6e..f2f229efbe64 100644
--- a/drivers/infiniband/sw/rdmavt/cq.c
+++ b/drivers/infiniband/sw/rdmavt/cq.c
@@ -510,6 +510,7 @@ int rvt_driver_cq_init(struct rvt_dev_info *rdi)
if (rdi->worker)
return 0;
+ spin_lock_init(&rdi->n_cqs_lock);
rdi->worker = kzalloc(sizeof(*rdi->worker), GFP_KERNEL);
if (!rdi->worker)
return -ENOMEM;
diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c
index 0f4d4500f45e..80c4b6b401b8 100644
--- a/drivers/infiniband/sw/rdmavt/mr.c
+++ b/drivers/infiniband/sw/rdmavt/mr.c
@@ -140,6 +140,7 @@ static int rvt_init_mregion(struct rvt_mregion *mr, struct ib_pd *pd,
init_completion(&mr->comp);
/* count returning the ptr to user */
atomic_set(&mr->refcount, 1);
+ atomic_set(&mr->lkey_invalid, 0);
mr->pd = pd;
mr->max_segs = count;
return 0;
@@ -480,6 +481,123 @@ struct ib_mr *rvt_alloc_mr(struct ib_pd *pd,
}
/**
+ * rvt_set_page - page assignment function called by ib_sg_to_pages
+ * @ibmr: memory region
+ * @addr: dma address of mapped page
+ *
+ * Return: 0 on success
+ */
+static int rvt_set_page(struct ib_mr *ibmr, u64 addr)
+{
+ struct rvt_mr *mr = to_imr(ibmr);
+ u32 ps = 1 << mr->mr.page_shift;
+ u32 mapped_segs = mr->mr.length >> mr->mr.page_shift;
+ int m, n;
+
+ if (unlikely(mapped_segs == mr->mr.max_segs))
+ return -ENOMEM;
+
+ if (mr->mr.length == 0) {
+ mr->mr.user_base = addr;
+ mr->mr.iova = addr;
+ }
+
+ m = mapped_segs / RVT_SEGSZ;
+ n = mapped_segs % RVT_SEGSZ;
+ mr->mr.map[m]->segs[n].vaddr = (void *)addr;
+ mr->mr.map[m]->segs[n].length = ps;
+ mr->mr.length += ps;
+
+ return 0;
+}
+
+/**
+ * rvt_map_mr_sg - map sg list and set it the memory region
+ * @ibmr: memory region
+ * @sg: dma mapped scatterlist
+ * @sg_nents: number of entries in sg
+ * @sg_offset: offset in bytes into sg
+ *
+ * Return: number of sg elements mapped to the memory region
+ */
+int rvt_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
+ int sg_nents, unsigned int *sg_offset)
+{
+ struct rvt_mr *mr = to_imr(ibmr);
+
+ mr->mr.length = 0;
+ mr->mr.page_shift = PAGE_SHIFT;
+ return ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset,
+ rvt_set_page);
+}
+
+/**
+ * rvt_fast_reg_mr - fast register physical MR
+ * @qp: the queue pair where the work request comes from
+ * @ibmr: the memory region to be registered
+ * @key: updated key for this memory region
+ * @access: access flags for this memory region
+ *
+ * Returns 0 on success.
+ */
+int rvt_fast_reg_mr(struct rvt_qp *qp, struct ib_mr *ibmr, u32 key,
+ int access)
+{
+ struct rvt_mr *mr = to_imr(ibmr);
+
+ if (qp->ibqp.pd != mr->mr.pd)
+ return -EACCES;
+
+ /* not applicable to dma MR or user MR */
+ if (!mr->mr.lkey || mr->umem)
+ return -EINVAL;
+
+ if ((key & 0xFFFFFF00) != (mr->mr.lkey & 0xFFFFFF00))
+ return -EINVAL;
+
+ ibmr->lkey = key;
+ ibmr->rkey = key;
+ mr->mr.lkey = key;
+ mr->mr.access_flags = access;
+ atomic_set(&mr->mr.lkey_invalid, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(rvt_fast_reg_mr);
+
+/**
+ * rvt_invalidate_rkey - invalidate an MR rkey
+ * @qp: queue pair associated with the invalidate op
+ * @rkey: rkey to invalidate
+ *
+ * Returns 0 on success.
+ */
+int rvt_invalidate_rkey(struct rvt_qp *qp, u32 rkey)
+{
+ struct rvt_dev_info *dev = ib_to_rvt(qp->ibqp.device);
+ struct rvt_lkey_table *rkt = &dev->lkey_table;
+ struct rvt_mregion *mr;
+
+ if (rkey == 0)
+ return -EINVAL;
+
+ rcu_read_lock();
+ mr = rcu_dereference(
+ rkt->table[(rkey >> (32 - dev->dparms.lkey_table_size))]);
+ if (unlikely(!mr || mr->lkey != rkey || qp->ibqp.pd != mr->pd))
+ goto bail;
+
+ atomic_set(&mr->lkey_invalid, 1);
+ rcu_read_unlock();
+ return 0;
+
+bail:
+ rcu_read_unlock();
+ return -EINVAL;
+}
+EXPORT_SYMBOL(rvt_invalidate_rkey);
+
+/**
* rvt_alloc_fmr - allocate a fast memory region
* @pd: the protection domain for this memory region
* @mr_access_flags: access flags for this memory region
@@ -682,7 +800,8 @@ int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
}
mr = rcu_dereference(
rkt->table[(sge->lkey >> (32 - dev->dparms.lkey_table_size))]);
- if (unlikely(!mr || mr->lkey != sge->lkey || mr->pd != &pd->ibpd))
+ if (unlikely(!mr || atomic_read(&mr->lkey_invalid) ||
+ mr->lkey != sge->lkey || mr->pd != &pd->ibpd))
goto bail;
off = sge->addr - mr->user_base;
@@ -782,7 +901,8 @@ int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
mr = rcu_dereference(
rkt->table[(rkey >> (32 - dev->dparms.lkey_table_size))]);
- if (unlikely(!mr || mr->lkey != rkey || qp->ibqp.pd != mr->pd))
+ if (unlikely(!mr || atomic_read(&mr->lkey_invalid) ||
+ mr->lkey != rkey || qp->ibqp.pd != mr->pd))
goto bail;
off = vaddr - mr->iova;
diff --git a/drivers/infiniband/sw/rdmavt/mr.h b/drivers/infiniband/sw/rdmavt/mr.h
index 69380512c6d1..132800ee0205 100644
--- a/drivers/infiniband/sw/rdmavt/mr.h
+++ b/drivers/infiniband/sw/rdmavt/mr.h
@@ -82,6 +82,8 @@ int rvt_dereg_mr(struct ib_mr *ibmr);
struct ib_mr *rvt_alloc_mr(struct ib_pd *pd,
enum ib_mr_type mr_type,
u32 max_num_sg);
+int rvt_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
+ int sg_nents, unsigned int *sg_offset);
struct ib_fmr *rvt_alloc_fmr(struct ib_pd *pd, int mr_access_flags,
struct ib_fmr_attr *fmr_attr);
int rvt_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index 41ba7e9cadaa..bdb540f25a88 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -435,8 +435,7 @@ static void rvt_clear_mr_refs(struct rvt_qp *qp, int clr_sends)
for (n = 0; n < rvt_max_atomic(rdi); n++) {
struct rvt_ack_entry *e = &qp->s_ack_queue[n];
- if (e->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST &&
- e->rdma_sge.mr) {
+ if (e->rdma_sge.mr) {
rvt_put_mr(e->rdma_sge.mr);
e->rdma_sge.mr = NULL;
}
@@ -584,6 +583,7 @@ static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
qp->r_rq.wq->tail = 0;
}
qp->r_sge.num_sge = 0;
+ atomic_set(&qp->s_reserved_used, 0);
}
/**
@@ -613,6 +613,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
struct rvt_dev_info *rdi = ib_to_rvt(ibpd->device);
void *priv = NULL;
gfp_t gfp;
+ size_t sqsize;
if (!rdi)
return ERR_PTR(-EINVAL);
@@ -643,7 +644,9 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
init_attr->cap.max_recv_wr == 0)
return ERR_PTR(-EINVAL);
}
-
+ sqsize =
+ init_attr->cap.max_send_wr + 1 +
+ rdi->dparms.reserved_operations;
switch (init_attr->qp_type) {
case IB_QPT_SMI:
case IB_QPT_GSI:
@@ -658,11 +661,11 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
sizeof(struct rvt_swqe);
if (gfp == GFP_NOIO)
swq = __vmalloc(
- (init_attr->cap.max_send_wr + 1) * sz,
+ sqsize * sz,
gfp | __GFP_ZERO, PAGE_KERNEL);
else
swq = vzalloc_node(
- (init_attr->cap.max_send_wr + 1) * sz,
+ sqsize * sz,
rdi->dparms.node);
if (!swq)
return ERR_PTR(-ENOMEM);
@@ -741,13 +744,14 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
spin_lock_init(&qp->s_lock);
spin_lock_init(&qp->r_rq.lock);
atomic_set(&qp->refcount, 0);
+ atomic_set(&qp->local_ops_pending, 0);
init_waitqueue_head(&qp->wait);
init_timer(&qp->s_timer);
qp->s_timer.data = (unsigned long)qp;
INIT_LIST_HEAD(&qp->rspwait);
qp->state = IB_QPS_RESET;
qp->s_wq = swq;
- qp->s_size = init_attr->cap.max_send_wr + 1;
+ qp->s_size = sqsize;
qp->s_avail = init_attr->cap.max_send_wr;
qp->s_max_sge = init_attr->cap.max_send_sge;
if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR)
@@ -1332,7 +1336,8 @@ int rvt_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
attr->sq_psn = qp->s_next_psn & rdi->dparms.psn_mask;
attr->dest_qp_num = qp->remote_qpn;
attr->qp_access_flags = qp->qp_access_flags;
- attr->cap.max_send_wr = qp->s_size - 1;
+ attr->cap.max_send_wr = qp->s_size - 1 -
+ rdi->dparms.reserved_operations;
attr->cap.max_recv_wr = qp->ibqp.srq ? 0 : qp->r_rq.size - 1;
attr->cap.max_send_sge = qp->s_max_sge;
attr->cap.max_recv_sge = qp->r_rq.max_sge;
@@ -1440,25 +1445,116 @@ int rvt_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
}
/**
- * qp_get_savail - return number of avail send entries
+ * rvt_qp_valid_operation - validate post send wr request
+ * @qp - the qp
+ * @post-parms - the post send table for the driver
+ * @wr - the work request
+ *
+ * The routine validates the operation based on the
+ * validation table an returns the length of the operation
+ * which can extend beyond the ib_send_bw. Operation
+ * dependent flags key atomic operation validation.
*
+ * There is an exception for UD qps that validates the pd and
+ * overrides the length to include the additional UD specific
+ * length.
+ *
+ * Returns a negative error or the length of the work request
+ * for building the swqe.
+ */
+static inline int rvt_qp_valid_operation(
+ struct rvt_qp *qp,
+ const struct rvt_operation_params *post_parms,
+ struct ib_send_wr *wr)
+{
+ int len;
+
+ if (wr->opcode >= RVT_OPERATION_MAX || !post_parms[wr->opcode].length)
+ return -EINVAL;
+ if (!(post_parms[wr->opcode].qpt_support & BIT(qp->ibqp.qp_type)))
+ return -EINVAL;
+ if ((post_parms[wr->opcode].flags & RVT_OPERATION_PRIV) &&
+ ibpd_to_rvtpd(qp->ibqp.pd)->user)
+ return -EINVAL;
+ if (post_parms[wr->opcode].flags & RVT_OPERATION_ATOMIC_SGE &&
+ (wr->num_sge == 0 ||
+ wr->sg_list[0].length < sizeof(u64) ||
+ wr->sg_list[0].addr & (sizeof(u64) - 1)))
+ return -EINVAL;
+ if (post_parms[wr->opcode].flags & RVT_OPERATION_ATOMIC &&
+ !qp->s_max_rd_atomic)
+ return -EINVAL;
+ len = post_parms[wr->opcode].length;
+ /* UD specific */
+ if (qp->ibqp.qp_type != IB_QPT_UC &&
+ qp->ibqp.qp_type != IB_QPT_RC) {
+ if (qp->ibqp.pd != ud_wr(wr)->ah->pd)
+ return -EINVAL;
+ len = sizeof(struct ib_ud_wr);
+ }
+ return len;
+}
+
+/**
+ * rvt_qp_is_avail - determine queue capacity
* @qp - the qp
+ * @rdi - the rdmavt device
+ * @reserved_op - is reserved operation
*
* This assumes the s_hlock is held but the s_last
* qp variable is uncontrolled.
+ *
+ * For non reserved operations, the qp->s_avail
+ * may be changed.
+ *
+ * The return value is zero or a -ENOMEM.
*/
-static inline u32 qp_get_savail(struct rvt_qp *qp)
+static inline int rvt_qp_is_avail(
+ struct rvt_qp *qp,
+ struct rvt_dev_info *rdi,
+ bool reserved_op)
{
u32 slast;
- u32 ret;
-
+ u32 avail;
+ u32 reserved_used;
+
+ /* see rvt_qp_wqe_unreserve() */
+ smp_mb__before_atomic();
+ reserved_used = atomic_read(&qp->s_reserved_used);
+ if (unlikely(reserved_op)) {
+ /* see rvt_qp_wqe_unreserve() */
+ smp_mb__before_atomic();
+ if (reserved_used >= rdi->dparms.reserved_operations)
+ return -ENOMEM;
+ return 0;
+ }
+ /* non-reserved operations */
+ if (likely(qp->s_avail))
+ return 0;
smp_read_barrier_depends(); /* see rc.c */
slast = ACCESS_ONCE(qp->s_last);
if (qp->s_head >= slast)
- ret = qp->s_size - (qp->s_head - slast);
+ avail = qp->s_size - (qp->s_head - slast);
else
- ret = slast - qp->s_head;
- return ret - 1;
+ avail = slast - qp->s_head;
+
+ /* see rvt_qp_wqe_unreserve() */
+ smp_mb__before_atomic();
+ reserved_used = atomic_read(&qp->s_reserved_used);
+ avail = avail - 1 -
+ (rdi->dparms.reserved_operations - reserved_used);
+ /* insure we don't assign a negative s_avail */
+ if ((s32)avail <= 0)
+ return -ENOMEM;
+ qp->s_avail = avail;
+ if (WARN_ON(qp->s_avail >
+ (qp->s_size - 1 - rdi->dparms.reserved_operations)))
+ rvt_pr_err(rdi,
+ "More avail entries than QP RB size.\nQP: %u, size: %u, avail: %u\nhead: %u, tail: %u, cur: %u, acked: %u, last: %u",
+ qp->ibqp.qp_num, qp->s_size, qp->s_avail,
+ qp->s_head, qp->s_tail, qp->s_cur,
+ qp->s_acked, qp->s_last);
+ return 0;
}
/**
@@ -1480,49 +1576,64 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
u8 log_pmtu;
int ret;
+ size_t cplen;
+ bool reserved_op;
+ int local_ops_delayed = 0;
+
+ BUILD_BUG_ON(IB_QPT_MAX >= (sizeof(u32) * BITS_PER_BYTE));
/* IB spec says that num_sge == 0 is OK. */
if (unlikely(wr->num_sge > qp->s_max_sge))
return -EINVAL;
+ ret = rvt_qp_valid_operation(qp, rdi->post_parms, wr);
+ if (ret < 0)
+ return ret;
+ cplen = ret;
+
/*
- * Don't allow RDMA reads or atomic operations on UC or
- * undefined operations.
- * Make sure buffer is large enough to hold the result for atomics.
+ * Local operations include fast register and local invalidate.
+ * Fast register needs to be processed immediately because the
+ * registered lkey may be used by following work requests and the
+ * lkey needs to be valid at the time those requests are posted.
+ * Local invalidate can be processed immediately if fencing is
+ * not required and no previous local invalidate ops are pending.
+ * Signaled local operations that have been processed immediately
+ * need to have requests with "completion only" flags set posted
+ * to the send queue in order to generate completions.
*/
- if (qp->ibqp.qp_type == IB_QPT_UC) {
- if ((unsigned)wr->opcode >= IB_WR_RDMA_READ)
- return -EINVAL;
- } else if (qp->ibqp.qp_type != IB_QPT_RC) {
- /* Check IB_QPT_SMI, IB_QPT_GSI, IB_QPT_UD opcode */
- if (wr->opcode != IB_WR_SEND &&
- wr->opcode != IB_WR_SEND_WITH_IMM)
- return -EINVAL;
- /* Check UD destination address PD */
- if (qp->ibqp.pd != ud_wr(wr)->ah->pd)
+ if ((rdi->post_parms[wr->opcode].flags & RVT_OPERATION_LOCAL)) {
+ switch (wr->opcode) {
+ case IB_WR_REG_MR:
+ ret = rvt_fast_reg_mr(qp,
+ reg_wr(wr)->mr,
+ reg_wr(wr)->key,
+ reg_wr(wr)->access);
+ if (ret || !(wr->send_flags & IB_SEND_SIGNALED))
+ return ret;
+ break;
+ case IB_WR_LOCAL_INV:
+ if ((wr->send_flags & IB_SEND_FENCE) ||
+ atomic_read(&qp->local_ops_pending)) {
+ local_ops_delayed = 1;
+ } else {
+ ret = rvt_invalidate_rkey(
+ qp, wr->ex.invalidate_rkey);
+ if (ret || !(wr->send_flags & IB_SEND_SIGNALED))
+ return ret;
+ }
+ break;
+ default:
return -EINVAL;
- } else if ((unsigned)wr->opcode > IB_WR_ATOMIC_FETCH_AND_ADD) {
- return -EINVAL;
- } else if (wr->opcode >= IB_WR_ATOMIC_CMP_AND_SWP &&
- (wr->num_sge == 0 ||
- wr->sg_list[0].length < sizeof(u64) ||
- wr->sg_list[0].addr & (sizeof(u64) - 1))) {
- return -EINVAL;
- } else if (wr->opcode >= IB_WR_RDMA_READ && !qp->s_max_rd_atomic) {
- return -EINVAL;
+ }
}
+
+ reserved_op = rdi->post_parms[wr->opcode].flags &
+ RVT_OPERATION_USE_RESERVE;
/* check for avail */
- if (unlikely(!qp->s_avail)) {
- qp->s_avail = qp_get_savail(qp);
- if (WARN_ON(qp->s_avail > (qp->s_size - 1)))
- rvt_pr_err(rdi,
- "More avail entries than QP RB size.\nQP: %u, size: %u, avail: %u\nhead: %u, tail: %u, cur: %u, acked: %u, last: %u",
- qp->ibqp.qp_num, qp->s_size, qp->s_avail,
- qp->s_head, qp->s_tail, qp->s_cur,
- qp->s_acked, qp->s_last);
- if (!qp->s_avail)
- return -ENOMEM;
- }
+ ret = rvt_qp_is_avail(qp, rdi, reserved_op);
+ if (ret)
+ return ret;
next = qp->s_head + 1;
if (next >= qp->s_size)
next = 0;
@@ -1531,18 +1642,8 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
pd = ibpd_to_rvtpd(qp->ibqp.pd);
wqe = rvt_get_swqe_ptr(qp, qp->s_head);
- if (qp->ibqp.qp_type != IB_QPT_UC &&
- qp->ibqp.qp_type != IB_QPT_RC)
- memcpy(&wqe->ud_wr, ud_wr(wr), sizeof(wqe->ud_wr));
- else if (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
- wr->opcode == IB_WR_RDMA_WRITE ||
- wr->opcode == IB_WR_RDMA_READ)
- memcpy(&wqe->rdma_wr, rdma_wr(wr), sizeof(wqe->rdma_wr));
- else if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP ||
- wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD)
- memcpy(&wqe->atomic_wr, atomic_wr(wr), sizeof(wqe->atomic_wr));
- else
- memcpy(&wqe->wr, wr, sizeof(wqe->wr));
+ /* cplen has length from above */
+ memcpy(&wqe->wr, wr, cplen);
wqe->length = 0;
j = 0;
@@ -1585,14 +1686,29 @@ static int rvt_post_one_wr(struct rvt_qp *qp,
atomic_inc(&ibah_to_rvtah(ud_wr(wr)->ah)->refcount);
}
- wqe->ssn = qp->s_ssn++;
- wqe->psn = qp->s_next_psn;
- wqe->lpsn = wqe->psn +
- (wqe->length ? ((wqe->length - 1) >> log_pmtu) : 0);
- qp->s_next_psn = wqe->lpsn + 1;
+ if (rdi->post_parms[wr->opcode].flags & RVT_OPERATION_LOCAL) {
+ if (local_ops_delayed)
+ atomic_inc(&qp->local_ops_pending);
+ else
+ wqe->wr.send_flags |= RVT_SEND_COMPLETION_ONLY;
+ wqe->ssn = 0;
+ wqe->psn = 0;
+ wqe->lpsn = 0;
+ } else {
+ wqe->ssn = qp->s_ssn++;
+ wqe->psn = qp->s_next_psn;
+ wqe->lpsn = wqe->psn +
+ (wqe->length ?
+ ((wqe->length - 1) >> log_pmtu) :
+ 0);
+ qp->s_next_psn = wqe->lpsn + 1;
+ }
trace_rvt_post_one_wr(qp, wqe);
+ if (unlikely(reserved_op))
+ rvt_qp_wqe_reserve(qp, wqe);
+ else
+ qp->s_avail--;
smp_wmb(); /* see request builders */
- qp->s_avail--;
qp->s_head = next;
return 0;
diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
index 30c4fda7a05a..d430c2f7cec4 100644
--- a/drivers/infiniband/sw/rdmavt/vt.c
+++ b/drivers/infiniband/sw/rdmavt/vt.c
@@ -370,6 +370,7 @@ enum {
REG_USER_MR,
DEREG_MR,
ALLOC_MR,
+ MAP_MR_SG,
ALLOC_FMR,
MAP_PHYS_FMR,
UNMAP_FMR,
@@ -528,7 +529,8 @@ static noinline int check_support(struct rvt_dev_info *rdi, int verb)
post_send),
rvt_post_send))
if (!rdi->driver_f.schedule_send ||
- !rdi->driver_f.do_send)
+ !rdi->driver_f.do_send ||
+ !rdi->post_parms)
return -EINVAL;
break;
@@ -633,6 +635,12 @@ static noinline int check_support(struct rvt_dev_info *rdi, int verb)
rvt_alloc_mr);
break;
+ case MAP_MR_SG:
+ check_driver_override(rdi, offsetof(struct ib_device,
+ map_mr_sg),
+ rvt_map_mr_sg);
+ break;
+
case MAP_PHYS_FMR:
check_driver_override(rdi, offsetof(struct ib_device,
map_phys_fmr),
diff --git a/drivers/infiniband/sw/rxe/Kconfig b/drivers/infiniband/sw/rxe/Kconfig
new file mode 100644
index 000000000000..1e4e628fe7b0
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/Kconfig
@@ -0,0 +1,24 @@
+config RDMA_RXE
+ tristate "Software RDMA over Ethernet (RoCE) driver"
+ depends on INET && PCI && INFINIBAND
+ depends on NET_UDP_TUNNEL
+ ---help---
+ This driver implements the InfiniBand RDMA transport over
+ the Linux network stack. It enables a system with a
+ standard Ethernet adapter to interoperate with a RoCE
+ adapter or with another system running the RXE driver.
+ Documentation on InfiniBand and RoCE can be downloaded at
+ www.infinibandta.org and www.openfabrics.org. (See also
+ siw which is a similar software driver for iWARP.)
+
+ The driver is split into two layers, one interfaces with the
+ Linux RDMA stack and implements a kernel or user space
+ verbs API. The user space verbs API requires a support
+ library named librxe which is loaded by the generic user
+ space verbs API, libibverbs. The other layer interfaces
+ with the Linux network stack at layer 3.
+
+ To configure and work with soft-RoCE driver please use the
+ following wiki page under "configure Soft-RoCE (RXE)" section:
+
+ https://github.com/SoftRoCE/rxe-dev/wiki/rxe-dev:-Home
diff --git a/drivers/infiniband/sw/rxe/Makefile b/drivers/infiniband/sw/rxe/Makefile
new file mode 100644
index 000000000000..3b3fb9d1c470
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/Makefile
@@ -0,0 +1,24 @@
+obj-$(CONFIG_RDMA_RXE) += rdma_rxe.o
+
+rdma_rxe-y := \
+ rxe.o \
+ rxe_comp.o \
+ rxe_req.o \
+ rxe_resp.o \
+ rxe_recv.o \
+ rxe_pool.o \
+ rxe_queue.o \
+ rxe_verbs.o \
+ rxe_av.o \
+ rxe_srq.o \
+ rxe_qp.o \
+ rxe_cq.o \
+ rxe_mr.o \
+ rxe_dma.o \
+ rxe_opcode.o \
+ rxe_mmap.o \
+ rxe_icrc.o \
+ rxe_mcast.o \
+ rxe_task.o \
+ rxe_net.o \
+ rxe_sysfs.o
diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
new file mode 100644
index 000000000000..55f0e8f0ca79
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+MODULE_AUTHOR("Bob Pearson, Frank Zago, John Groves, Kamal Heib");
+MODULE_DESCRIPTION("Soft RDMA transport");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION("0.2");
+
+/* free resources for all ports on a device */
+static void rxe_cleanup_ports(struct rxe_dev *rxe)
+{
+ kfree(rxe->port.pkey_tbl);
+ rxe->port.pkey_tbl = NULL;
+
+}
+
+/* free resources for a rxe device all objects created for this device must
+ * have been destroyed
+ */
+static void rxe_cleanup(struct rxe_dev *rxe)
+{
+ rxe_pool_cleanup(&rxe->uc_pool);
+ rxe_pool_cleanup(&rxe->pd_pool);
+ rxe_pool_cleanup(&rxe->ah_pool);
+ rxe_pool_cleanup(&rxe->srq_pool);
+ rxe_pool_cleanup(&rxe->qp_pool);
+ rxe_pool_cleanup(&rxe->cq_pool);
+ rxe_pool_cleanup(&rxe->mr_pool);
+ rxe_pool_cleanup(&rxe->mw_pool);
+ rxe_pool_cleanup(&rxe->mc_grp_pool);
+ rxe_pool_cleanup(&rxe->mc_elem_pool);
+
+ rxe_cleanup_ports(rxe);
+}
+
+/* called when all references have been dropped */
+void rxe_release(struct kref *kref)
+{
+ struct rxe_dev *rxe = container_of(kref, struct rxe_dev, ref_cnt);
+
+ rxe_cleanup(rxe);
+ ib_dealloc_device(&rxe->ib_dev);
+}
+
+void rxe_dev_put(struct rxe_dev *rxe)
+{
+ kref_put(&rxe->ref_cnt, rxe_release);
+}
+EXPORT_SYMBOL_GPL(rxe_dev_put);
+
+/* initialize rxe device parameters */
+static int rxe_init_device_param(struct rxe_dev *rxe)
+{
+ rxe->max_inline_data = RXE_MAX_INLINE_DATA;
+
+ rxe->attr.fw_ver = RXE_FW_VER;
+ rxe->attr.max_mr_size = RXE_MAX_MR_SIZE;
+ rxe->attr.page_size_cap = RXE_PAGE_SIZE_CAP;
+ rxe->attr.vendor_id = RXE_VENDOR_ID;
+ rxe->attr.vendor_part_id = RXE_VENDOR_PART_ID;
+ rxe->attr.hw_ver = RXE_HW_VER;
+ rxe->attr.max_qp = RXE_MAX_QP;
+ rxe->attr.max_qp_wr = RXE_MAX_QP_WR;
+ rxe->attr.device_cap_flags = RXE_DEVICE_CAP_FLAGS;
+ rxe->attr.max_sge = RXE_MAX_SGE;
+ rxe->attr.max_sge_rd = RXE_MAX_SGE_RD;
+ rxe->attr.max_cq = RXE_MAX_CQ;
+ rxe->attr.max_cqe = (1 << RXE_MAX_LOG_CQE) - 1;
+ rxe->attr.max_mr = RXE_MAX_MR;
+ rxe->attr.max_pd = RXE_MAX_PD;
+ rxe->attr.max_qp_rd_atom = RXE_MAX_QP_RD_ATOM;
+ rxe->attr.max_ee_rd_atom = RXE_MAX_EE_RD_ATOM;
+ rxe->attr.max_res_rd_atom = RXE_MAX_RES_RD_ATOM;
+ rxe->attr.max_qp_init_rd_atom = RXE_MAX_QP_INIT_RD_ATOM;
+ rxe->attr.max_ee_init_rd_atom = RXE_MAX_EE_INIT_RD_ATOM;
+ rxe->attr.atomic_cap = RXE_ATOMIC_CAP;
+ rxe->attr.max_ee = RXE_MAX_EE;
+ rxe->attr.max_rdd = RXE_MAX_RDD;
+ rxe->attr.max_mw = RXE_MAX_MW;
+ rxe->attr.max_raw_ipv6_qp = RXE_MAX_RAW_IPV6_QP;
+ rxe->attr.max_raw_ethy_qp = RXE_MAX_RAW_ETHY_QP;
+ rxe->attr.max_mcast_grp = RXE_MAX_MCAST_GRP;
+ rxe->attr.max_mcast_qp_attach = RXE_MAX_MCAST_QP_ATTACH;
+ rxe->attr.max_total_mcast_qp_attach = RXE_MAX_TOT_MCAST_QP_ATTACH;
+ rxe->attr.max_ah = RXE_MAX_AH;
+ rxe->attr.max_fmr = RXE_MAX_FMR;
+ rxe->attr.max_map_per_fmr = RXE_MAX_MAP_PER_FMR;
+ rxe->attr.max_srq = RXE_MAX_SRQ;
+ rxe->attr.max_srq_wr = RXE_MAX_SRQ_WR;
+ rxe->attr.max_srq_sge = RXE_MAX_SRQ_SGE;
+ rxe->attr.max_fast_reg_page_list_len = RXE_MAX_FMR_PAGE_LIST_LEN;
+ rxe->attr.max_pkeys = RXE_MAX_PKEYS;
+ rxe->attr.local_ca_ack_delay = RXE_LOCAL_CA_ACK_DELAY;
+
+ rxe->max_ucontext = RXE_MAX_UCONTEXT;
+
+ return 0;
+}
+
+/* initialize port attributes */
+static int rxe_init_port_param(struct rxe_port *port)
+{
+ port->attr.state = RXE_PORT_STATE;
+ port->attr.max_mtu = RXE_PORT_MAX_MTU;
+ port->attr.active_mtu = RXE_PORT_ACTIVE_MTU;
+ port->attr.gid_tbl_len = RXE_PORT_GID_TBL_LEN;
+ port->attr.port_cap_flags = RXE_PORT_PORT_CAP_FLAGS;
+ port->attr.max_msg_sz = RXE_PORT_MAX_MSG_SZ;
+ port->attr.bad_pkey_cntr = RXE_PORT_BAD_PKEY_CNTR;
+ port->attr.qkey_viol_cntr = RXE_PORT_QKEY_VIOL_CNTR;
+ port->attr.pkey_tbl_len = RXE_PORT_PKEY_TBL_LEN;
+ port->attr.lid = RXE_PORT_LID;
+ port->attr.sm_lid = RXE_PORT_SM_LID;
+ port->attr.lmc = RXE_PORT_LMC;
+ port->attr.max_vl_num = RXE_PORT_MAX_VL_NUM;
+ port->attr.sm_sl = RXE_PORT_SM_SL;
+ port->attr.subnet_timeout = RXE_PORT_SUBNET_TIMEOUT;
+ port->attr.init_type_reply = RXE_PORT_INIT_TYPE_REPLY;
+ port->attr.active_width = RXE_PORT_ACTIVE_WIDTH;
+ port->attr.active_speed = RXE_PORT_ACTIVE_SPEED;
+ port->attr.phys_state = RXE_PORT_PHYS_STATE;
+ port->mtu_cap =
+ ib_mtu_enum_to_int(RXE_PORT_ACTIVE_MTU);
+ port->subnet_prefix = cpu_to_be64(RXE_PORT_SUBNET_PREFIX);
+
+ return 0;
+}
+
+/* initialize port state, note IB convention that HCA ports are always
+ * numbered from 1
+ */
+static int rxe_init_ports(struct rxe_dev *rxe)
+{
+ struct rxe_port *port = &rxe->port;
+
+ rxe_init_port_param(port);
+
+ if (!port->attr.pkey_tbl_len || !port->attr.gid_tbl_len)
+ return -EINVAL;
+
+ port->pkey_tbl = kcalloc(port->attr.pkey_tbl_len,
+ sizeof(*port->pkey_tbl), GFP_KERNEL);
+
+ if (!port->pkey_tbl)
+ return -ENOMEM;
+
+ port->pkey_tbl[0] = 0xffff;
+ port->port_guid = rxe->ifc_ops->port_guid(rxe);
+
+ spin_lock_init(&port->port_lock);
+
+ return 0;
+}
+
+/* init pools of managed objects */
+static int rxe_init_pools(struct rxe_dev *rxe)
+{
+ int err;
+
+ err = rxe_pool_init(rxe, &rxe->uc_pool, RXE_TYPE_UC,
+ rxe->max_ucontext);
+ if (err)
+ goto err1;
+
+ err = rxe_pool_init(rxe, &rxe->pd_pool, RXE_TYPE_PD,
+ rxe->attr.max_pd);
+ if (err)
+ goto err2;
+
+ err = rxe_pool_init(rxe, &rxe->ah_pool, RXE_TYPE_AH,
+ rxe->attr.max_ah);
+ if (err)
+ goto err3;
+
+ err = rxe_pool_init(rxe, &rxe->srq_pool, RXE_TYPE_SRQ,
+ rxe->attr.max_srq);
+ if (err)
+ goto err4;
+
+ err = rxe_pool_init(rxe, &rxe->qp_pool, RXE_TYPE_QP,
+ rxe->attr.max_qp);
+ if (err)
+ goto err5;
+
+ err = rxe_pool_init(rxe, &rxe->cq_pool, RXE_TYPE_CQ,
+ rxe->attr.max_cq);
+ if (err)
+ goto err6;
+
+ err = rxe_pool_init(rxe, &rxe->mr_pool, RXE_TYPE_MR,
+ rxe->attr.max_mr);
+ if (err)
+ goto err7;
+
+ err = rxe_pool_init(rxe, &rxe->mw_pool, RXE_TYPE_MW,
+ rxe->attr.max_mw);
+ if (err)
+ goto err8;
+
+ err = rxe_pool_init(rxe, &rxe->mc_grp_pool, RXE_TYPE_MC_GRP,
+ rxe->attr.max_mcast_grp);
+ if (err)
+ goto err9;
+
+ err = rxe_pool_init(rxe, &rxe->mc_elem_pool, RXE_TYPE_MC_ELEM,
+ rxe->attr.max_total_mcast_qp_attach);
+ if (err)
+ goto err10;
+
+ return 0;
+
+err10:
+ rxe_pool_cleanup(&rxe->mc_grp_pool);
+err9:
+ rxe_pool_cleanup(&rxe->mw_pool);
+err8:
+ rxe_pool_cleanup(&rxe->mr_pool);
+err7:
+ rxe_pool_cleanup(&rxe->cq_pool);
+err6:
+ rxe_pool_cleanup(&rxe->qp_pool);
+err5:
+ rxe_pool_cleanup(&rxe->srq_pool);
+err4:
+ rxe_pool_cleanup(&rxe->ah_pool);
+err3:
+ rxe_pool_cleanup(&rxe->pd_pool);
+err2:
+ rxe_pool_cleanup(&rxe->uc_pool);
+err1:
+ return err;
+}
+
+/* initialize rxe device state */
+static int rxe_init(struct rxe_dev *rxe)
+{
+ int err;
+
+ /* init default device parameters */
+ rxe_init_device_param(rxe);
+
+ err = rxe_init_ports(rxe);
+ if (err)
+ goto err1;
+
+ err = rxe_init_pools(rxe);
+ if (err)
+ goto err2;
+
+ /* init pending mmap list */
+ spin_lock_init(&rxe->mmap_offset_lock);
+ spin_lock_init(&rxe->pending_lock);
+ INIT_LIST_HEAD(&rxe->pending_mmaps);
+ INIT_LIST_HEAD(&rxe->list);
+
+ mutex_init(&rxe->usdev_lock);
+
+ return 0;
+
+err2:
+ rxe_cleanup_ports(rxe);
+err1:
+ return err;
+}
+
+int rxe_set_mtu(struct rxe_dev *rxe, unsigned int ndev_mtu)
+{
+ struct rxe_port *port = &rxe->port;
+ enum ib_mtu mtu;
+
+ mtu = eth_mtu_int_to_enum(ndev_mtu);
+
+ /* Make sure that new MTU in range */
+ mtu = mtu ? min_t(enum ib_mtu, mtu, RXE_PORT_MAX_MTU) : IB_MTU_256;
+
+ port->attr.active_mtu = mtu;
+ port->mtu_cap = ib_mtu_enum_to_int(mtu);
+
+ return 0;
+}
+EXPORT_SYMBOL(rxe_set_mtu);
+
+/* called by ifc layer to create new rxe device.
+ * The caller should allocate memory for rxe by calling ib_alloc_device.
+ */
+int rxe_add(struct rxe_dev *rxe, unsigned int mtu)
+{
+ int err;
+
+ kref_init(&rxe->ref_cnt);
+
+ err = rxe_init(rxe);
+ if (err)
+ goto err1;
+
+ err = rxe_set_mtu(rxe, mtu);
+ if (err)
+ goto err1;
+
+ err = rxe_register_device(rxe);
+ if (err)
+ goto err1;
+
+ return 0;
+
+err1:
+ rxe_dev_put(rxe);
+ return err;
+}
+EXPORT_SYMBOL(rxe_add);
+
+/* called by the ifc layer to remove a device */
+void rxe_remove(struct rxe_dev *rxe)
+{
+ rxe_unregister_device(rxe);
+
+ rxe_dev_put(rxe);
+}
+EXPORT_SYMBOL(rxe_remove);
+
+static int __init rxe_module_init(void)
+{
+ int err;
+
+ /* initialize slab caches for managed objects */
+ err = rxe_cache_init();
+ if (err) {
+ pr_err("rxe: unable to init object pools\n");
+ return err;
+ }
+
+ err = rxe_net_init();
+ if (err) {
+ pr_err("rxe: unable to init\n");
+ rxe_cache_exit();
+ return err;
+ }
+ pr_info("rxe: loaded\n");
+
+ return 0;
+}
+
+static void __exit rxe_module_exit(void)
+{
+ rxe_remove_all();
+ rxe_net_exit();
+ rxe_cache_exit();
+
+ pr_info("rxe: unloaded\n");
+}
+
+module_init(rxe_module_init);
+module_exit(rxe_module_exit);
diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h
new file mode 100644
index 000000000000..12c71c549f97
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_H
+#define RXE_H
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/crc32.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_pack.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_umem.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_addr.h>
+
+#include "rxe_net.h"
+#include "rxe_opcode.h"
+#include "rxe_hdr.h"
+#include "rxe_param.h"
+#include "rxe_verbs.h"
+
+#define RXE_UVERBS_ABI_VERSION (1)
+
+#define IB_PHYS_STATE_LINK_UP (5)
+#define IB_PHYS_STATE_LINK_DOWN (3)
+
+#define RXE_ROCE_V2_SPORT (0xc000)
+
+int rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
+
+int rxe_add(struct rxe_dev *rxe, unsigned int mtu);
+void rxe_remove(struct rxe_dev *rxe);
+void rxe_remove_all(void);
+
+int rxe_rcv(struct sk_buff *skb);
+
+void rxe_dev_put(struct rxe_dev *rxe);
+struct rxe_dev *net_to_rxe(struct net_device *ndev);
+struct rxe_dev *get_rxe_by_name(const char* name);
+
+void rxe_port_up(struct rxe_dev *rxe);
+void rxe_port_down(struct rxe_dev *rxe);
+
+#endif /* RXE_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_av.c b/drivers/infiniband/sw/rxe/rxe_av.c
new file mode 100644
index 000000000000..5c9474212d4e
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_av.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+int rxe_av_chk_attr(struct rxe_dev *rxe, struct ib_ah_attr *attr)
+{
+ struct rxe_port *port;
+
+ if (attr->port_num != 1) {
+ pr_info("rxe: invalid port_num = %d\n", attr->port_num);
+ return -EINVAL;
+ }
+
+ port = &rxe->port;
+
+ if (attr->ah_flags & IB_AH_GRH) {
+ if (attr->grh.sgid_index > port->attr.gid_tbl_len) {
+ pr_info("rxe: invalid sgid index = %d\n",
+ attr->grh.sgid_index);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int rxe_av_from_attr(struct rxe_dev *rxe, u8 port_num,
+ struct rxe_av *av, struct ib_ah_attr *attr)
+{
+ memset(av, 0, sizeof(*av));
+ memcpy(&av->grh, &attr->grh, sizeof(attr->grh));
+ av->port_num = port_num;
+ return 0;
+}
+
+int rxe_av_to_attr(struct rxe_dev *rxe, struct rxe_av *av,
+ struct ib_ah_attr *attr)
+{
+ memcpy(&attr->grh, &av->grh, sizeof(av->grh));
+ attr->port_num = av->port_num;
+ return 0;
+}
+
+int rxe_av_fill_ip_info(struct rxe_dev *rxe,
+ struct rxe_av *av,
+ struct ib_ah_attr *attr,
+ struct ib_gid_attr *sgid_attr,
+ union ib_gid *sgid)
+{
+ rdma_gid2ip(&av->sgid_addr._sockaddr, sgid);
+ rdma_gid2ip(&av->dgid_addr._sockaddr, &attr->grh.dgid);
+ av->network_type = ib_gid_to_network_type(sgid_attr->gid_type, sgid);
+
+ return 0;
+}
+
+struct rxe_av *rxe_get_av(struct rxe_pkt_info *pkt)
+{
+ if (!pkt || !pkt->qp)
+ return NULL;
+
+ if (qp_type(pkt->qp) == IB_QPT_RC || qp_type(pkt->qp) == IB_QPT_UC)
+ return &pkt->qp->pri_av;
+
+ return (pkt->wqe) ? &pkt->wqe->av : NULL;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
new file mode 100644
index 000000000000..36f67de44095
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_comp.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+#include "rxe_task.h"
+
+enum comp_state {
+ COMPST_GET_ACK,
+ COMPST_GET_WQE,
+ COMPST_COMP_WQE,
+ COMPST_COMP_ACK,
+ COMPST_CHECK_PSN,
+ COMPST_CHECK_ACK,
+ COMPST_READ,
+ COMPST_ATOMIC,
+ COMPST_WRITE_SEND,
+ COMPST_UPDATE_COMP,
+ COMPST_ERROR_RETRY,
+ COMPST_RNR_RETRY,
+ COMPST_ERROR,
+ COMPST_EXIT, /* We have an issue, and we want to rerun the completer */
+ COMPST_DONE, /* The completer finished successflly */
+};
+
+static char *comp_state_name[] = {
+ [COMPST_GET_ACK] = "GET ACK",
+ [COMPST_GET_WQE] = "GET WQE",
+ [COMPST_COMP_WQE] = "COMP WQE",
+ [COMPST_COMP_ACK] = "COMP ACK",
+ [COMPST_CHECK_PSN] = "CHECK PSN",
+ [COMPST_CHECK_ACK] = "CHECK ACK",
+ [COMPST_READ] = "READ",
+ [COMPST_ATOMIC] = "ATOMIC",
+ [COMPST_WRITE_SEND] = "WRITE/SEND",
+ [COMPST_UPDATE_COMP] = "UPDATE COMP",
+ [COMPST_ERROR_RETRY] = "ERROR RETRY",
+ [COMPST_RNR_RETRY] = "RNR RETRY",
+ [COMPST_ERROR] = "ERROR",
+ [COMPST_EXIT] = "EXIT",
+ [COMPST_DONE] = "DONE",
+};
+
+static unsigned long rnrnak_usec[32] = {
+ [IB_RNR_TIMER_655_36] = 655360,
+ [IB_RNR_TIMER_000_01] = 10,
+ [IB_RNR_TIMER_000_02] = 20,
+ [IB_RNR_TIMER_000_03] = 30,
+ [IB_RNR_TIMER_000_04] = 40,
+ [IB_RNR_TIMER_000_06] = 60,
+ [IB_RNR_TIMER_000_08] = 80,
+ [IB_RNR_TIMER_000_12] = 120,
+ [IB_RNR_TIMER_000_16] = 160,
+ [IB_RNR_TIMER_000_24] = 240,
+ [IB_RNR_TIMER_000_32] = 320,
+ [IB_RNR_TIMER_000_48] = 480,
+ [IB_RNR_TIMER_000_64] = 640,
+ [IB_RNR_TIMER_000_96] = 960,
+ [IB_RNR_TIMER_001_28] = 1280,
+ [IB_RNR_TIMER_001_92] = 1920,
+ [IB_RNR_TIMER_002_56] = 2560,
+ [IB_RNR_TIMER_003_84] = 3840,
+ [IB_RNR_TIMER_005_12] = 5120,
+ [IB_RNR_TIMER_007_68] = 7680,
+ [IB_RNR_TIMER_010_24] = 10240,
+ [IB_RNR_TIMER_015_36] = 15360,
+ [IB_RNR_TIMER_020_48] = 20480,
+ [IB_RNR_TIMER_030_72] = 30720,
+ [IB_RNR_TIMER_040_96] = 40960,
+ [IB_RNR_TIMER_061_44] = 61410,
+ [IB_RNR_TIMER_081_92] = 81920,
+ [IB_RNR_TIMER_122_88] = 122880,
+ [IB_RNR_TIMER_163_84] = 163840,
+ [IB_RNR_TIMER_245_76] = 245760,
+ [IB_RNR_TIMER_327_68] = 327680,
+ [IB_RNR_TIMER_491_52] = 491520,
+};
+
+static inline unsigned long rnrnak_jiffies(u8 timeout)
+{
+ return max_t(unsigned long,
+ usecs_to_jiffies(rnrnak_usec[timeout]), 1);
+}
+
+static enum ib_wc_opcode wr_to_wc_opcode(enum ib_wr_opcode opcode)
+{
+ switch (opcode) {
+ case IB_WR_RDMA_WRITE: return IB_WC_RDMA_WRITE;
+ case IB_WR_RDMA_WRITE_WITH_IMM: return IB_WC_RDMA_WRITE;
+ case IB_WR_SEND: return IB_WC_SEND;
+ case IB_WR_SEND_WITH_IMM: return IB_WC_SEND;
+ case IB_WR_RDMA_READ: return IB_WC_RDMA_READ;
+ case IB_WR_ATOMIC_CMP_AND_SWP: return IB_WC_COMP_SWAP;
+ case IB_WR_ATOMIC_FETCH_AND_ADD: return IB_WC_FETCH_ADD;
+ case IB_WR_LSO: return IB_WC_LSO;
+ case IB_WR_SEND_WITH_INV: return IB_WC_SEND;
+ case IB_WR_RDMA_READ_WITH_INV: return IB_WC_RDMA_READ;
+ case IB_WR_LOCAL_INV: return IB_WC_LOCAL_INV;
+ case IB_WR_REG_MR: return IB_WC_REG_MR;
+
+ default:
+ return 0xff;
+ }
+}
+
+void retransmit_timer(unsigned long data)
+{
+ struct rxe_qp *qp = (struct rxe_qp *)data;
+
+ if (qp->valid) {
+ qp->comp.timeout = 1;
+ rxe_run_task(&qp->comp.task, 1);
+ }
+}
+
+void rxe_comp_queue_pkt(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct sk_buff *skb)
+{
+ int must_sched;
+
+ skb_queue_tail(&qp->resp_pkts, skb);
+
+ must_sched = skb_queue_len(&qp->resp_pkts) > 1;
+ rxe_run_task(&qp->comp.task, must_sched);
+}
+
+static inline enum comp_state get_wqe(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe **wqe_p)
+{
+ struct rxe_send_wqe *wqe;
+
+ /* we come here whether or not we found a response packet to see if
+ * there are any posted WQEs
+ */
+ wqe = queue_head(qp->sq.queue);
+ *wqe_p = wqe;
+
+ /* no WQE or requester has not started it yet */
+ if (!wqe || wqe->state == wqe_state_posted)
+ return pkt ? COMPST_DONE : COMPST_EXIT;
+
+ /* WQE does not require an ack */
+ if (wqe->state == wqe_state_done)
+ return COMPST_COMP_WQE;
+
+ /* WQE caused an error */
+ if (wqe->state == wqe_state_error)
+ return COMPST_ERROR;
+
+ /* we have a WQE, if we also have an ack check its PSN */
+ return pkt ? COMPST_CHECK_PSN : COMPST_EXIT;
+}
+
+static inline void reset_retry_counters(struct rxe_qp *qp)
+{
+ qp->comp.retry_cnt = qp->attr.retry_cnt;
+ qp->comp.rnr_retry = qp->attr.rnr_retry;
+}
+
+static inline enum comp_state check_psn(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ s32 diff;
+
+ /* check to see if response is past the oldest WQE. if it is, complete
+ * send/write or error read/atomic
+ */
+ diff = psn_compare(pkt->psn, wqe->last_psn);
+ if (diff > 0) {
+ if (wqe->state == wqe_state_pending) {
+ if (wqe->mask & WR_ATOMIC_OR_READ_MASK)
+ return COMPST_ERROR_RETRY;
+
+ reset_retry_counters(qp);
+ return COMPST_COMP_WQE;
+ } else {
+ return COMPST_DONE;
+ }
+ }
+
+ /* compare response packet to expected response */
+ diff = psn_compare(pkt->psn, qp->comp.psn);
+ if (diff < 0) {
+ /* response is most likely a retried packet if it matches an
+ * uncompleted WQE go complete it else ignore it
+ */
+ if (pkt->psn == wqe->last_psn)
+ return COMPST_COMP_ACK;
+ else
+ return COMPST_DONE;
+ } else if ((diff > 0) && (wqe->mask & WR_ATOMIC_OR_READ_MASK)) {
+ return COMPST_ERROR_RETRY;
+ } else {
+ return COMPST_CHECK_ACK;
+ }
+}
+
+static inline enum comp_state check_ack(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ unsigned int mask = pkt->mask;
+ u8 syn;
+
+ /* Check the sequence only */
+ switch (qp->comp.opcode) {
+ case -1:
+ /* Will catch all *_ONLY cases. */
+ if (!(mask & RXE_START_MASK))
+ return COMPST_ERROR;
+
+ break;
+
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST:
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE:
+ if (pkt->opcode != IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE &&
+ pkt->opcode != IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST) {
+ return COMPST_ERROR;
+ }
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ /* Check operation validity. */
+ switch (pkt->opcode) {
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST:
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST:
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY:
+ syn = aeth_syn(pkt);
+
+ if ((syn & AETH_TYPE_MASK) != AETH_ACK)
+ return COMPST_ERROR;
+
+ /* Fall through (IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE
+ * doesn't have an AETH)
+ */
+ case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE:
+ if (wqe->wr.opcode != IB_WR_RDMA_READ &&
+ wqe->wr.opcode != IB_WR_RDMA_READ_WITH_INV) {
+ return COMPST_ERROR;
+ }
+ reset_retry_counters(qp);
+ return COMPST_READ;
+
+ case IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE:
+ syn = aeth_syn(pkt);
+
+ if ((syn & AETH_TYPE_MASK) != AETH_ACK)
+ return COMPST_ERROR;
+
+ if (wqe->wr.opcode != IB_WR_ATOMIC_CMP_AND_SWP &&
+ wqe->wr.opcode != IB_WR_ATOMIC_FETCH_AND_ADD)
+ return COMPST_ERROR;
+ reset_retry_counters(qp);
+ return COMPST_ATOMIC;
+
+ case IB_OPCODE_RC_ACKNOWLEDGE:
+ syn = aeth_syn(pkt);
+ switch (syn & AETH_TYPE_MASK) {
+ case AETH_ACK:
+ reset_retry_counters(qp);
+ return COMPST_WRITE_SEND;
+
+ case AETH_RNR_NAK:
+ return COMPST_RNR_RETRY;
+
+ case AETH_NAK:
+ switch (syn) {
+ case AETH_NAK_PSN_SEQ_ERROR:
+ /* a nak implicitly acks all packets with psns
+ * before
+ */
+ if (psn_compare(pkt->psn, qp->comp.psn) > 0) {
+ qp->comp.psn = pkt->psn;
+ if (qp->req.wait_psn) {
+ qp->req.wait_psn = 0;
+ rxe_run_task(&qp->req.task, 1);
+ }
+ }
+ return COMPST_ERROR_RETRY;
+
+ case AETH_NAK_INVALID_REQ:
+ wqe->status = IB_WC_REM_INV_REQ_ERR;
+ return COMPST_ERROR;
+
+ case AETH_NAK_REM_ACC_ERR:
+ wqe->status = IB_WC_REM_ACCESS_ERR;
+ return COMPST_ERROR;
+
+ case AETH_NAK_REM_OP_ERR:
+ wqe->status = IB_WC_REM_OP_ERR;
+ return COMPST_ERROR;
+
+ default:
+ pr_warn("unexpected nak %x\n", syn);
+ wqe->status = IB_WC_REM_OP_ERR;
+ return COMPST_ERROR;
+ }
+
+ default:
+ return COMPST_ERROR;
+ }
+ break;
+
+ default:
+ pr_warn("unexpected opcode\n");
+ }
+
+ return COMPST_ERROR;
+}
+
+static inline enum comp_state do_read(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ int ret;
+
+ ret = copy_data(rxe, qp->pd, IB_ACCESS_LOCAL_WRITE,
+ &wqe->dma, payload_addr(pkt),
+ payload_size(pkt), to_mem_obj, NULL);
+ if (ret)
+ return COMPST_ERROR;
+
+ if (wqe->dma.resid == 0 && (pkt->mask & RXE_END_MASK))
+ return COMPST_COMP_ACK;
+ else
+ return COMPST_UPDATE_COMP;
+}
+
+static inline enum comp_state do_atomic(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ int ret;
+
+ u64 atomic_orig = atmack_orig(pkt);
+
+ ret = copy_data(rxe, qp->pd, IB_ACCESS_LOCAL_WRITE,
+ &wqe->dma, &atomic_orig,
+ sizeof(u64), to_mem_obj, NULL);
+ if (ret)
+ return COMPST_ERROR;
+ else
+ return COMPST_COMP_ACK;
+}
+
+static void make_send_cqe(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
+ struct rxe_cqe *cqe)
+{
+ memset(cqe, 0, sizeof(*cqe));
+
+ if (!qp->is_user) {
+ struct ib_wc *wc = &cqe->ibwc;
+
+ wc->wr_id = wqe->wr.wr_id;
+ wc->status = wqe->status;
+ wc->opcode = wr_to_wc_opcode(wqe->wr.opcode);
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ wqe->wr.opcode == IB_WR_SEND_WITH_IMM)
+ wc->wc_flags = IB_WC_WITH_IMM;
+ wc->byte_len = wqe->dma.length;
+ wc->qp = &qp->ibqp;
+ } else {
+ struct ib_uverbs_wc *uwc = &cqe->uibwc;
+
+ uwc->wr_id = wqe->wr.wr_id;
+ uwc->status = wqe->status;
+ uwc->opcode = wr_to_wc_opcode(wqe->wr.opcode);
+ if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+ wqe->wr.opcode == IB_WR_SEND_WITH_IMM)
+ uwc->wc_flags = IB_WC_WITH_IMM;
+ uwc->byte_len = wqe->dma.length;
+ uwc->qp_num = qp->ibqp.qp_num;
+ }
+}
+
+static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
+{
+ struct rxe_cqe cqe;
+
+ if ((qp->sq_sig_type == IB_SIGNAL_ALL_WR) ||
+ (wqe->wr.send_flags & IB_SEND_SIGNALED) ||
+ (qp->req.state == QP_STATE_ERROR)) {
+ make_send_cqe(qp, wqe, &cqe);
+ rxe_cq_post(qp->scq, &cqe, 0);
+ }
+
+ advance_consumer(qp->sq.queue);
+
+ /*
+ * we completed something so let req run again
+ * if it is trying to fence
+ */
+ if (qp->req.wait_fence) {
+ qp->req.wait_fence = 0;
+ rxe_run_task(&qp->req.task, 1);
+ }
+}
+
+static inline enum comp_state complete_ack(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ unsigned long flags;
+
+ if (wqe->has_rd_atomic) {
+ wqe->has_rd_atomic = 0;
+ atomic_inc(&qp->req.rd_atomic);
+ if (qp->req.need_rd_atomic) {
+ qp->comp.timeout_retry = 0;
+ qp->req.need_rd_atomic = 0;
+ rxe_run_task(&qp->req.task, 1);
+ }
+ }
+
+ if (unlikely(qp->req.state == QP_STATE_DRAIN)) {
+ /* state_lock used by requester & completer */
+ spin_lock_irqsave(&qp->state_lock, flags);
+ if ((qp->req.state == QP_STATE_DRAIN) &&
+ (qp->comp.psn == qp->req.psn)) {
+ qp->req.state = QP_STATE_DRAINED;
+ spin_unlock_irqrestore(&qp->state_lock, flags);
+
+ if (qp->ibqp.event_handler) {
+ struct ib_event ev;
+
+ ev.device = qp->ibqp.device;
+ ev.element.qp = &qp->ibqp;
+ ev.event = IB_EVENT_SQ_DRAINED;
+ qp->ibqp.event_handler(&ev,
+ qp->ibqp.qp_context);
+ }
+ } else {
+ spin_unlock_irqrestore(&qp->state_lock, flags);
+ }
+ }
+
+ do_complete(qp, wqe);
+
+ if (psn_compare(pkt->psn, qp->comp.psn) >= 0)
+ return COMPST_UPDATE_COMP;
+ else
+ return COMPST_DONE;
+}
+
+static inline enum comp_state complete_wqe(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_send_wqe *wqe)
+{
+ qp->comp.opcode = -1;
+
+ if (pkt) {
+ if (psn_compare(pkt->psn, qp->comp.psn) >= 0)
+ qp->comp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
+
+ if (qp->req.wait_psn) {
+ qp->req.wait_psn = 0;
+ rxe_run_task(&qp->req.task, 1);
+ }
+ }
+
+ do_complete(qp, wqe);
+
+ return COMPST_GET_WQE;
+}
+
+int rxe_completer(void *arg)
+{
+ struct rxe_qp *qp = (struct rxe_qp *)arg;
+ struct rxe_send_wqe *wqe = wqe;
+ struct sk_buff *skb = NULL;
+ struct rxe_pkt_info *pkt = NULL;
+ enum comp_state state;
+
+ if (!qp->valid) {
+ while ((skb = skb_dequeue(&qp->resp_pkts))) {
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ }
+ skb = NULL;
+ pkt = NULL;
+
+ while (queue_head(qp->sq.queue))
+ advance_consumer(qp->sq.queue);
+
+ goto exit;
+ }
+
+ if (qp->req.state == QP_STATE_ERROR) {
+ while ((skb = skb_dequeue(&qp->resp_pkts))) {
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ }
+ skb = NULL;
+ pkt = NULL;
+
+ while ((wqe = queue_head(qp->sq.queue))) {
+ wqe->status = IB_WC_WR_FLUSH_ERR;
+ do_complete(qp, wqe);
+ }
+
+ goto exit;
+ }
+
+ if (qp->req.state == QP_STATE_RESET) {
+ while ((skb = skb_dequeue(&qp->resp_pkts))) {
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ }
+ skb = NULL;
+ pkt = NULL;
+
+ while (queue_head(qp->sq.queue))
+ advance_consumer(qp->sq.queue);
+
+ goto exit;
+ }
+
+ if (qp->comp.timeout) {
+ qp->comp.timeout_retry = 1;
+ qp->comp.timeout = 0;
+ } else {
+ qp->comp.timeout_retry = 0;
+ }
+
+ if (qp->req.need_retry)
+ goto exit;
+
+ state = COMPST_GET_ACK;
+
+ while (1) {
+ pr_debug("state = %s\n", comp_state_name[state]);
+ switch (state) {
+ case COMPST_GET_ACK:
+ skb = skb_dequeue(&qp->resp_pkts);
+ if (skb) {
+ pkt = SKB_TO_PKT(skb);
+ qp->comp.timeout_retry = 0;
+ }
+ state = COMPST_GET_WQE;
+ break;
+
+ case COMPST_GET_WQE:
+ state = get_wqe(qp, pkt, &wqe);
+ break;
+
+ case COMPST_CHECK_PSN:
+ state = check_psn(qp, pkt, wqe);
+ break;
+
+ case COMPST_CHECK_ACK:
+ state = check_ack(qp, pkt, wqe);
+ break;
+
+ case COMPST_READ:
+ state = do_read(qp, pkt, wqe);
+ break;
+
+ case COMPST_ATOMIC:
+ state = do_atomic(qp, pkt, wqe);
+ break;
+
+ case COMPST_WRITE_SEND:
+ if (wqe->state == wqe_state_pending &&
+ wqe->last_psn == pkt->psn)
+ state = COMPST_COMP_ACK;
+ else
+ state = COMPST_UPDATE_COMP;
+ break;
+
+ case COMPST_COMP_ACK:
+ state = complete_ack(qp, pkt, wqe);
+ break;
+
+ case COMPST_COMP_WQE:
+ state = complete_wqe(qp, pkt, wqe);
+ break;
+
+ case COMPST_UPDATE_COMP:
+ if (pkt->mask & RXE_END_MASK)
+ qp->comp.opcode = -1;
+ else
+ qp->comp.opcode = pkt->opcode;
+
+ if (psn_compare(pkt->psn, qp->comp.psn) >= 0)
+ qp->comp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
+
+ if (qp->req.wait_psn) {
+ qp->req.wait_psn = 0;
+ rxe_run_task(&qp->req.task, 1);
+ }
+
+ state = COMPST_DONE;
+ break;
+
+ case COMPST_DONE:
+ if (pkt) {
+ rxe_drop_ref(pkt->qp);
+ kfree_skb(skb);
+ }
+ goto done;
+
+ case COMPST_EXIT:
+ if (qp->comp.timeout_retry && wqe) {
+ state = COMPST_ERROR_RETRY;
+ break;
+ }
+
+ /* re reset the timeout counter if
+ * (1) QP is type RC
+ * (2) the QP is alive
+ * (3) there is a packet sent by the requester that
+ * might be acked (we still might get spurious
+ * timeouts but try to keep them as few as possible)
+ * (4) the timeout parameter is set
+ */
+ if ((qp_type(qp) == IB_QPT_RC) &&
+ (qp->req.state == QP_STATE_READY) &&
+ (psn_compare(qp->req.psn, qp->comp.psn) > 0) &&
+ qp->qp_timeout_jiffies)
+ mod_timer(&qp->retrans_timer,
+ jiffies + qp->qp_timeout_jiffies);
+ goto exit;
+
+ case COMPST_ERROR_RETRY:
+ /* we come here if the retry timer fired and we did
+ * not receive a response packet. try to retry the send
+ * queue if that makes sense and the limits have not
+ * been exceeded. remember that some timeouts are
+ * spurious since we do not reset the timer but kick
+ * it down the road or let it expire
+ */
+
+ /* there is nothing to retry in this case */
+ if (!wqe || (wqe->state == wqe_state_posted))
+ goto exit;
+
+ if (qp->comp.retry_cnt > 0) {
+ if (qp->comp.retry_cnt != 7)
+ qp->comp.retry_cnt--;
+
+ /* no point in retrying if we have already
+ * seen the last ack that the requester could
+ * have caused
+ */
+ if (psn_compare(qp->req.psn,
+ qp->comp.psn) > 0) {
+ /* tell the requester to retry the
+ * send send queue next time around
+ */
+ qp->req.need_retry = 1;
+ rxe_run_task(&qp->req.task, 1);
+ }
+ goto exit;
+ } else {
+ wqe->status = IB_WC_RETRY_EXC_ERR;
+ state = COMPST_ERROR;
+ }
+ break;
+
+ case COMPST_RNR_RETRY:
+ if (qp->comp.rnr_retry > 0) {
+ if (qp->comp.rnr_retry != 7)
+ qp->comp.rnr_retry--;
+
+ qp->req.need_retry = 1;
+ pr_debug("set rnr nak timer\n");
+ mod_timer(&qp->rnr_nak_timer,
+ jiffies + rnrnak_jiffies(aeth_syn(pkt)
+ & ~AETH_TYPE_MASK));
+ goto exit;
+ } else {
+ wqe->status = IB_WC_RNR_RETRY_EXC_ERR;
+ state = COMPST_ERROR;
+ }
+ break;
+
+ case COMPST_ERROR:
+ do_complete(qp, wqe);
+ rxe_qp_error(qp);
+ goto exit;
+ }
+ }
+
+exit:
+ /* we come here if we are done with processing and want the task to
+ * exit from the loop calling us
+ */
+ return -EAGAIN;
+
+done:
+ /* we come here if we have processed a packet we want the task to call
+ * us again to see if there is anything else to do
+ */
+ return 0;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_cq.c b/drivers/infiniband/sw/rxe/rxe_cq.c
new file mode 100644
index 000000000000..e5e6a5e7dee9
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_cq.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,
+ int cqe, int comp_vector, struct ib_udata *udata)
+{
+ int count;
+
+ if (cqe <= 0) {
+ pr_warn("cqe(%d) <= 0\n", cqe);
+ goto err1;
+ }
+
+ if (cqe > rxe->attr.max_cqe) {
+ pr_warn("cqe(%d) > max_cqe(%d)\n",
+ cqe, rxe->attr.max_cqe);
+ goto err1;
+ }
+
+ if (cq) {
+ count = queue_count(cq->queue);
+ if (cqe < count) {
+ pr_warn("cqe(%d) < current # elements in queue (%d)",
+ cqe, count);
+ goto err1;
+ }
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static void rxe_send_complete(unsigned long data)
+{
+ struct rxe_cq *cq = (struct rxe_cq *)data;
+
+ cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+}
+
+int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,
+ int comp_vector, struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ int err;
+
+ cq->queue = rxe_queue_init(rxe, &cqe,
+ sizeof(struct rxe_cqe));
+ if (!cq->queue) {
+ pr_warn("unable to create cq\n");
+ return -ENOMEM;
+ }
+
+ err = do_mmap_info(rxe, udata, false, context, cq->queue->buf,
+ cq->queue->buf_size, &cq->queue->ip);
+ if (err) {
+ kvfree(cq->queue->buf);
+ kfree(cq->queue);
+ return err;
+ }
+
+ if (udata)
+ cq->is_user = 1;
+
+ tasklet_init(&cq->comp_task, rxe_send_complete, (unsigned long)cq);
+
+ spin_lock_init(&cq->cq_lock);
+ cq->ibcq.cqe = cqe;
+ return 0;
+}
+
+int rxe_cq_resize_queue(struct rxe_cq *cq, int cqe, struct ib_udata *udata)
+{
+ int err;
+
+ err = rxe_queue_resize(cq->queue, (unsigned int *)&cqe,
+ sizeof(struct rxe_cqe),
+ cq->queue->ip ? cq->queue->ip->context : NULL,
+ udata, NULL, &cq->cq_lock);
+ if (!err)
+ cq->ibcq.cqe = cqe;
+
+ return err;
+}
+
+int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited)
+{
+ struct ib_event ev;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->cq_lock, flags);
+
+ if (unlikely(queue_full(cq->queue))) {
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+ if (cq->ibcq.event_handler) {
+ ev.device = cq->ibcq.device;
+ ev.element.cq = &cq->ibcq;
+ ev.event = IB_EVENT_CQ_ERR;
+ cq->ibcq.event_handler(&ev, cq->ibcq.cq_context);
+ }
+
+ return -EBUSY;
+ }
+
+ memcpy(producer_addr(cq->queue), cqe, sizeof(*cqe));
+
+ /* make sure all changes to the CQ are written before we update the
+ * producer pointer
+ */
+ smp_wmb();
+
+ advance_producer(cq->queue);
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+
+ if ((cq->notify == IB_CQ_NEXT_COMP) ||
+ (cq->notify == IB_CQ_SOLICITED && solicited)) {
+ cq->notify = 0;
+ tasklet_schedule(&cq->comp_task);
+ }
+
+ return 0;
+}
+
+void rxe_cq_cleanup(void *arg)
+{
+ struct rxe_cq *cq = arg;
+
+ if (cq->queue)
+ rxe_queue_cleanup(cq->queue);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_dma.c b/drivers/infiniband/sw/rxe/rxe_dma.c
new file mode 100644
index 000000000000..7634c1a81b2b
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_dma.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+#define DMA_BAD_ADDER ((u64)0)
+
+static int rxe_mapping_error(struct ib_device *dev, u64 dma_addr)
+{
+ return dma_addr == DMA_BAD_ADDER;
+}
+
+static u64 rxe_dma_map_single(struct ib_device *dev,
+ void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ WARN_ON(!valid_dma_direction(direction));
+ return (uintptr_t)cpu_addr;
+}
+
+static void rxe_dma_unmap_single(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ WARN_ON(!valid_dma_direction(direction));
+}
+
+static u64 rxe_dma_map_page(struct ib_device *dev,
+ struct page *page,
+ unsigned long offset,
+ size_t size, enum dma_data_direction direction)
+{
+ u64 addr;
+
+ WARN_ON(!valid_dma_direction(direction));
+
+ if (offset + size > PAGE_SIZE) {
+ addr = DMA_BAD_ADDER;
+ goto done;
+ }
+
+ addr = (uintptr_t)page_address(page);
+ if (addr)
+ addr += offset;
+
+done:
+ return addr;
+}
+
+static void rxe_dma_unmap_page(struct ib_device *dev,
+ u64 addr, size_t size,
+ enum dma_data_direction direction)
+{
+ WARN_ON(!valid_dma_direction(direction));
+}
+
+static int rxe_map_sg(struct ib_device *dev, struct scatterlist *sgl,
+ int nents, enum dma_data_direction direction)
+{
+ struct scatterlist *sg;
+ u64 addr;
+ int i;
+ int ret = nents;
+
+ WARN_ON(!valid_dma_direction(direction));
+
+ for_each_sg(sgl, sg, nents, i) {
+ addr = (uintptr_t)page_address(sg_page(sg));
+ if (!addr) {
+ ret = 0;
+ break;
+ }
+ sg->dma_address = addr + sg->offset;
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ sg->dma_length = sg->length;
+#endif
+ }
+
+ return ret;
+}
+
+static void rxe_unmap_sg(struct ib_device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ WARN_ON(!valid_dma_direction(direction));
+}
+
+static void rxe_sync_single_for_cpu(struct ib_device *dev,
+ u64 addr,
+ size_t size, enum dma_data_direction dir)
+{
+}
+
+static void rxe_sync_single_for_device(struct ib_device *dev,
+ u64 addr,
+ size_t size, enum dma_data_direction dir)
+{
+}
+
+static void *rxe_dma_alloc_coherent(struct ib_device *dev, size_t size,
+ u64 *dma_handle, gfp_t flag)
+{
+ struct page *p;
+ void *addr = NULL;
+
+ p = alloc_pages(flag, get_order(size));
+ if (p)
+ addr = page_address(p);
+
+ if (dma_handle)
+ *dma_handle = (uintptr_t)addr;
+
+ return addr;
+}
+
+static void rxe_dma_free_coherent(struct ib_device *dev, size_t size,
+ void *cpu_addr, u64 dma_handle)
+{
+ free_pages((unsigned long)cpu_addr, get_order(size));
+}
+
+struct ib_dma_mapping_ops rxe_dma_mapping_ops = {
+ .mapping_error = rxe_mapping_error,
+ .map_single = rxe_dma_map_single,
+ .unmap_single = rxe_dma_unmap_single,
+ .map_page = rxe_dma_map_page,
+ .unmap_page = rxe_dma_unmap_page,
+ .map_sg = rxe_map_sg,
+ .unmap_sg = rxe_unmap_sg,
+ .sync_single_for_cpu = rxe_sync_single_for_cpu,
+ .sync_single_for_device = rxe_sync_single_for_device,
+ .alloc_coherent = rxe_dma_alloc_coherent,
+ .free_coherent = rxe_dma_free_coherent
+};
diff --git a/drivers/infiniband/sw/rxe/rxe_hdr.h b/drivers/infiniband/sw/rxe/rxe_hdr.h
new file mode 100644
index 000000000000..d57b5e956ceb
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_hdr.h
@@ -0,0 +1,952 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_HDR_H
+#define RXE_HDR_H
+
+/* extracted information about a packet carried in an sk_buff struct fits in
+ * the skbuff cb array. Must be at most 48 bytes. stored in control block of
+ * sk_buff for received packets.
+ */
+struct rxe_pkt_info {
+ struct rxe_dev *rxe; /* device that owns packet */
+ struct rxe_qp *qp; /* qp that owns packet */
+ struct rxe_send_wqe *wqe; /* send wqe */
+ u8 *hdr; /* points to bth */
+ u32 mask; /* useful info about pkt */
+ u32 psn; /* bth psn of packet */
+ u16 pkey_index; /* partition of pkt */
+ u16 paylen; /* length of bth - icrc */
+ u8 port_num; /* port pkt received on */
+ u8 opcode; /* bth opcode of packet */
+ u8 offset; /* bth offset from pkt->hdr */
+};
+
+/* Macros should be used only for received skb */
+#define SKB_TO_PKT(skb) ((struct rxe_pkt_info *)(skb)->cb)
+#define PKT_TO_SKB(pkt) container_of((void *)(pkt), struct sk_buff, cb)
+
+/*
+ * IBA header types and methods
+ *
+ * Some of these are for reference and completeness only since
+ * rxe does not currently support RD transport
+ * most of this could be moved into IB core. ib_pack.h has
+ * part of this but is incomplete
+ *
+ * Header specific routines to insert/extract values to/from headers
+ * the routines that are named __hhh_(set_)fff() take a pointer to a
+ * hhh header and get(set) the fff field. The routines named
+ * hhh_(set_)fff take a packet info struct and find the
+ * header and field based on the opcode in the packet.
+ * Conversion to/from network byte order from cpu order is also done.
+ */
+
+#define RXE_ICRC_SIZE (4)
+#define RXE_MAX_HDR_LENGTH (80)
+
+/******************************************************************************
+ * Base Transport Header
+ ******************************************************************************/
+struct rxe_bth {
+ u8 opcode;
+ u8 flags;
+ __be16 pkey;
+ __be32 qpn;
+ __be32 apsn;
+};
+
+#define BTH_TVER (0)
+#define BTH_DEF_PKEY (0xffff)
+
+#define BTH_SE_MASK (0x80)
+#define BTH_MIG_MASK (0x40)
+#define BTH_PAD_MASK (0x30)
+#define BTH_TVER_MASK (0x0f)
+#define BTH_FECN_MASK (0x80000000)
+#define BTH_BECN_MASK (0x40000000)
+#define BTH_RESV6A_MASK (0x3f000000)
+#define BTH_QPN_MASK (0x00ffffff)
+#define BTH_ACK_MASK (0x80000000)
+#define BTH_RESV7_MASK (0x7f000000)
+#define BTH_PSN_MASK (0x00ffffff)
+
+static inline u8 __bth_opcode(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return bth->opcode;
+}
+
+static inline void __bth_set_opcode(void *arg, u8 opcode)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->opcode = opcode;
+}
+
+static inline u8 __bth_se(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return 0 != (BTH_SE_MASK & bth->flags);
+}
+
+static inline void __bth_set_se(void *arg, int se)
+{
+ struct rxe_bth *bth = arg;
+
+ if (se)
+ bth->flags |= BTH_SE_MASK;
+ else
+ bth->flags &= ~BTH_SE_MASK;
+}
+
+static inline u8 __bth_mig(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return 0 != (BTH_MIG_MASK & bth->flags);
+}
+
+static inline void __bth_set_mig(void *arg, u8 mig)
+{
+ struct rxe_bth *bth = arg;
+
+ if (mig)
+ bth->flags |= BTH_MIG_MASK;
+ else
+ bth->flags &= ~BTH_MIG_MASK;
+}
+
+static inline u8 __bth_pad(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return (BTH_PAD_MASK & bth->flags) >> 4;
+}
+
+static inline void __bth_set_pad(void *arg, u8 pad)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->flags = (BTH_PAD_MASK & (pad << 4)) |
+ (~BTH_PAD_MASK & bth->flags);
+}
+
+static inline u8 __bth_tver(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return BTH_TVER_MASK & bth->flags;
+}
+
+static inline void __bth_set_tver(void *arg, u8 tver)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->flags = (BTH_TVER_MASK & tver) |
+ (~BTH_TVER_MASK & bth->flags);
+}
+
+static inline u16 __bth_pkey(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return be16_to_cpu(bth->pkey);
+}
+
+static inline void __bth_set_pkey(void *arg, u16 pkey)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->pkey = cpu_to_be16(pkey);
+}
+
+static inline u32 __bth_qpn(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return BTH_QPN_MASK & be32_to_cpu(bth->qpn);
+}
+
+static inline void __bth_set_qpn(void *arg, u32 qpn)
+{
+ struct rxe_bth *bth = arg;
+ u32 resvqpn = be32_to_cpu(bth->qpn);
+
+ bth->qpn = cpu_to_be32((BTH_QPN_MASK & qpn) |
+ (~BTH_QPN_MASK & resvqpn));
+}
+
+static inline int __bth_fecn(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return 0 != (cpu_to_be32(BTH_FECN_MASK) & bth->qpn);
+}
+
+static inline void __bth_set_fecn(void *arg, int fecn)
+{
+ struct rxe_bth *bth = arg;
+
+ if (fecn)
+ bth->qpn |= cpu_to_be32(BTH_FECN_MASK);
+ else
+ bth->qpn &= ~cpu_to_be32(BTH_FECN_MASK);
+}
+
+static inline int __bth_becn(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return 0 != (cpu_to_be32(BTH_BECN_MASK) & bth->qpn);
+}
+
+static inline void __bth_set_becn(void *arg, int becn)
+{
+ struct rxe_bth *bth = arg;
+
+ if (becn)
+ bth->qpn |= cpu_to_be32(BTH_BECN_MASK);
+ else
+ bth->qpn &= ~cpu_to_be32(BTH_BECN_MASK);
+}
+
+static inline u8 __bth_resv6a(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return (BTH_RESV6A_MASK & be32_to_cpu(bth->qpn)) >> 24;
+}
+
+static inline void __bth_set_resv6a(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->qpn = cpu_to_be32(~BTH_RESV6A_MASK);
+}
+
+static inline int __bth_ack(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return 0 != (cpu_to_be32(BTH_ACK_MASK) & bth->apsn);
+}
+
+static inline void __bth_set_ack(void *arg, int ack)
+{
+ struct rxe_bth *bth = arg;
+
+ if (ack)
+ bth->apsn |= cpu_to_be32(BTH_ACK_MASK);
+ else
+ bth->apsn &= ~cpu_to_be32(BTH_ACK_MASK);
+}
+
+static inline void __bth_set_resv7(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ bth->apsn &= ~cpu_to_be32(BTH_RESV7_MASK);
+}
+
+static inline u32 __bth_psn(void *arg)
+{
+ struct rxe_bth *bth = arg;
+
+ return BTH_PSN_MASK & be32_to_cpu(bth->apsn);
+}
+
+static inline void __bth_set_psn(void *arg, u32 psn)
+{
+ struct rxe_bth *bth = arg;
+ u32 apsn = be32_to_cpu(bth->apsn);
+
+ bth->apsn = cpu_to_be32((BTH_PSN_MASK & psn) |
+ (~BTH_PSN_MASK & apsn));
+}
+
+static inline u8 bth_opcode(struct rxe_pkt_info *pkt)
+{
+ return __bth_opcode(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_opcode(struct rxe_pkt_info *pkt, u8 opcode)
+{
+ __bth_set_opcode(pkt->hdr + pkt->offset, opcode);
+}
+
+static inline u8 bth_se(struct rxe_pkt_info *pkt)
+{
+ return __bth_se(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_se(struct rxe_pkt_info *pkt, int se)
+{
+ __bth_set_se(pkt->hdr + pkt->offset, se);
+}
+
+static inline u8 bth_mig(struct rxe_pkt_info *pkt)
+{
+ return __bth_mig(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_mig(struct rxe_pkt_info *pkt, u8 mig)
+{
+ __bth_set_mig(pkt->hdr + pkt->offset, mig);
+}
+
+static inline u8 bth_pad(struct rxe_pkt_info *pkt)
+{
+ return __bth_pad(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_pad(struct rxe_pkt_info *pkt, u8 pad)
+{
+ __bth_set_pad(pkt->hdr + pkt->offset, pad);
+}
+
+static inline u8 bth_tver(struct rxe_pkt_info *pkt)
+{
+ return __bth_tver(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_tver(struct rxe_pkt_info *pkt, u8 tver)
+{
+ __bth_set_tver(pkt->hdr + pkt->offset, tver);
+}
+
+static inline u16 bth_pkey(struct rxe_pkt_info *pkt)
+{
+ return __bth_pkey(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_pkey(struct rxe_pkt_info *pkt, u16 pkey)
+{
+ __bth_set_pkey(pkt->hdr + pkt->offset, pkey);
+}
+
+static inline u32 bth_qpn(struct rxe_pkt_info *pkt)
+{
+ return __bth_qpn(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_qpn(struct rxe_pkt_info *pkt, u32 qpn)
+{
+ __bth_set_qpn(pkt->hdr + pkt->offset, qpn);
+}
+
+static inline int bth_fecn(struct rxe_pkt_info *pkt)
+{
+ return __bth_fecn(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_fecn(struct rxe_pkt_info *pkt, int fecn)
+{
+ __bth_set_fecn(pkt->hdr + pkt->offset, fecn);
+}
+
+static inline int bth_becn(struct rxe_pkt_info *pkt)
+{
+ return __bth_becn(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_becn(struct rxe_pkt_info *pkt, int becn)
+{
+ __bth_set_becn(pkt->hdr + pkt->offset, becn);
+}
+
+static inline u8 bth_resv6a(struct rxe_pkt_info *pkt)
+{
+ return __bth_resv6a(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_resv6a(struct rxe_pkt_info *pkt)
+{
+ __bth_set_resv6a(pkt->hdr + pkt->offset);
+}
+
+static inline int bth_ack(struct rxe_pkt_info *pkt)
+{
+ return __bth_ack(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_ack(struct rxe_pkt_info *pkt, int ack)
+{
+ __bth_set_ack(pkt->hdr + pkt->offset, ack);
+}
+
+static inline void bth_set_resv7(struct rxe_pkt_info *pkt)
+{
+ __bth_set_resv7(pkt->hdr + pkt->offset);
+}
+
+static inline u32 bth_psn(struct rxe_pkt_info *pkt)
+{
+ return __bth_psn(pkt->hdr + pkt->offset);
+}
+
+static inline void bth_set_psn(struct rxe_pkt_info *pkt, u32 psn)
+{
+ __bth_set_psn(pkt->hdr + pkt->offset, psn);
+}
+
+static inline void bth_init(struct rxe_pkt_info *pkt, u8 opcode, int se,
+ int mig, int pad, u16 pkey, u32 qpn, int ack_req,
+ u32 psn)
+{
+ struct rxe_bth *bth = (struct rxe_bth *)(pkt->hdr + pkt->offset);
+
+ bth->opcode = opcode;
+ bth->flags = (pad << 4) & BTH_PAD_MASK;
+ if (se)
+ bth->flags |= BTH_SE_MASK;
+ if (mig)
+ bth->flags |= BTH_MIG_MASK;
+ bth->pkey = cpu_to_be16(pkey);
+ bth->qpn = cpu_to_be32(qpn & BTH_QPN_MASK);
+ psn &= BTH_PSN_MASK;
+ if (ack_req)
+ psn |= BTH_ACK_MASK;
+ bth->apsn = cpu_to_be32(psn);
+}
+
+/******************************************************************************
+ * Reliable Datagram Extended Transport Header
+ ******************************************************************************/
+struct rxe_rdeth {
+ __be32 een;
+};
+
+#define RDETH_EEN_MASK (0x00ffffff)
+
+static inline u8 __rdeth_een(void *arg)
+{
+ struct rxe_rdeth *rdeth = arg;
+
+ return RDETH_EEN_MASK & be32_to_cpu(rdeth->een);
+}
+
+static inline void __rdeth_set_een(void *arg, u32 een)
+{
+ struct rxe_rdeth *rdeth = arg;
+
+ rdeth->een = cpu_to_be32(RDETH_EEN_MASK & een);
+}
+
+static inline u8 rdeth_een(struct rxe_pkt_info *pkt)
+{
+ return __rdeth_een(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RDETH]);
+}
+
+static inline void rdeth_set_een(struct rxe_pkt_info *pkt, u32 een)
+{
+ __rdeth_set_een(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RDETH], een);
+}
+
+/******************************************************************************
+ * Datagram Extended Transport Header
+ ******************************************************************************/
+struct rxe_deth {
+ __be32 qkey;
+ __be32 sqp;
+};
+
+#define GSI_QKEY (0x80010000)
+#define DETH_SQP_MASK (0x00ffffff)
+
+static inline u32 __deth_qkey(void *arg)
+{
+ struct rxe_deth *deth = arg;
+
+ return be32_to_cpu(deth->qkey);
+}
+
+static inline void __deth_set_qkey(void *arg, u32 qkey)
+{
+ struct rxe_deth *deth = arg;
+
+ deth->qkey = cpu_to_be32(qkey);
+}
+
+static inline u32 __deth_sqp(void *arg)
+{
+ struct rxe_deth *deth = arg;
+
+ return DETH_SQP_MASK & be32_to_cpu(deth->sqp);
+}
+
+static inline void __deth_set_sqp(void *arg, u32 sqp)
+{
+ struct rxe_deth *deth = arg;
+
+ deth->sqp = cpu_to_be32(DETH_SQP_MASK & sqp);
+}
+
+static inline u32 deth_qkey(struct rxe_pkt_info *pkt)
+{
+ return __deth_qkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_DETH]);
+}
+
+static inline void deth_set_qkey(struct rxe_pkt_info *pkt, u32 qkey)
+{
+ __deth_set_qkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_DETH], qkey);
+}
+
+static inline u32 deth_sqp(struct rxe_pkt_info *pkt)
+{
+ return __deth_sqp(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_DETH]);
+}
+
+static inline void deth_set_sqp(struct rxe_pkt_info *pkt, u32 sqp)
+{
+ __deth_set_sqp(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_DETH], sqp);
+}
+
+/******************************************************************************
+ * RDMA Extended Transport Header
+ ******************************************************************************/
+struct rxe_reth {
+ __be64 va;
+ __be32 rkey;
+ __be32 len;
+};
+
+static inline u64 __reth_va(void *arg)
+{
+ struct rxe_reth *reth = arg;
+
+ return be64_to_cpu(reth->va);
+}
+
+static inline void __reth_set_va(void *arg, u64 va)
+{
+ struct rxe_reth *reth = arg;
+
+ reth->va = cpu_to_be64(va);
+}
+
+static inline u32 __reth_rkey(void *arg)
+{
+ struct rxe_reth *reth = arg;
+
+ return be32_to_cpu(reth->rkey);
+}
+
+static inline void __reth_set_rkey(void *arg, u32 rkey)
+{
+ struct rxe_reth *reth = arg;
+
+ reth->rkey = cpu_to_be32(rkey);
+}
+
+static inline u32 __reth_len(void *arg)
+{
+ struct rxe_reth *reth = arg;
+
+ return be32_to_cpu(reth->len);
+}
+
+static inline void __reth_set_len(void *arg, u32 len)
+{
+ struct rxe_reth *reth = arg;
+
+ reth->len = cpu_to_be32(len);
+}
+
+static inline u64 reth_va(struct rxe_pkt_info *pkt)
+{
+ return __reth_va(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH]);
+}
+
+static inline void reth_set_va(struct rxe_pkt_info *pkt, u64 va)
+{
+ __reth_set_va(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH], va);
+}
+
+static inline u32 reth_rkey(struct rxe_pkt_info *pkt)
+{
+ return __reth_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH]);
+}
+
+static inline void reth_set_rkey(struct rxe_pkt_info *pkt, u32 rkey)
+{
+ __reth_set_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH], rkey);
+}
+
+static inline u32 reth_len(struct rxe_pkt_info *pkt)
+{
+ return __reth_len(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH]);
+}
+
+static inline void reth_set_len(struct rxe_pkt_info *pkt, u32 len)
+{
+ __reth_set_len(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_RETH], len);
+}
+
+/******************************************************************************
+ * Atomic Extended Transport Header
+ ******************************************************************************/
+struct rxe_atmeth {
+ __be64 va;
+ __be32 rkey;
+ __be64 swap_add;
+ __be64 comp;
+} __attribute__((__packed__));
+
+static inline u64 __atmeth_va(void *arg)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ return be64_to_cpu(atmeth->va);
+}
+
+static inline void __atmeth_set_va(void *arg, u64 va)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ atmeth->va = cpu_to_be64(va);
+}
+
+static inline u32 __atmeth_rkey(void *arg)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ return be32_to_cpu(atmeth->rkey);
+}
+
+static inline void __atmeth_set_rkey(void *arg, u32 rkey)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ atmeth->rkey = cpu_to_be32(rkey);
+}
+
+static inline u64 __atmeth_swap_add(void *arg)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ return be64_to_cpu(atmeth->swap_add);
+}
+
+static inline void __atmeth_set_swap_add(void *arg, u64 swap_add)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ atmeth->swap_add = cpu_to_be64(swap_add);
+}
+
+static inline u64 __atmeth_comp(void *arg)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ return be64_to_cpu(atmeth->comp);
+}
+
+static inline void __atmeth_set_comp(void *arg, u64 comp)
+{
+ struct rxe_atmeth *atmeth = arg;
+
+ atmeth->comp = cpu_to_be64(comp);
+}
+
+static inline u64 atmeth_va(struct rxe_pkt_info *pkt)
+{
+ return __atmeth_va(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH]);
+}
+
+static inline void atmeth_set_va(struct rxe_pkt_info *pkt, u64 va)
+{
+ __atmeth_set_va(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH], va);
+}
+
+static inline u32 atmeth_rkey(struct rxe_pkt_info *pkt)
+{
+ return __atmeth_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH]);
+}
+
+static inline void atmeth_set_rkey(struct rxe_pkt_info *pkt, u32 rkey)
+{
+ __atmeth_set_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH], rkey);
+}
+
+static inline u64 atmeth_swap_add(struct rxe_pkt_info *pkt)
+{
+ return __atmeth_swap_add(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH]);
+}
+
+static inline void atmeth_set_swap_add(struct rxe_pkt_info *pkt, u64 swap_add)
+{
+ __atmeth_set_swap_add(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH], swap_add);
+}
+
+static inline u64 atmeth_comp(struct rxe_pkt_info *pkt)
+{
+ return __atmeth_comp(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH]);
+}
+
+static inline void atmeth_set_comp(struct rxe_pkt_info *pkt, u64 comp)
+{
+ __atmeth_set_comp(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMETH], comp);
+}
+
+/******************************************************************************
+ * Ack Extended Transport Header
+ ******************************************************************************/
+struct rxe_aeth {
+ __be32 smsn;
+};
+
+#define AETH_SYN_MASK (0xff000000)
+#define AETH_MSN_MASK (0x00ffffff)
+
+enum aeth_syndrome {
+ AETH_TYPE_MASK = 0xe0,
+ AETH_ACK = 0x00,
+ AETH_RNR_NAK = 0x20,
+ AETH_RSVD = 0x40,
+ AETH_NAK = 0x60,
+ AETH_ACK_UNLIMITED = 0x1f,
+ AETH_NAK_PSN_SEQ_ERROR = 0x60,
+ AETH_NAK_INVALID_REQ = 0x61,
+ AETH_NAK_REM_ACC_ERR = 0x62,
+ AETH_NAK_REM_OP_ERR = 0x63,
+ AETH_NAK_INV_RD_REQ = 0x64,
+};
+
+static inline u8 __aeth_syn(void *arg)
+{
+ struct rxe_aeth *aeth = arg;
+
+ return (AETH_SYN_MASK & be32_to_cpu(aeth->smsn)) >> 24;
+}
+
+static inline void __aeth_set_syn(void *arg, u8 syn)
+{
+ struct rxe_aeth *aeth = arg;
+ u32 smsn = be32_to_cpu(aeth->smsn);
+
+ aeth->smsn = cpu_to_be32((AETH_SYN_MASK & (syn << 24)) |
+ (~AETH_SYN_MASK & smsn));
+}
+
+static inline u32 __aeth_msn(void *arg)
+{
+ struct rxe_aeth *aeth = arg;
+
+ return AETH_MSN_MASK & be32_to_cpu(aeth->smsn);
+}
+
+static inline void __aeth_set_msn(void *arg, u32 msn)
+{
+ struct rxe_aeth *aeth = arg;
+ u32 smsn = be32_to_cpu(aeth->smsn);
+
+ aeth->smsn = cpu_to_be32((AETH_MSN_MASK & msn) |
+ (~AETH_MSN_MASK & smsn));
+}
+
+static inline u8 aeth_syn(struct rxe_pkt_info *pkt)
+{
+ return __aeth_syn(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_AETH]);
+}
+
+static inline void aeth_set_syn(struct rxe_pkt_info *pkt, u8 syn)
+{
+ __aeth_set_syn(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_AETH], syn);
+}
+
+static inline u32 aeth_msn(struct rxe_pkt_info *pkt)
+{
+ return __aeth_msn(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_AETH]);
+}
+
+static inline void aeth_set_msn(struct rxe_pkt_info *pkt, u32 msn)
+{
+ __aeth_set_msn(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_AETH], msn);
+}
+
+/******************************************************************************
+ * Atomic Ack Extended Transport Header
+ ******************************************************************************/
+struct rxe_atmack {
+ __be64 orig;
+};
+
+static inline u64 __atmack_orig(void *arg)
+{
+ struct rxe_atmack *atmack = arg;
+
+ return be64_to_cpu(atmack->orig);
+}
+
+static inline void __atmack_set_orig(void *arg, u64 orig)
+{
+ struct rxe_atmack *atmack = arg;
+
+ atmack->orig = cpu_to_be64(orig);
+}
+
+static inline u64 atmack_orig(struct rxe_pkt_info *pkt)
+{
+ return __atmack_orig(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMACK]);
+}
+
+static inline void atmack_set_orig(struct rxe_pkt_info *pkt, u64 orig)
+{
+ __atmack_set_orig(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_ATMACK], orig);
+}
+
+/******************************************************************************
+ * Immediate Extended Transport Header
+ ******************************************************************************/
+struct rxe_immdt {
+ __be32 imm;
+};
+
+static inline __be32 __immdt_imm(void *arg)
+{
+ struct rxe_immdt *immdt = arg;
+
+ return immdt->imm;
+}
+
+static inline void __immdt_set_imm(void *arg, __be32 imm)
+{
+ struct rxe_immdt *immdt = arg;
+
+ immdt->imm = imm;
+}
+
+static inline __be32 immdt_imm(struct rxe_pkt_info *pkt)
+{
+ return __immdt_imm(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_IMMDT]);
+}
+
+static inline void immdt_set_imm(struct rxe_pkt_info *pkt, __be32 imm)
+{
+ __immdt_set_imm(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_IMMDT], imm);
+}
+
+/******************************************************************************
+ * Invalidate Extended Transport Header
+ ******************************************************************************/
+struct rxe_ieth {
+ __be32 rkey;
+};
+
+static inline u32 __ieth_rkey(void *arg)
+{
+ struct rxe_ieth *ieth = arg;
+
+ return be32_to_cpu(ieth->rkey);
+}
+
+static inline void __ieth_set_rkey(void *arg, u32 rkey)
+{
+ struct rxe_ieth *ieth = arg;
+
+ ieth->rkey = cpu_to_be32(rkey);
+}
+
+static inline u32 ieth_rkey(struct rxe_pkt_info *pkt)
+{
+ return __ieth_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_IETH]);
+}
+
+static inline void ieth_set_rkey(struct rxe_pkt_info *pkt, u32 rkey)
+{
+ __ieth_set_rkey(pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_IETH], rkey);
+}
+
+enum rxe_hdr_length {
+ RXE_BTH_BYTES = sizeof(struct rxe_bth),
+ RXE_DETH_BYTES = sizeof(struct rxe_deth),
+ RXE_IMMDT_BYTES = sizeof(struct rxe_immdt),
+ RXE_RETH_BYTES = sizeof(struct rxe_reth),
+ RXE_AETH_BYTES = sizeof(struct rxe_aeth),
+ RXE_ATMACK_BYTES = sizeof(struct rxe_atmack),
+ RXE_ATMETH_BYTES = sizeof(struct rxe_atmeth),
+ RXE_IETH_BYTES = sizeof(struct rxe_ieth),
+ RXE_RDETH_BYTES = sizeof(struct rxe_rdeth),
+};
+
+static inline size_t header_size(struct rxe_pkt_info *pkt)
+{
+ return pkt->offset + rxe_opcode[pkt->opcode].length;
+}
+
+static inline void *payload_addr(struct rxe_pkt_info *pkt)
+{
+ return pkt->hdr + pkt->offset
+ + rxe_opcode[pkt->opcode].offset[RXE_PAYLOAD];
+}
+
+static inline size_t payload_size(struct rxe_pkt_info *pkt)
+{
+ return pkt->paylen - rxe_opcode[pkt->opcode].offset[RXE_PAYLOAD]
+ - bth_pad(pkt) - RXE_ICRC_SIZE;
+}
+
+#endif /* RXE_HDR_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_icrc.c b/drivers/infiniband/sw/rxe/rxe_icrc.c
new file mode 100644
index 000000000000..413b56b23a06
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_icrc.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+/* Compute a partial ICRC for all the IB transport headers. */
+u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb)
+{
+ unsigned int bth_offset = 0;
+ struct iphdr *ip4h = NULL;
+ struct ipv6hdr *ip6h = NULL;
+ struct udphdr *udph;
+ struct rxe_bth *bth;
+ int crc;
+ int length;
+ int hdr_size = sizeof(struct udphdr) +
+ (skb->protocol == htons(ETH_P_IP) ?
+ sizeof(struct iphdr) : sizeof(struct ipv6hdr));
+ /* pseudo header buffer size is calculate using ipv6 header size since
+ * it is bigger than ipv4
+ */
+ u8 pshdr[sizeof(struct udphdr) +
+ sizeof(struct ipv6hdr) +
+ RXE_BTH_BYTES];
+
+ /* This seed is the result of computing a CRC with a seed of
+ * 0xfffffff and 8 bytes of 0xff representing a masked LRH.
+ */
+ crc = 0xdebb20e3;
+
+ if (skb->protocol == htons(ETH_P_IP)) { /* IPv4 */
+ memcpy(pshdr, ip_hdr(skb), hdr_size);
+ ip4h = (struct iphdr *)pshdr;
+ udph = (struct udphdr *)(ip4h + 1);
+
+ ip4h->ttl = 0xff;
+ ip4h->check = CSUM_MANGLED_0;
+ ip4h->tos = 0xff;
+ } else { /* IPv6 */
+ memcpy(pshdr, ipv6_hdr(skb), hdr_size);
+ ip6h = (struct ipv6hdr *)pshdr;
+ udph = (struct udphdr *)(ip6h + 1);
+
+ memset(ip6h->flow_lbl, 0xff, sizeof(ip6h->flow_lbl));
+ ip6h->priority = 0xf;
+ ip6h->hop_limit = 0xff;
+ }
+ udph->check = CSUM_MANGLED_0;
+
+ bth_offset += hdr_size;
+
+ memcpy(&pshdr[bth_offset], pkt->hdr, RXE_BTH_BYTES);
+ bth = (struct rxe_bth *)&pshdr[bth_offset];
+
+ /* exclude bth.resv8a */
+ bth->qpn |= cpu_to_be32(~BTH_QPN_MASK);
+
+ length = hdr_size + RXE_BTH_BYTES;
+ crc = crc32_le(crc, pshdr, length);
+
+ /* And finish to compute the CRC on the remainder of the headers. */
+ crc = crc32_le(crc, pkt->hdr + RXE_BTH_BYTES,
+ rxe_opcode[pkt->opcode].length - RXE_BTH_BYTES);
+ return crc;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h
new file mode 100644
index 000000000000..4a5484ef604f
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_loc.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_LOC_H
+#define RXE_LOC_H
+
+/* rxe_av.c */
+
+int rxe_av_chk_attr(struct rxe_dev *rxe, struct ib_ah_attr *attr);
+
+int rxe_av_from_attr(struct rxe_dev *rxe, u8 port_num,
+ struct rxe_av *av, struct ib_ah_attr *attr);
+
+int rxe_av_to_attr(struct rxe_dev *rxe, struct rxe_av *av,
+ struct ib_ah_attr *attr);
+
+int rxe_av_fill_ip_info(struct rxe_dev *rxe,
+ struct rxe_av *av,
+ struct ib_ah_attr *attr,
+ struct ib_gid_attr *sgid_attr,
+ union ib_gid *sgid);
+
+struct rxe_av *rxe_get_av(struct rxe_pkt_info *pkt);
+
+/* rxe_cq.c */
+int rxe_cq_chk_attr(struct rxe_dev *rxe, struct rxe_cq *cq,
+ int cqe, int comp_vector, struct ib_udata *udata);
+
+int rxe_cq_from_init(struct rxe_dev *rxe, struct rxe_cq *cq, int cqe,
+ int comp_vector, struct ib_ucontext *context,
+ struct ib_udata *udata);
+
+int rxe_cq_resize_queue(struct rxe_cq *cq, int new_cqe, struct ib_udata *udata);
+
+int rxe_cq_post(struct rxe_cq *cq, struct rxe_cqe *cqe, int solicited);
+
+void rxe_cq_cleanup(void *arg);
+
+/* rxe_mcast.c */
+int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
+ struct rxe_mc_grp **grp_p);
+
+int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct rxe_mc_grp *grp);
+
+int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
+ union ib_gid *mgid);
+
+void rxe_drop_all_mcast_groups(struct rxe_qp *qp);
+
+void rxe_mc_cleanup(void *arg);
+
+/* rxe_mmap.c */
+struct rxe_mmap_info {
+ struct list_head pending_mmaps;
+ struct ib_ucontext *context;
+ struct kref ref;
+ void *obj;
+
+ struct mminfo info;
+};
+
+void rxe_mmap_release(struct kref *ref);
+
+struct rxe_mmap_info *rxe_create_mmap_info(struct rxe_dev *dev,
+ u32 size,
+ struct ib_ucontext *context,
+ void *obj);
+
+int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
+
+/* rxe_mr.c */
+enum copy_direction {
+ to_mem_obj,
+ from_mem_obj,
+};
+
+int rxe_mem_init_dma(struct rxe_dev *rxe, struct rxe_pd *pd,
+ int access, struct rxe_mem *mem);
+
+int rxe_mem_init_user(struct rxe_dev *rxe, struct rxe_pd *pd, u64 start,
+ u64 length, u64 iova, int access, struct ib_udata *udata,
+ struct rxe_mem *mr);
+
+int rxe_mem_init_fast(struct rxe_dev *rxe, struct rxe_pd *pd,
+ int max_pages, struct rxe_mem *mem);
+
+int rxe_mem_copy(struct rxe_mem *mem, u64 iova, void *addr,
+ int length, enum copy_direction dir, u32 *crcp);
+
+int copy_data(struct rxe_dev *rxe, struct rxe_pd *pd, int access,
+ struct rxe_dma_info *dma, void *addr, int length,
+ enum copy_direction dir, u32 *crcp);
+
+void *iova_to_vaddr(struct rxe_mem *mem, u64 iova, int length);
+
+enum lookup_type {
+ lookup_local,
+ lookup_remote,
+};
+
+struct rxe_mem *lookup_mem(struct rxe_pd *pd, int access, u32 key,
+ enum lookup_type type);
+
+int mem_check_range(struct rxe_mem *mem, u64 iova, size_t length);
+
+int rxe_mem_map_pages(struct rxe_dev *rxe, struct rxe_mem *mem,
+ u64 *page, int num_pages, u64 iova);
+
+void rxe_mem_cleanup(void *arg);
+
+int advance_dma_data(struct rxe_dma_info *dma, unsigned int length);
+
+/* rxe_qp.c */
+int rxe_qp_chk_init(struct rxe_dev *rxe, struct ib_qp_init_attr *init);
+
+int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
+ struct ib_qp_init_attr *init, struct ib_udata *udata,
+ struct ib_pd *ibpd);
+
+int rxe_qp_to_init(struct rxe_qp *qp, struct ib_qp_init_attr *init);
+
+int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct ib_qp_attr *attr, int mask);
+
+int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr,
+ int mask, struct ib_udata *udata);
+
+int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask);
+
+void rxe_qp_error(struct rxe_qp *qp);
+
+void rxe_qp_destroy(struct rxe_qp *qp);
+
+void rxe_qp_cleanup(void *arg);
+
+static inline int qp_num(struct rxe_qp *qp)
+{
+ return qp->ibqp.qp_num;
+}
+
+static inline enum ib_qp_type qp_type(struct rxe_qp *qp)
+{
+ return qp->ibqp.qp_type;
+}
+
+static inline enum ib_qp_state qp_state(struct rxe_qp *qp)
+{
+ return qp->attr.qp_state;
+}
+
+static inline int qp_mtu(struct rxe_qp *qp)
+{
+ if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC)
+ return qp->attr.path_mtu;
+ else
+ return RXE_PORT_MAX_MTU;
+}
+
+static inline int rcv_wqe_size(int max_sge)
+{
+ return sizeof(struct rxe_recv_wqe) +
+ max_sge * sizeof(struct ib_sge);
+}
+
+void free_rd_atomic_resource(struct rxe_qp *qp, struct resp_res *res);
+
+static inline void rxe_advance_resp_resource(struct rxe_qp *qp)
+{
+ qp->resp.res_head++;
+ if (unlikely(qp->resp.res_head == qp->attr.max_rd_atomic))
+ qp->resp.res_head = 0;
+}
+
+void retransmit_timer(unsigned long data);
+void rnr_nak_timer(unsigned long data);
+
+void dump_qp(struct rxe_qp *qp);
+
+/* rxe_srq.c */
+#define IB_SRQ_INIT_MASK (~IB_SRQ_LIMIT)
+
+int rxe_srq_chk_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_attr *attr, enum ib_srq_attr_mask mask);
+
+int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_init_attr *init,
+ struct ib_ucontext *context, struct ib_udata *udata);
+
+int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_attr *attr, enum ib_srq_attr_mask mask,
+ struct ib_udata *udata);
+
+extern struct ib_dma_mapping_ops rxe_dma_mapping_ops;
+
+void rxe_release(struct kref *kref);
+
+int rxe_completer(void *arg);
+int rxe_requester(void *arg);
+int rxe_responder(void *arg);
+
+u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb);
+
+void rxe_resp_queue_pkt(struct rxe_dev *rxe,
+ struct rxe_qp *qp, struct sk_buff *skb);
+
+void rxe_comp_queue_pkt(struct rxe_dev *rxe,
+ struct rxe_qp *qp, struct sk_buff *skb);
+
+static inline unsigned wr_opcode_mask(int opcode, struct rxe_qp *qp)
+{
+ return rxe_wr_opcode_info[opcode].mask[qp->ibqp.qp_type];
+}
+
+static inline int rxe_xmit_packet(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt, struct sk_buff *skb)
+{
+ int err;
+ int is_request = pkt->mask & RXE_REQ_MASK;
+
+ if ((is_request && (qp->req.state != QP_STATE_READY)) ||
+ (!is_request && (qp->resp.state != QP_STATE_READY))) {
+ pr_info("Packet dropped. QP is not in ready state\n");
+ goto drop;
+ }
+
+ if (pkt->mask & RXE_LOOPBACK_MASK) {
+ memcpy(SKB_TO_PKT(skb), pkt, sizeof(*pkt));
+ err = rxe->ifc_ops->loopback(skb);
+ } else {
+ err = rxe->ifc_ops->send(rxe, pkt, skb);
+ }
+
+ if (err) {
+ rxe->xmit_errors++;
+ return err;
+ }
+
+ atomic_inc(&qp->skb_out);
+
+ if ((qp_type(qp) != IB_QPT_RC) &&
+ (pkt->mask & RXE_END_MASK)) {
+ pkt->wqe->state = wqe_state_done;
+ rxe_run_task(&qp->comp.task, 1);
+ }
+
+ goto done;
+
+drop:
+ kfree_skb(skb);
+ err = 0;
+done:
+ return err;
+}
+
+#endif /* RXE_LOC_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_mcast.c b/drivers/infiniband/sw/rxe/rxe_mcast.c
new file mode 100644
index 000000000000..fa95544ca7e0
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_mcast.c
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+int rxe_mcast_get_grp(struct rxe_dev *rxe, union ib_gid *mgid,
+ struct rxe_mc_grp **grp_p)
+{
+ int err;
+ struct rxe_mc_grp *grp;
+
+ if (rxe->attr.max_mcast_qp_attach == 0) {
+ err = -EINVAL;
+ goto err1;
+ }
+
+ grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
+ if (grp)
+ goto done;
+
+ grp = rxe_alloc(&rxe->mc_grp_pool);
+ if (!grp) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ INIT_LIST_HEAD(&grp->qp_list);
+ spin_lock_init(&grp->mcg_lock);
+ grp->rxe = rxe;
+
+ rxe_add_key(grp, mgid);
+
+ err = rxe->ifc_ops->mcast_add(rxe, mgid);
+ if (err)
+ goto err2;
+
+done:
+ *grp_p = grp;
+ return 0;
+
+err2:
+ rxe_drop_ref(grp);
+err1:
+ return err;
+}
+
+int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct rxe_mc_grp *grp)
+{
+ int err;
+ struct rxe_mc_elem *elem;
+
+ /* check to see of the qp is already a member of the group */
+ spin_lock_bh(&qp->grp_lock);
+ spin_lock_bh(&grp->mcg_lock);
+ list_for_each_entry(elem, &grp->qp_list, qp_list) {
+ if (elem->qp == qp) {
+ err = 0;
+ goto out;
+ }
+ }
+
+ if (grp->num_qp >= rxe->attr.max_mcast_qp_attach) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ elem = rxe_alloc(&rxe->mc_elem_pool);
+ if (!elem) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ /* each qp holds a ref on the grp */
+ rxe_add_ref(grp);
+
+ grp->num_qp++;
+ elem->qp = qp;
+ elem->grp = grp;
+
+ list_add(&elem->qp_list, &grp->qp_list);
+ list_add(&elem->grp_list, &qp->grp_list);
+
+ err = 0;
+out:
+ spin_unlock_bh(&grp->mcg_lock);
+ spin_unlock_bh(&qp->grp_lock);
+ return err;
+}
+
+int rxe_mcast_drop_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
+ union ib_gid *mgid)
+{
+ struct rxe_mc_grp *grp;
+ struct rxe_mc_elem *elem, *tmp;
+
+ grp = rxe_pool_get_key(&rxe->mc_grp_pool, mgid);
+ if (!grp)
+ goto err1;
+
+ spin_lock_bh(&qp->grp_lock);
+ spin_lock_bh(&grp->mcg_lock);
+
+ list_for_each_entry_safe(elem, tmp, &grp->qp_list, qp_list) {
+ if (elem->qp == qp) {
+ list_del(&elem->qp_list);
+ list_del(&elem->grp_list);
+ grp->num_qp--;
+
+ spin_unlock_bh(&grp->mcg_lock);
+ spin_unlock_bh(&qp->grp_lock);
+ rxe_drop_ref(elem);
+ rxe_drop_ref(grp); /* ref held by QP */
+ rxe_drop_ref(grp); /* ref from get_key */
+ return 0;
+ }
+ }
+
+ spin_unlock_bh(&grp->mcg_lock);
+ spin_unlock_bh(&qp->grp_lock);
+ rxe_drop_ref(grp); /* ref from get_key */
+err1:
+ return -EINVAL;
+}
+
+void rxe_drop_all_mcast_groups(struct rxe_qp *qp)
+{
+ struct rxe_mc_grp *grp;
+ struct rxe_mc_elem *elem;
+
+ while (1) {
+ spin_lock_bh(&qp->grp_lock);
+ if (list_empty(&qp->grp_list)) {
+ spin_unlock_bh(&qp->grp_lock);
+ break;
+ }
+ elem = list_first_entry(&qp->grp_list, struct rxe_mc_elem,
+ grp_list);
+ list_del(&elem->grp_list);
+ spin_unlock_bh(&qp->grp_lock);
+
+ grp = elem->grp;
+ spin_lock_bh(&grp->mcg_lock);
+ list_del(&elem->qp_list);
+ grp->num_qp--;
+ spin_unlock_bh(&grp->mcg_lock);
+ rxe_drop_ref(grp);
+ rxe_drop_ref(elem);
+ }
+}
+
+void rxe_mc_cleanup(void *arg)
+{
+ struct rxe_mc_grp *grp = arg;
+ struct rxe_dev *rxe = grp->rxe;
+
+ rxe_drop_key(grp);
+ rxe->ifc_ops->mcast_delete(rxe, &grp->mgid);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_mmap.c b/drivers/infiniband/sw/rxe/rxe_mmap.c
new file mode 100644
index 000000000000..54b3c7c99eff
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_mmap.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <asm/pgtable.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+void rxe_mmap_release(struct kref *ref)
+{
+ struct rxe_mmap_info *ip = container_of(ref,
+ struct rxe_mmap_info, ref);
+ struct rxe_dev *rxe = to_rdev(ip->context->device);
+
+ spin_lock_bh(&rxe->pending_lock);
+
+ if (!list_empty(&ip->pending_mmaps))
+ list_del(&ip->pending_mmaps);
+
+ spin_unlock_bh(&rxe->pending_lock);
+
+ vfree(ip->obj); /* buf */
+ kfree(ip);
+}
+
+/*
+ * open and close keep track of how many times the memory region is mapped,
+ * to avoid releasing it.
+ */
+static void rxe_vma_open(struct vm_area_struct *vma)
+{
+ struct rxe_mmap_info *ip = vma->vm_private_data;
+
+ kref_get(&ip->ref);
+}
+
+static void rxe_vma_close(struct vm_area_struct *vma)
+{
+ struct rxe_mmap_info *ip = vma->vm_private_data;
+
+ kref_put(&ip->ref, rxe_mmap_release);
+}
+
+static struct vm_operations_struct rxe_vm_ops = {
+ .open = rxe_vma_open,
+ .close = rxe_vma_close,
+};
+
+/**
+ * rxe_mmap - create a new mmap region
+ * @context: the IB user context of the process making the mmap() call
+ * @vma: the VMA to be initialized
+ * Return zero if the mmap is OK. Otherwise, return an errno.
+ */
+int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+{
+ struct rxe_dev *rxe = to_rdev(context->device);
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ struct rxe_mmap_info *ip, *pp;
+ int ret;
+
+ /*
+ * Search the device's list of objects waiting for a mmap call.
+ * Normally, this list is very short since a call to create a
+ * CQ, QP, or SRQ is soon followed by a call to mmap().
+ */
+ spin_lock_bh(&rxe->pending_lock);
+ list_for_each_entry_safe(ip, pp, &rxe->pending_mmaps, pending_mmaps) {
+ if (context != ip->context || (__u64)offset != ip->info.offset)
+ continue;
+
+ /* Don't allow a mmap larger than the object. */
+ if (size > ip->info.size) {
+ pr_err("mmap region is larger than the object!\n");
+ spin_unlock_bh(&rxe->pending_lock);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ goto found_it;
+ }
+ pr_warn("unable to find pending mmap info\n");
+ spin_unlock_bh(&rxe->pending_lock);
+ ret = -EINVAL;
+ goto done;
+
+found_it:
+ list_del_init(&ip->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock);
+
+ ret = remap_vmalloc_range(vma, ip->obj, 0);
+ if (ret) {
+ pr_err("rxe: err %d from remap_vmalloc_range\n", ret);
+ goto done;
+ }
+
+ vma->vm_ops = &rxe_vm_ops;
+ vma->vm_private_data = ip;
+ rxe_vma_open(vma);
+done:
+ return ret;
+}
+
+/*
+ * Allocate information for rxe_mmap
+ */
+struct rxe_mmap_info *rxe_create_mmap_info(struct rxe_dev *rxe,
+ u32 size,
+ struct ib_ucontext *context,
+ void *obj)
+{
+ struct rxe_mmap_info *ip;
+
+ ip = kmalloc(sizeof(*ip), GFP_KERNEL);
+ if (!ip)
+ return NULL;
+
+ size = PAGE_ALIGN(size);
+
+ spin_lock_bh(&rxe->mmap_offset_lock);
+
+ if (rxe->mmap_offset == 0)
+ rxe->mmap_offset = PAGE_SIZE;
+
+ ip->info.offset = rxe->mmap_offset;
+ rxe->mmap_offset += size;
+
+ spin_unlock_bh(&rxe->mmap_offset_lock);
+
+ INIT_LIST_HEAD(&ip->pending_mmaps);
+ ip->info.size = size;
+ ip->context = context;
+ ip->obj = obj;
+ kref_init(&ip->ref);
+
+ return ip;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c
new file mode 100644
index 000000000000..f3dab6574504
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -0,0 +1,643 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+/*
+ * lfsr (linear feedback shift register) with period 255
+ */
+static u8 rxe_get_key(void)
+{
+ static unsigned key = 1;
+
+ key = key << 1;
+
+ key |= (0 != (key & 0x100)) ^ (0 != (key & 0x10))
+ ^ (0 != (key & 0x80)) ^ (0 != (key & 0x40));
+
+ key &= 0xff;
+
+ return key;
+}
+
+int mem_check_range(struct rxe_mem *mem, u64 iova, size_t length)
+{
+ switch (mem->type) {
+ case RXE_MEM_TYPE_DMA:
+ return 0;
+
+ case RXE_MEM_TYPE_MR:
+ case RXE_MEM_TYPE_FMR:
+ return ((iova < mem->iova) ||
+ ((iova + length) > (mem->iova + mem->length))) ?
+ -EFAULT : 0;
+
+ default:
+ return -EFAULT;
+ }
+}
+
+#define IB_ACCESS_REMOTE (IB_ACCESS_REMOTE_READ \
+ | IB_ACCESS_REMOTE_WRITE \
+ | IB_ACCESS_REMOTE_ATOMIC)
+
+static void rxe_mem_init(int access, struct rxe_mem *mem)
+{
+ u32 lkey = mem->pelem.index << 8 | rxe_get_key();
+ u32 rkey = (access & IB_ACCESS_REMOTE) ? lkey : 0;
+
+ if (mem->pelem.pool->type == RXE_TYPE_MR) {
+ mem->ibmr.lkey = lkey;
+ mem->ibmr.rkey = rkey;
+ }
+
+ mem->lkey = lkey;
+ mem->rkey = rkey;
+ mem->state = RXE_MEM_STATE_INVALID;
+ mem->type = RXE_MEM_TYPE_NONE;
+ mem->map_shift = ilog2(RXE_BUF_PER_MAP);
+}
+
+void rxe_mem_cleanup(void *arg)
+{
+ struct rxe_mem *mem = arg;
+ int i;
+
+ if (mem->umem)
+ ib_umem_release(mem->umem);
+
+ if (mem->map) {
+ for (i = 0; i < mem->num_map; i++)
+ kfree(mem->map[i]);
+
+ kfree(mem->map);
+ }
+}
+
+static int rxe_mem_alloc(struct rxe_dev *rxe, struct rxe_mem *mem, int num_buf)
+{
+ int i;
+ int num_map;
+ struct rxe_map **map = mem->map;
+
+ num_map = (num_buf + RXE_BUF_PER_MAP - 1) / RXE_BUF_PER_MAP;
+
+ mem->map = kmalloc_array(num_map, sizeof(*map), GFP_KERNEL);
+ if (!mem->map)
+ goto err1;
+
+ for (i = 0; i < num_map; i++) {
+ mem->map[i] = kmalloc(sizeof(**map), GFP_KERNEL);
+ if (!mem->map[i])
+ goto err2;
+ }
+
+ WARN_ON(!is_power_of_2(RXE_BUF_PER_MAP));
+
+ mem->map_shift = ilog2(RXE_BUF_PER_MAP);
+ mem->map_mask = RXE_BUF_PER_MAP - 1;
+
+ mem->num_buf = num_buf;
+ mem->num_map = num_map;
+ mem->max_buf = num_map * RXE_BUF_PER_MAP;
+
+ return 0;
+
+err2:
+ for (i--; i >= 0; i--)
+ kfree(mem->map[i]);
+
+ kfree(mem->map);
+err1:
+ return -ENOMEM;
+}
+
+int rxe_mem_init_dma(struct rxe_dev *rxe, struct rxe_pd *pd,
+ int access, struct rxe_mem *mem)
+{
+ rxe_mem_init(access, mem);
+
+ mem->pd = pd;
+ mem->access = access;
+ mem->state = RXE_MEM_STATE_VALID;
+ mem->type = RXE_MEM_TYPE_DMA;
+
+ return 0;
+}
+
+int rxe_mem_init_user(struct rxe_dev *rxe, struct rxe_pd *pd, u64 start,
+ u64 length, u64 iova, int access, struct ib_udata *udata,
+ struct rxe_mem *mem)
+{
+ int entry;
+ struct rxe_map **map;
+ struct rxe_phys_buf *buf = NULL;
+ struct ib_umem *umem;
+ struct scatterlist *sg;
+ int num_buf;
+ void *vaddr;
+ int err;
+
+ umem = ib_umem_get(pd->ibpd.uobject->context, start, length, access, 0);
+ if (IS_ERR(umem)) {
+ pr_warn("err %d from rxe_umem_get\n",
+ (int)PTR_ERR(umem));
+ err = -EINVAL;
+ goto err1;
+ }
+
+ mem->umem = umem;
+ num_buf = umem->nmap;
+
+ rxe_mem_init(access, mem);
+
+ err = rxe_mem_alloc(rxe, mem, num_buf);
+ if (err) {
+ pr_warn("err %d from rxe_mem_alloc\n", err);
+ ib_umem_release(umem);
+ goto err1;
+ }
+
+ WARN_ON(!is_power_of_2(umem->page_size));
+
+ mem->page_shift = ilog2(umem->page_size);
+ mem->page_mask = umem->page_size - 1;
+
+ num_buf = 0;
+ map = mem->map;
+ if (length > 0) {
+ buf = map[0]->buf;
+
+ for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
+ vaddr = page_address(sg_page(sg));
+ if (!vaddr) {
+ pr_warn("null vaddr\n");
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ buf->addr = (uintptr_t)vaddr;
+ buf->size = umem->page_size;
+ num_buf++;
+ buf++;
+
+ if (num_buf >= RXE_BUF_PER_MAP) {
+ map++;
+ buf = map[0]->buf;
+ num_buf = 0;
+ }
+ }
+ }
+
+ mem->pd = pd;
+ mem->umem = umem;
+ mem->access = access;
+ mem->length = length;
+ mem->iova = iova;
+ mem->va = start;
+ mem->offset = ib_umem_offset(umem);
+ mem->state = RXE_MEM_STATE_VALID;
+ mem->type = RXE_MEM_TYPE_MR;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+int rxe_mem_init_fast(struct rxe_dev *rxe, struct rxe_pd *pd,
+ int max_pages, struct rxe_mem *mem)
+{
+ int err;
+
+ rxe_mem_init(0, mem);
+
+ /* In fastreg, we also set the rkey */
+ mem->ibmr.rkey = mem->ibmr.lkey;
+
+ err = rxe_mem_alloc(rxe, mem, max_pages);
+ if (err)
+ goto err1;
+
+ mem->pd = pd;
+ mem->max_buf = max_pages;
+ mem->state = RXE_MEM_STATE_FREE;
+ mem->type = RXE_MEM_TYPE_MR;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+static void lookup_iova(
+ struct rxe_mem *mem,
+ u64 iova,
+ int *m_out,
+ int *n_out,
+ size_t *offset_out)
+{
+ size_t offset = iova - mem->iova + mem->offset;
+ int map_index;
+ int buf_index;
+ u64 length;
+
+ if (likely(mem->page_shift)) {
+ *offset_out = offset & mem->page_mask;
+ offset >>= mem->page_shift;
+ *n_out = offset & mem->map_mask;
+ *m_out = offset >> mem->map_shift;
+ } else {
+ map_index = 0;
+ buf_index = 0;
+
+ length = mem->map[map_index]->buf[buf_index].size;
+
+ while (offset >= length) {
+ offset -= length;
+ buf_index++;
+
+ if (buf_index == RXE_BUF_PER_MAP) {
+ map_index++;
+ buf_index = 0;
+ }
+ length = mem->map[map_index]->buf[buf_index].size;
+ }
+
+ *m_out = map_index;
+ *n_out = buf_index;
+ *offset_out = offset;
+ }
+}
+
+void *iova_to_vaddr(struct rxe_mem *mem, u64 iova, int length)
+{
+ size_t offset;
+ int m, n;
+ void *addr;
+
+ if (mem->state != RXE_MEM_STATE_VALID) {
+ pr_warn("mem not in valid state\n");
+ addr = NULL;
+ goto out;
+ }
+
+ if (!mem->map) {
+ addr = (void *)(uintptr_t)iova;
+ goto out;
+ }
+
+ if (mem_check_range(mem, iova, length)) {
+ pr_warn("range violation\n");
+ addr = NULL;
+ goto out;
+ }
+
+ lookup_iova(mem, iova, &m, &n, &offset);
+
+ if (offset + length > mem->map[m]->buf[n].size) {
+ pr_warn("crosses page boundary\n");
+ addr = NULL;
+ goto out;
+ }
+
+ addr = (void *)(uintptr_t)mem->map[m]->buf[n].addr + offset;
+
+out:
+ return addr;
+}
+
+/* copy data from a range (vaddr, vaddr+length-1) to or from
+ * a mem object starting at iova. Compute incremental value of
+ * crc32 if crcp is not zero. caller must hold a reference to mem
+ */
+int rxe_mem_copy(struct rxe_mem *mem, u64 iova, void *addr, int length,
+ enum copy_direction dir, u32 *crcp)
+{
+ int err;
+ int bytes;
+ u8 *va;
+ struct rxe_map **map;
+ struct rxe_phys_buf *buf;
+ int m;
+ int i;
+ size_t offset;
+ u32 crc = crcp ? (*crcp) : 0;
+
+ if (mem->type == RXE_MEM_TYPE_DMA) {
+ u8 *src, *dest;
+
+ src = (dir == to_mem_obj) ?
+ addr : ((void *)(uintptr_t)iova);
+
+ dest = (dir == to_mem_obj) ?
+ ((void *)(uintptr_t)iova) : addr;
+
+ if (crcp)
+ *crcp = crc32_le(*crcp, src, length);
+
+ memcpy(dest, src, length);
+
+ return 0;
+ }
+
+ WARN_ON(!mem->map);
+
+ err = mem_check_range(mem, iova, length);
+ if (err) {
+ err = -EFAULT;
+ goto err1;
+ }
+
+ lookup_iova(mem, iova, &m, &i, &offset);
+
+ map = mem->map + m;
+ buf = map[0]->buf + i;
+
+ while (length > 0) {
+ u8 *src, *dest;
+
+ va = (u8 *)(uintptr_t)buf->addr + offset;
+ src = (dir == to_mem_obj) ? addr : va;
+ dest = (dir == to_mem_obj) ? va : addr;
+
+ bytes = buf->size - offset;
+
+ if (bytes > length)
+ bytes = length;
+
+ if (crcp)
+ crc = crc32_le(crc, src, bytes);
+
+ memcpy(dest, src, bytes);
+
+ length -= bytes;
+ addr += bytes;
+
+ offset = 0;
+ buf++;
+ i++;
+
+ if (i == RXE_BUF_PER_MAP) {
+ i = 0;
+ map++;
+ buf = map[0]->buf;
+ }
+ }
+
+ if (crcp)
+ *crcp = crc;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+/* copy data in or out of a wqe, i.e. sg list
+ * under the control of a dma descriptor
+ */
+int copy_data(
+ struct rxe_dev *rxe,
+ struct rxe_pd *pd,
+ int access,
+ struct rxe_dma_info *dma,
+ void *addr,
+ int length,
+ enum copy_direction dir,
+ u32 *crcp)
+{
+ int bytes;
+ struct rxe_sge *sge = &dma->sge[dma->cur_sge];
+ int offset = dma->sge_offset;
+ int resid = dma->resid;
+ struct rxe_mem *mem = NULL;
+ u64 iova;
+ int err;
+
+ if (length == 0)
+ return 0;
+
+ if (length > resid) {
+ err = -EINVAL;
+ goto err2;
+ }
+
+ if (sge->length && (offset < sge->length)) {
+ mem = lookup_mem(pd, access, sge->lkey, lookup_local);
+ if (!mem) {
+ err = -EINVAL;
+ goto err1;
+ }
+ }
+
+ while (length > 0) {
+ bytes = length;
+
+ if (offset >= sge->length) {
+ if (mem) {
+ rxe_drop_ref(mem);
+ mem = NULL;
+ }
+ sge++;
+ dma->cur_sge++;
+ offset = 0;
+
+ if (dma->cur_sge >= dma->num_sge) {
+ err = -ENOSPC;
+ goto err2;
+ }
+
+ if (sge->length) {
+ mem = lookup_mem(pd, access, sge->lkey,
+ lookup_local);
+ if (!mem) {
+ err = -EINVAL;
+ goto err1;
+ }
+ } else {
+ continue;
+ }
+ }
+
+ if (bytes > sge->length - offset)
+ bytes = sge->length - offset;
+
+ if (bytes > 0) {
+ iova = sge->addr + offset;
+
+ err = rxe_mem_copy(mem, iova, addr, bytes, dir, crcp);
+ if (err)
+ goto err2;
+
+ offset += bytes;
+ resid -= bytes;
+ length -= bytes;
+ addr += bytes;
+ }
+ }
+
+ dma->sge_offset = offset;
+ dma->resid = resid;
+
+ if (mem)
+ rxe_drop_ref(mem);
+
+ return 0;
+
+err2:
+ if (mem)
+ rxe_drop_ref(mem);
+err1:
+ return err;
+}
+
+int advance_dma_data(struct rxe_dma_info *dma, unsigned int length)
+{
+ struct rxe_sge *sge = &dma->sge[dma->cur_sge];
+ int offset = dma->sge_offset;
+ int resid = dma->resid;
+
+ while (length) {
+ unsigned int bytes;
+
+ if (offset >= sge->length) {
+ sge++;
+ dma->cur_sge++;
+ offset = 0;
+ if (dma->cur_sge >= dma->num_sge)
+ return -ENOSPC;
+ }
+
+ bytes = length;
+
+ if (bytes > sge->length - offset)
+ bytes = sge->length - offset;
+
+ offset += bytes;
+ resid -= bytes;
+ length -= bytes;
+ }
+
+ dma->sge_offset = offset;
+ dma->resid = resid;
+
+ return 0;
+}
+
+/* (1) find the mem (mr or mw) corresponding to lkey/rkey
+ * depending on lookup_type
+ * (2) verify that the (qp) pd matches the mem pd
+ * (3) verify that the mem can support the requested access
+ * (4) verify that mem state is valid
+ */
+struct rxe_mem *lookup_mem(struct rxe_pd *pd, int access, u32 key,
+ enum lookup_type type)
+{
+ struct rxe_mem *mem;
+ struct rxe_dev *rxe = to_rdev(pd->ibpd.device);
+ int index = key >> 8;
+
+ if (index >= RXE_MIN_MR_INDEX && index <= RXE_MAX_MR_INDEX) {
+ mem = rxe_pool_get_index(&rxe->mr_pool, index);
+ if (!mem)
+ goto err1;
+ } else {
+ goto err1;
+ }
+
+ if ((type == lookup_local && mem->lkey != key) ||
+ (type == lookup_remote && mem->rkey != key))
+ goto err2;
+
+ if (mem->pd != pd)
+ goto err2;
+
+ if (access && !(access & mem->access))
+ goto err2;
+
+ if (mem->state != RXE_MEM_STATE_VALID)
+ goto err2;
+
+ return mem;
+
+err2:
+ rxe_drop_ref(mem);
+err1:
+ return NULL;
+}
+
+int rxe_mem_map_pages(struct rxe_dev *rxe, struct rxe_mem *mem,
+ u64 *page, int num_pages, u64 iova)
+{
+ int i;
+ int num_buf;
+ int err;
+ struct rxe_map **map;
+ struct rxe_phys_buf *buf;
+ int page_size;
+
+ if (num_pages > mem->max_buf) {
+ err = -EINVAL;
+ goto err1;
+ }
+
+ num_buf = 0;
+ page_size = 1 << mem->page_shift;
+ map = mem->map;
+ buf = map[0]->buf;
+
+ for (i = 0; i < num_pages; i++) {
+ buf->addr = *page++;
+ buf->size = page_size;
+ buf++;
+ num_buf++;
+
+ if (num_buf == RXE_BUF_PER_MAP) {
+ map++;
+ buf = map[0]->buf;
+ num_buf = 0;
+ }
+ }
+
+ mem->iova = iova;
+ mem->va = iova;
+ mem->length = num_pages << mem->page_shift;
+ mem->state = RXE_MEM_STATE_VALID;
+
+ return 0;
+
+err1:
+ return err;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
new file mode 100644
index 000000000000..0b8d2ea8b41d
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/if.h>
+#include <linux/if_vlan.h>
+#include <net/udp_tunnel.h>
+#include <net/sch_generic.h>
+#include <linux/netfilter.h>
+#include <rdma/ib_addr.h>
+
+#include "rxe.h"
+#include "rxe_net.h"
+#include "rxe_loc.h"
+
+static LIST_HEAD(rxe_dev_list);
+static spinlock_t dev_list_lock; /* spinlock for device list */
+
+struct rxe_dev *net_to_rxe(struct net_device *ndev)
+{
+ struct rxe_dev *rxe;
+ struct rxe_dev *found = NULL;
+
+ spin_lock_bh(&dev_list_lock);
+ list_for_each_entry(rxe, &rxe_dev_list, list) {
+ if (rxe->ndev == ndev) {
+ found = rxe;
+ break;
+ }
+ }
+ spin_unlock_bh(&dev_list_lock);
+
+ return found;
+}
+
+struct rxe_dev *get_rxe_by_name(const char* name)
+{
+ struct rxe_dev *rxe;
+ struct rxe_dev *found = NULL;
+
+ spin_lock_bh(&dev_list_lock);
+ list_for_each_entry(rxe, &rxe_dev_list, list) {
+ if (!strcmp(name, rxe->ib_dev.name)) {
+ found = rxe;
+ break;
+ }
+ }
+ spin_unlock_bh(&dev_list_lock);
+ return found;
+}
+
+
+struct rxe_recv_sockets recv_sockets;
+
+static __be64 rxe_mac_to_eui64(struct net_device *ndev)
+{
+ unsigned char *mac_addr = ndev->dev_addr;
+ __be64 eui64;
+ unsigned char *dst = (unsigned char *)&eui64;
+
+ dst[0] = mac_addr[0] ^ 2;
+ dst[1] = mac_addr[1];
+ dst[2] = mac_addr[2];
+ dst[3] = 0xff;
+ dst[4] = 0xfe;
+ dst[5] = mac_addr[3];
+ dst[6] = mac_addr[4];
+ dst[7] = mac_addr[5];
+
+ return eui64;
+}
+
+static __be64 node_guid(struct rxe_dev *rxe)
+{
+ return rxe_mac_to_eui64(rxe->ndev);
+}
+
+static __be64 port_guid(struct rxe_dev *rxe)
+{
+ return rxe_mac_to_eui64(rxe->ndev);
+}
+
+static struct device *dma_device(struct rxe_dev *rxe)
+{
+ struct net_device *ndev;
+
+ ndev = rxe->ndev;
+
+ if (ndev->priv_flags & IFF_802_1Q_VLAN)
+ ndev = vlan_dev_real_dev(ndev);
+
+ return ndev->dev.parent;
+}
+
+static int mcast_add(struct rxe_dev *rxe, union ib_gid *mgid)
+{
+ int err;
+ unsigned char ll_addr[ETH_ALEN];
+
+ ipv6_eth_mc_map((struct in6_addr *)mgid->raw, ll_addr);
+ err = dev_mc_add(rxe->ndev, ll_addr);
+
+ return err;
+}
+
+static int mcast_delete(struct rxe_dev *rxe, union ib_gid *mgid)
+{
+ int err;
+ unsigned char ll_addr[ETH_ALEN];
+
+ ipv6_eth_mc_map((struct in6_addr *)mgid->raw, ll_addr);
+ err = dev_mc_del(rxe->ndev, ll_addr);
+
+ return err;
+}
+
+static struct dst_entry *rxe_find_route4(struct net_device *ndev,
+ struct in_addr *saddr,
+ struct in_addr *daddr)
+{
+ struct rtable *rt;
+ struct flowi4 fl = { { 0 } };
+
+ memset(&fl, 0, sizeof(fl));
+ fl.flowi4_oif = ndev->ifindex;
+ memcpy(&fl.saddr, saddr, sizeof(*saddr));
+ memcpy(&fl.daddr, daddr, sizeof(*daddr));
+ fl.flowi4_proto = IPPROTO_UDP;
+
+ rt = ip_route_output_key(&init_net, &fl);
+ if (IS_ERR(rt)) {
+ pr_err_ratelimited("no route to %pI4\n", &daddr->s_addr);
+ return NULL;
+ }
+
+ return &rt->dst;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *rxe_find_route6(struct net_device *ndev,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr)
+{
+ struct dst_entry *ndst;
+ struct flowi6 fl6 = { { 0 } };
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.flowi6_oif = ndev->ifindex;
+ memcpy(&fl6.saddr, saddr, sizeof(*saddr));
+ memcpy(&fl6.daddr, daddr, sizeof(*daddr));
+ fl6.flowi6_proto = IPPROTO_UDP;
+
+ if (unlikely(ipv6_stub->ipv6_dst_lookup(sock_net(recv_sockets.sk6->sk),
+ recv_sockets.sk6->sk, &ndst, &fl6))) {
+ pr_err_ratelimited("no route to %pI6\n", daddr);
+ goto put;
+ }
+
+ if (unlikely(ndst->error)) {
+ pr_err("no route to %pI6\n", daddr);
+ goto put;
+ }
+
+ return ndst;
+put:
+ dst_release(ndst);
+ return NULL;
+}
+
+#else
+
+static struct dst_entry *rxe_find_route6(struct net_device *ndev,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr)
+{
+ return NULL;
+}
+
+#endif
+
+static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+{
+ struct udphdr *udph;
+ struct net_device *ndev = skb->dev;
+ struct rxe_dev *rxe = net_to_rxe(ndev);
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+
+ if (!rxe)
+ goto drop;
+
+ if (skb_linearize(skb)) {
+ pr_err("skb_linearize failed\n");
+ goto drop;
+ }
+
+ udph = udp_hdr(skb);
+ pkt->rxe = rxe;
+ pkt->port_num = 1;
+ pkt->hdr = (u8 *)(udph + 1);
+ pkt->mask = RXE_GRH_MASK;
+ pkt->paylen = be16_to_cpu(udph->len) - sizeof(*udph);
+
+ return rxe_rcv(skb);
+drop:
+ kfree_skb(skb);
+ return 0;
+}
+
+static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port,
+ bool ipv6)
+{
+ int err;
+ struct socket *sock;
+ struct udp_port_cfg udp_cfg;
+ struct udp_tunnel_sock_cfg tnl_cfg;
+
+ memset(&udp_cfg, 0, sizeof(udp_cfg));
+
+ if (ipv6) {
+ udp_cfg.family = AF_INET6;
+ udp_cfg.ipv6_v6only = 1;
+ } else {
+ udp_cfg.family = AF_INET;
+ }
+
+ udp_cfg.local_udp_port = port;
+
+ /* Create UDP socket */
+ err = udp_sock_create(net, &udp_cfg, &sock);
+ if (err < 0) {
+ pr_err("failed to create udp socket. err = %d\n", err);
+ return ERR_PTR(err);
+ }
+
+ tnl_cfg.sk_user_data = NULL;
+ tnl_cfg.encap_type = 1;
+ tnl_cfg.encap_rcv = rxe_udp_encap_recv;
+ tnl_cfg.encap_destroy = NULL;
+
+ /* Setup UDP tunnel */
+ setup_udp_tunnel_sock(net, sock, &tnl_cfg);
+
+ return sock;
+}
+
+static void rxe_release_udp_tunnel(struct socket *sk)
+{
+ udp_tunnel_sock_release(sk);
+}
+
+static void prepare_udp_hdr(struct sk_buff *skb, __be16 src_port,
+ __be16 dst_port)
+{
+ struct udphdr *udph;
+
+ __skb_push(skb, sizeof(*udph));
+ skb_reset_transport_header(skb);
+ udph = udp_hdr(skb);
+
+ udph->dest = dst_port;
+ udph->source = src_port;
+ udph->len = htons(skb->len);
+ udph->check = 0;
+}
+
+static void prepare_ipv4_hdr(struct dst_entry *dst, struct sk_buff *skb,
+ __be32 saddr, __be32 daddr, __u8 proto,
+ __u8 tos, __u8 ttl, __be16 df, bool xnet)
+{
+ struct iphdr *iph;
+
+ skb_scrub_packet(skb, xnet);
+
+ skb_clear_hash(skb);
+ skb_dst_set(skb, dst);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+ skb_push(skb, sizeof(struct iphdr));
+ skb_reset_network_header(skb);
+
+ iph = ip_hdr(skb);
+
+ iph->version = IPVERSION;
+ iph->ihl = sizeof(struct iphdr) >> 2;
+ iph->frag_off = df;
+ iph->protocol = proto;
+ iph->tos = tos;
+ iph->daddr = daddr;
+ iph->saddr = saddr;
+ iph->ttl = ttl;
+ __ip_select_ident(dev_net(dst->dev), iph,
+ skb_shinfo(skb)->gso_segs ?: 1);
+ iph->tot_len = htons(skb->len);
+ ip_send_check(iph);
+}
+
+static void prepare_ipv6_hdr(struct dst_entry *dst, struct sk_buff *skb,
+ struct in6_addr *saddr, struct in6_addr *daddr,
+ __u8 proto, __u8 prio, __u8 ttl)
+{
+ struct ipv6hdr *ip6h;
+
+ memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
+ IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED
+ | IPSKB_REROUTED);
+ skb_dst_set(skb, dst);
+
+ __skb_push(skb, sizeof(*ip6h));
+ skb_reset_network_header(skb);
+ ip6h = ipv6_hdr(skb);
+ ip6_flow_hdr(ip6h, prio, htonl(0));
+ ip6h->payload_len = htons(skb->len);
+ ip6h->nexthdr = proto;
+ ip6h->hop_limit = ttl;
+ ip6h->daddr = *daddr;
+ ip6h->saddr = *saddr;
+ ip6h->payload_len = htons(skb->len - sizeof(*ip6h));
+}
+
+static int prepare4(struct rxe_dev *rxe, struct sk_buff *skb, struct rxe_av *av)
+{
+ struct dst_entry *dst;
+ bool xnet = false;
+ __be16 df = htons(IP_DF);
+ struct in_addr *saddr = &av->sgid_addr._sockaddr_in.sin_addr;
+ struct in_addr *daddr = &av->dgid_addr._sockaddr_in.sin_addr;
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+
+ dst = rxe_find_route4(rxe->ndev, saddr, daddr);
+ if (!dst) {
+ pr_err("Host not reachable\n");
+ return -EHOSTUNREACH;
+ }
+
+ if (!memcmp(saddr, daddr, sizeof(*daddr)))
+ pkt->mask |= RXE_LOOPBACK_MASK;
+
+ prepare_udp_hdr(skb, htons(RXE_ROCE_V2_SPORT),
+ htons(ROCE_V2_UDP_DPORT));
+
+ prepare_ipv4_hdr(dst, skb, saddr->s_addr, daddr->s_addr, IPPROTO_UDP,
+ av->grh.traffic_class, av->grh.hop_limit, df, xnet);
+ return 0;
+}
+
+static int prepare6(struct rxe_dev *rxe, struct sk_buff *skb, struct rxe_av *av)
+{
+ struct dst_entry *dst;
+ struct in6_addr *saddr = &av->sgid_addr._sockaddr_in6.sin6_addr;
+ struct in6_addr *daddr = &av->dgid_addr._sockaddr_in6.sin6_addr;
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+
+ dst = rxe_find_route6(rxe->ndev, saddr, daddr);
+ if (!dst) {
+ pr_err("Host not reachable\n");
+ return -EHOSTUNREACH;
+ }
+
+ if (!memcmp(saddr, daddr, sizeof(*daddr)))
+ pkt->mask |= RXE_LOOPBACK_MASK;
+
+ prepare_udp_hdr(skb, htons(RXE_ROCE_V2_SPORT),
+ htons(ROCE_V2_UDP_DPORT));
+
+ prepare_ipv6_hdr(dst, skb, saddr, daddr, IPPROTO_UDP,
+ av->grh.traffic_class,
+ av->grh.hop_limit);
+ return 0;
+}
+
+static int prepare(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb, u32 *crc)
+{
+ int err = 0;
+ struct rxe_av *av = rxe_get_av(pkt);
+
+ if (av->network_type == RDMA_NETWORK_IPV4)
+ err = prepare4(rxe, skb, av);
+ else if (av->network_type == RDMA_NETWORK_IPV6)
+ err = prepare6(rxe, skb, av);
+
+ *crc = rxe_icrc_hdr(pkt, skb);
+
+ return err;
+}
+
+static void rxe_skb_tx_dtor(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct rxe_qp *qp = sk->sk_user_data;
+ int skb_out = atomic_dec_return(&qp->skb_out);
+
+ if (unlikely(qp->need_req_skb &&
+ skb_out < RXE_INFLIGHT_SKBS_PER_QP_LOW))
+ rxe_run_task(&qp->req.task, 1);
+}
+
+static int send(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb)
+{
+ struct sk_buff *nskb;
+ struct rxe_av *av;
+ int err;
+
+ av = rxe_get_av(pkt);
+
+ nskb = skb_clone(skb, GFP_ATOMIC);
+ if (!nskb)
+ return -ENOMEM;
+
+ nskb->destructor = rxe_skb_tx_dtor;
+ nskb->sk = pkt->qp->sk->sk;
+
+ if (av->network_type == RDMA_NETWORK_IPV4) {
+ err = ip_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb);
+ } else if (av->network_type == RDMA_NETWORK_IPV6) {
+ err = ip6_local_out(dev_net(skb_dst(skb)->dev), nskb->sk, nskb);
+ } else {
+ pr_err("Unknown layer 3 protocol: %d\n", av->network_type);
+ kfree_skb(nskb);
+ return -EINVAL;
+ }
+
+ if (unlikely(net_xmit_eval(err))) {
+ pr_debug("error sending packet: %d\n", err);
+ return -EAGAIN;
+ }
+
+ kfree_skb(skb);
+
+ return 0;
+}
+
+static int loopback(struct sk_buff *skb)
+{
+ return rxe_rcv(skb);
+}
+
+static inline int addr_same(struct rxe_dev *rxe, struct rxe_av *av)
+{
+ return rxe->port.port_guid == av->grh.dgid.global.interface_id;
+}
+
+static struct sk_buff *init_packet(struct rxe_dev *rxe, struct rxe_av *av,
+ int paylen, struct rxe_pkt_info *pkt)
+{
+ unsigned int hdr_len;
+ struct sk_buff *skb;
+
+ if (av->network_type == RDMA_NETWORK_IPV4)
+ hdr_len = ETH_HLEN + sizeof(struct udphdr) +
+ sizeof(struct iphdr);
+ else
+ hdr_len = ETH_HLEN + sizeof(struct udphdr) +
+ sizeof(struct ipv6hdr);
+
+ skb = alloc_skb(paylen + hdr_len + LL_RESERVED_SPACE(rxe->ndev),
+ GFP_ATOMIC);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, hdr_len + LL_RESERVED_SPACE(rxe->ndev));
+
+ skb->dev = rxe->ndev;
+ if (av->network_type == RDMA_NETWORK_IPV4)
+ skb->protocol = htons(ETH_P_IP);
+ else
+ skb->protocol = htons(ETH_P_IPV6);
+
+ pkt->rxe = rxe;
+ pkt->port_num = 1;
+ pkt->hdr = skb_put(skb, paylen);
+ pkt->mask |= RXE_GRH_MASK;
+
+ memset(pkt->hdr, 0, paylen);
+
+ return skb;
+}
+
+/*
+ * this is required by rxe_cfg to match rxe devices in
+ * /sys/class/infiniband up with their underlying ethernet devices
+ */
+static char *parent_name(struct rxe_dev *rxe, unsigned int port_num)
+{
+ return rxe->ndev->name;
+}
+
+static enum rdma_link_layer link_layer(struct rxe_dev *rxe,
+ unsigned int port_num)
+{
+ return IB_LINK_LAYER_ETHERNET;
+}
+
+static struct rxe_ifc_ops ifc_ops = {
+ .node_guid = node_guid,
+ .port_guid = port_guid,
+ .dma_device = dma_device,
+ .mcast_add = mcast_add,
+ .mcast_delete = mcast_delete,
+ .prepare = prepare,
+ .send = send,
+ .loopback = loopback,
+ .init_packet = init_packet,
+ .parent_name = parent_name,
+ .link_layer = link_layer,
+};
+
+struct rxe_dev *rxe_net_add(struct net_device *ndev)
+{
+ int err;
+ struct rxe_dev *rxe = NULL;
+
+ rxe = (struct rxe_dev *)ib_alloc_device(sizeof(*rxe));
+ if (!rxe)
+ return NULL;
+
+ rxe->ifc_ops = &ifc_ops;
+ rxe->ndev = ndev;
+
+ err = rxe_add(rxe, ndev->mtu);
+ if (err) {
+ ib_dealloc_device(&rxe->ib_dev);
+ return NULL;
+ }
+
+ spin_lock_bh(&dev_list_lock);
+ list_add_tail(&rxe_dev_list, &rxe->list);
+ spin_unlock_bh(&dev_list_lock);
+ return rxe;
+}
+
+void rxe_remove_all(void)
+{
+ spin_lock_bh(&dev_list_lock);
+ while (!list_empty(&rxe_dev_list)) {
+ struct rxe_dev *rxe =
+ list_first_entry(&rxe_dev_list, struct rxe_dev, list);
+
+ list_del(&rxe->list);
+ spin_unlock_bh(&dev_list_lock);
+ rxe_remove(rxe);
+ spin_lock_bh(&dev_list_lock);
+ }
+ spin_unlock_bh(&dev_list_lock);
+}
+EXPORT_SYMBOL(rxe_remove_all);
+
+static void rxe_port_event(struct rxe_dev *rxe,
+ enum ib_event_type event)
+{
+ struct ib_event ev;
+
+ ev.device = &rxe->ib_dev;
+ ev.element.port_num = 1;
+ ev.event = event;
+
+ ib_dispatch_event(&ev);
+}
+
+/* Caller must hold net_info_lock */
+void rxe_port_up(struct rxe_dev *rxe)
+{
+ struct rxe_port *port;
+
+ port = &rxe->port;
+ port->attr.state = IB_PORT_ACTIVE;
+ port->attr.phys_state = IB_PHYS_STATE_LINK_UP;
+
+ rxe_port_event(rxe, IB_EVENT_PORT_ACTIVE);
+ pr_info("rxe: set %s active\n", rxe->ib_dev.name);
+ return;
+}
+
+/* Caller must hold net_info_lock */
+void rxe_port_down(struct rxe_dev *rxe)
+{
+ struct rxe_port *port;
+
+ port = &rxe->port;
+ port->attr.state = IB_PORT_DOWN;
+ port->attr.phys_state = IB_PHYS_STATE_LINK_DOWN;
+
+ rxe_port_event(rxe, IB_EVENT_PORT_ERR);
+ pr_info("rxe: set %s down\n", rxe->ib_dev.name);
+ return;
+}
+
+static int rxe_notify(struct notifier_block *not_blk,
+ unsigned long event,
+ void *arg)
+{
+ struct net_device *ndev = netdev_notifier_info_to_dev(arg);
+ struct rxe_dev *rxe = net_to_rxe(ndev);
+
+ if (!rxe)
+ goto out;
+
+ switch (event) {
+ case NETDEV_UNREGISTER:
+ list_del(&rxe->list);
+ rxe_remove(rxe);
+ break;
+ case NETDEV_UP:
+ rxe_port_up(rxe);
+ break;
+ case NETDEV_DOWN:
+ rxe_port_down(rxe);
+ break;
+ case NETDEV_CHANGEMTU:
+ pr_info("rxe: %s changed mtu to %d\n", ndev->name, ndev->mtu);
+ rxe_set_mtu(rxe, ndev->mtu);
+ break;
+ case NETDEV_REBOOT:
+ case NETDEV_CHANGE:
+ case NETDEV_GOING_DOWN:
+ case NETDEV_CHANGEADDR:
+ case NETDEV_CHANGENAME:
+ case NETDEV_FEAT_CHANGE:
+ default:
+ pr_info("rxe: ignoring netdev event = %ld for %s\n",
+ event, ndev->name);
+ break;
+ }
+out:
+ return NOTIFY_OK;
+}
+
+static struct notifier_block rxe_net_notifier = {
+ .notifier_call = rxe_notify,
+};
+
+int rxe_net_init(void)
+{
+ int err;
+
+ spin_lock_init(&dev_list_lock);
+
+ recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
+ htons(ROCE_V2_UDP_DPORT), true);
+ if (IS_ERR(recv_sockets.sk6)) {
+ recv_sockets.sk6 = NULL;
+ pr_err("rxe: Failed to create IPv6 UDP tunnel\n");
+ return -1;
+ }
+
+ recv_sockets.sk4 = rxe_setup_udp_tunnel(&init_net,
+ htons(ROCE_V2_UDP_DPORT), false);
+ if (IS_ERR(recv_sockets.sk4)) {
+ rxe_release_udp_tunnel(recv_sockets.sk6);
+ recv_sockets.sk4 = NULL;
+ recv_sockets.sk6 = NULL;
+ pr_err("rxe: Failed to create IPv4 UDP tunnel\n");
+ return -1;
+ }
+
+ err = register_netdevice_notifier(&rxe_net_notifier);
+ if (err) {
+ rxe_release_udp_tunnel(recv_sockets.sk6);
+ rxe_release_udp_tunnel(recv_sockets.sk4);
+ pr_err("rxe: Failed to rigister netdev notifier\n");
+ }
+
+ return err;
+}
+
+void rxe_net_exit(void)
+{
+ if (recv_sockets.sk6)
+ rxe_release_udp_tunnel(recv_sockets.sk6);
+
+ if (recv_sockets.sk4)
+ rxe_release_udp_tunnel(recv_sockets.sk4);
+
+ unregister_netdevice_notifier(&rxe_net_notifier);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_net.h b/drivers/infiniband/sw/rxe/rxe_net.h
new file mode 100644
index 000000000000..7b06f76d16cc
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_net.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_NET_H
+#define RXE_NET_H
+
+#include <net/sock.h>
+#include <net/if_inet6.h>
+#include <linux/module.h>
+
+struct rxe_recv_sockets {
+ struct socket *sk4;
+ struct socket *sk6;
+};
+
+extern struct rxe_recv_sockets recv_sockets;
+
+struct rxe_dev *rxe_net_add(struct net_device *ndev);
+
+int rxe_net_init(void);
+void rxe_net_exit(void);
+
+#endif /* RXE_NET_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.c b/drivers/infiniband/sw/rxe/rxe_opcode.c
new file mode 100644
index 000000000000..61927c165b59
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_opcode.c
@@ -0,0 +1,961 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_pack.h>
+#include "rxe_opcode.h"
+#include "rxe_hdr.h"
+
+/* useful information about work request opcodes and pkt opcodes in
+ * table form
+ */
+struct rxe_wr_opcode_info rxe_wr_opcode_info[] = {
+ [IB_WR_RDMA_WRITE] = {
+ .name = "IB_WR_RDMA_WRITE",
+ .mask = {
+ [IB_QPT_RC] = WR_INLINE_MASK | WR_WRITE_MASK,
+ [IB_QPT_UC] = WR_INLINE_MASK | WR_WRITE_MASK,
+ },
+ },
+ [IB_WR_RDMA_WRITE_WITH_IMM] = {
+ .name = "IB_WR_RDMA_WRITE_WITH_IMM",
+ .mask = {
+ [IB_QPT_RC] = WR_INLINE_MASK | WR_WRITE_MASK,
+ [IB_QPT_UC] = WR_INLINE_MASK | WR_WRITE_MASK,
+ },
+ },
+ [IB_WR_SEND] = {
+ .name = "IB_WR_SEND",
+ .mask = {
+ [IB_QPT_SMI] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_GSI] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_RC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UD] = WR_INLINE_MASK | WR_SEND_MASK,
+ },
+ },
+ [IB_WR_SEND_WITH_IMM] = {
+ .name = "IB_WR_SEND_WITH_IMM",
+ .mask = {
+ [IB_QPT_SMI] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_GSI] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_RC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UD] = WR_INLINE_MASK | WR_SEND_MASK,
+ },
+ },
+ [IB_WR_RDMA_READ] = {
+ .name = "IB_WR_RDMA_READ",
+ .mask = {
+ [IB_QPT_RC] = WR_READ_MASK,
+ },
+ },
+ [IB_WR_ATOMIC_CMP_AND_SWP] = {
+ .name = "IB_WR_ATOMIC_CMP_AND_SWP",
+ .mask = {
+ [IB_QPT_RC] = WR_ATOMIC_MASK,
+ },
+ },
+ [IB_WR_ATOMIC_FETCH_AND_ADD] = {
+ .name = "IB_WR_ATOMIC_FETCH_AND_ADD",
+ .mask = {
+ [IB_QPT_RC] = WR_ATOMIC_MASK,
+ },
+ },
+ [IB_WR_LSO] = {
+ .name = "IB_WR_LSO",
+ .mask = {
+ /* not supported */
+ },
+ },
+ [IB_WR_SEND_WITH_INV] = {
+ .name = "IB_WR_SEND_WITH_INV",
+ .mask = {
+ [IB_QPT_RC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UC] = WR_INLINE_MASK | WR_SEND_MASK,
+ [IB_QPT_UD] = WR_INLINE_MASK | WR_SEND_MASK,
+ },
+ },
+ [IB_WR_RDMA_READ_WITH_INV] = {
+ .name = "IB_WR_RDMA_READ_WITH_INV",
+ .mask = {
+ [IB_QPT_RC] = WR_READ_MASK,
+ },
+ },
+ [IB_WR_LOCAL_INV] = {
+ .name = "IB_WR_LOCAL_INV",
+ .mask = {
+ [IB_QPT_RC] = WR_REG_MASK,
+ },
+ },
+ [IB_WR_REG_MR] = {
+ .name = "IB_WR_REG_MR",
+ .mask = {
+ [IB_QPT_RC] = WR_REG_MASK,
+ },
+ },
+};
+
+struct rxe_opcode_info rxe_opcode[RXE_NUM_OPCODE] = {
+ [IB_OPCODE_RC_SEND_FIRST] = {
+ .name = "IB_OPCODE_RC_SEND_FIRST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_RWR_MASK
+ | RXE_SEND_MASK | RXE_START_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_MIDDLE] = {
+ .name = "IB_OPCODE_RC_SEND_MIDDLE]",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_SEND_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_LAST] = {
+ .name = "IB_OPCODE_RC_SEND_LAST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_COMP_MASK
+ | RXE_SEND_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_SEND_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_ONLY] = {
+ .name = "IB_OPCODE_RC_SEND_ONLY",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_COMP_MASK
+ | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_FIRST] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_FIRST",
+ .mask = RXE_RETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_MIDDLE] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_MIDDLE",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_LAST] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_LAST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_ONLY] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_ONLY",
+ .mask = RXE_RETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_RETH_MASK | RXE_IMMDT_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_READ_REQUEST] = {
+ .name = "IB_OPCODE_RC_RDMA_READ_REQUEST",
+ .mask = RXE_RETH_MASK | RXE_REQ_MASK | RXE_READ_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST] = {
+ .name = "IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST",
+ .mask = RXE_AETH_MASK | RXE_PAYLOAD_MASK | RXE_ACK_MASK
+ | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_AETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE] = {
+ .name = "IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE",
+ .mask = RXE_PAYLOAD_MASK | RXE_ACK_MASK | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST] = {
+ .name = "IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST",
+ .mask = RXE_AETH_MASK | RXE_PAYLOAD_MASK | RXE_ACK_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_AETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY] = {
+ .name = "IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY",
+ .mask = RXE_AETH_MASK | RXE_PAYLOAD_MASK | RXE_ACK_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_AETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_ACKNOWLEDGE] = {
+ .name = "IB_OPCODE_RC_ACKNOWLEDGE",
+ .mask = RXE_AETH_MASK | RXE_ACK_MASK | RXE_START_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_AETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE] = {
+ .name = "IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE",
+ .mask = RXE_AETH_MASK | RXE_ATMACK_MASK | RXE_ACK_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMACK_BYTES + RXE_AETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_AETH] = RXE_BTH_BYTES,
+ [RXE_ATMACK] = RXE_BTH_BYTES
+ + RXE_AETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_ATMACK_BYTES + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_COMPARE_SWAP] = {
+ .name = "IB_OPCODE_RC_COMPARE_SWAP",
+ .mask = RXE_ATMETH_MASK | RXE_REQ_MASK | RXE_ATOMIC_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_ATMETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_ATMETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_FETCH_ADD] = {
+ .name = "IB_OPCODE_RC_FETCH_ADD",
+ .mask = RXE_ATMETH_MASK | RXE_REQ_MASK | RXE_ATOMIC_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_ATMETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_ATMETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE] = {
+ .name = "IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE",
+ .mask = RXE_IETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_SEND_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE] = {
+ .name = "IB_OPCODE_RC_SEND_ONLY_INV",
+ .mask = RXE_IETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IETH_BYTES,
+ }
+ },
+
+ /* UC */
+ [IB_OPCODE_UC_SEND_FIRST] = {
+ .name = "IB_OPCODE_UC_SEND_FIRST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_RWR_MASK
+ | RXE_SEND_MASK | RXE_START_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_SEND_MIDDLE] = {
+ .name = "IB_OPCODE_UC_SEND_MIDDLE",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_SEND_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_SEND_LAST] = {
+ .name = "IB_OPCODE_UC_SEND_LAST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_COMP_MASK
+ | RXE_SEND_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_SEND_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_SEND_ONLY] = {
+ .name = "IB_OPCODE_UC_SEND_ONLY",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_COMP_MASK
+ | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_FIRST] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_FIRST",
+ .mask = RXE_RETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_MIDDLE] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_MIDDLE",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_LAST] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_LAST",
+ .mask = RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE",
+ .mask = RXE_IMMDT_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_IMMDT] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_ONLY] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_ONLY",
+ .mask = RXE_RETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_RETH_MASK | RXE_IMMDT_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_RETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RETH] = RXE_BTH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+
+ /* RD */
+ [IB_OPCODE_RD_SEND_FIRST] = {
+ .name = "IB_OPCODE_RD_SEND_FIRST",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_SEND_MIDDLE] = {
+ .name = "IB_OPCODE_RD_SEND_MIDDLE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_SEND_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_SEND_LAST] = {
+ .name = "IB_OPCODE_RD_SEND_LAST",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_COMP_MASK | RXE_SEND_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_SEND_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RD_SEND_LAST_WITH_IMMEDIATE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_IMMDT_MASK
+ | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_SEND_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_SEND_ONLY] = {
+ .name = "IB_OPCODE_RD_SEND_ONLY",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_SEND_MASK | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_SEND_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RD_SEND_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_IMMDT_MASK
+ | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_FIRST] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_FIRST",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_RETH_MASK
+ | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_RETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_MIDDLE] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_MIDDLE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_LAST] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_LAST",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_LAST_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_LAST_WITH_IMMEDIATE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_IMMDT_MASK
+ | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_ONLY] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_ONLY",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_RETH_MASK
+ | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_WRITE_MASK | RXE_START_MASK
+ | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_RETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_RETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_WRITE_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_RD_RDMA_WRITE_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_RETH_MASK
+ | RXE_IMMDT_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_WRITE_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_RETH_BYTES
+ + RXE_DETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_RETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_RETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_RETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_READ_REQUEST] = {
+ .name = "IB_OPCODE_RD_RDMA_READ_REQUEST",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_RETH_MASK
+ | RXE_REQ_MASK | RXE_READ_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_RETH_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_RETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RETH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_READ_RESPONSE_FIRST] = {
+ .name = "IB_OPCODE_RD_RDMA_READ_RESPONSE_FIRST",
+ .mask = RXE_RDETH_MASK | RXE_AETH_MASK
+ | RXE_PAYLOAD_MASK | RXE_ACK_MASK
+ | RXE_START_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_AETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_READ_RESPONSE_MIDDLE] = {
+ .name = "IB_OPCODE_RD_RDMA_READ_RESPONSE_MIDDLE",
+ .mask = RXE_RDETH_MASK | RXE_PAYLOAD_MASK | RXE_ACK_MASK
+ | RXE_MIDDLE_MASK,
+ .length = RXE_BTH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_READ_RESPONSE_LAST] = {
+ .name = "IB_OPCODE_RD_RDMA_READ_RESPONSE_LAST",
+ .mask = RXE_RDETH_MASK | RXE_AETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_ACK_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_AETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_RDMA_READ_RESPONSE_ONLY] = {
+ .name = "IB_OPCODE_RD_RDMA_READ_RESPONSE_ONLY",
+ .mask = RXE_RDETH_MASK | RXE_AETH_MASK | RXE_PAYLOAD_MASK
+ | RXE_ACK_MASK | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_AETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_ACKNOWLEDGE] = {
+ .name = "IB_OPCODE_RD_ACKNOWLEDGE",
+ .mask = RXE_RDETH_MASK | RXE_AETH_MASK | RXE_ACK_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_AETH_BYTES + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_AETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_ATOMIC_ACKNOWLEDGE] = {
+ .name = "IB_OPCODE_RD_ATOMIC_ACKNOWLEDGE",
+ .mask = RXE_RDETH_MASK | RXE_AETH_MASK | RXE_ATMACK_MASK
+ | RXE_ACK_MASK | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMACK_BYTES + RXE_AETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_AETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_ATMACK] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_AETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_COMPARE_SWAP] = {
+ .name = "RD_COMPARE_SWAP",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_ATMETH_MASK
+ | RXE_REQ_MASK | RXE_ATOMIC_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMETH_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_ATMETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES +
+ + RXE_ATMETH_BYTES
+ + RXE_DETH_BYTES +
+ + RXE_RDETH_BYTES,
+ }
+ },
+ [IB_OPCODE_RD_FETCH_ADD] = {
+ .name = "IB_OPCODE_RD_FETCH_ADD",
+ .mask = RXE_RDETH_MASK | RXE_DETH_MASK | RXE_ATMETH_MASK
+ | RXE_REQ_MASK | RXE_ATOMIC_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_ATMETH_BYTES + RXE_DETH_BYTES
+ + RXE_RDETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_RDETH] = RXE_BTH_BYTES,
+ [RXE_DETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES,
+ [RXE_ATMETH] = RXE_BTH_BYTES
+ + RXE_RDETH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES +
+ + RXE_ATMETH_BYTES
+ + RXE_DETH_BYTES +
+ + RXE_RDETH_BYTES,
+ }
+ },
+
+ /* UD */
+ [IB_OPCODE_UD_SEND_ONLY] = {
+ .name = "IB_OPCODE_UD_SEND_ONLY",
+ .mask = RXE_DETH_MASK | RXE_PAYLOAD_MASK | RXE_REQ_MASK
+ | RXE_COMP_MASK | RXE_RWR_MASK | RXE_SEND_MASK
+ | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_DETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_DETH] = RXE_BTH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_DETH_BYTES,
+ }
+ },
+ [IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE] = {
+ .name = "IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE",
+ .mask = RXE_DETH_MASK | RXE_IMMDT_MASK | RXE_PAYLOAD_MASK
+ | RXE_REQ_MASK | RXE_COMP_MASK | RXE_RWR_MASK
+ | RXE_SEND_MASK | RXE_START_MASK | RXE_END_MASK,
+ .length = RXE_BTH_BYTES + RXE_IMMDT_BYTES + RXE_DETH_BYTES,
+ .offset = {
+ [RXE_BTH] = 0,
+ [RXE_DETH] = RXE_BTH_BYTES,
+ [RXE_IMMDT] = RXE_BTH_BYTES
+ + RXE_DETH_BYTES,
+ [RXE_PAYLOAD] = RXE_BTH_BYTES
+ + RXE_DETH_BYTES
+ + RXE_IMMDT_BYTES,
+ }
+ },
+
+};
diff --git a/drivers/infiniband/sw/rxe/rxe_opcode.h b/drivers/infiniband/sw/rxe/rxe_opcode.h
new file mode 100644
index 000000000000..307604e9c78d
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_opcode.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_OPCODE_H
+#define RXE_OPCODE_H
+
+/*
+ * contains header bit mask definitions and header lengths
+ * declaration of the rxe_opcode_info struct and
+ * rxe_wr_opcode_info struct
+ */
+
+enum rxe_wr_mask {
+ WR_INLINE_MASK = BIT(0),
+ WR_ATOMIC_MASK = BIT(1),
+ WR_SEND_MASK = BIT(2),
+ WR_READ_MASK = BIT(3),
+ WR_WRITE_MASK = BIT(4),
+ WR_LOCAL_MASK = BIT(5),
+ WR_REG_MASK = BIT(6),
+
+ WR_READ_OR_WRITE_MASK = WR_READ_MASK | WR_WRITE_MASK,
+ WR_READ_WRITE_OR_SEND_MASK = WR_READ_OR_WRITE_MASK | WR_SEND_MASK,
+ WR_WRITE_OR_SEND_MASK = WR_WRITE_MASK | WR_SEND_MASK,
+ WR_ATOMIC_OR_READ_MASK = WR_ATOMIC_MASK | WR_READ_MASK,
+};
+
+#define WR_MAX_QPT (8)
+
+struct rxe_wr_opcode_info {
+ char *name;
+ enum rxe_wr_mask mask[WR_MAX_QPT];
+};
+
+extern struct rxe_wr_opcode_info rxe_wr_opcode_info[];
+
+enum rxe_hdr_type {
+ RXE_LRH,
+ RXE_GRH,
+ RXE_BTH,
+ RXE_RETH,
+ RXE_AETH,
+ RXE_ATMETH,
+ RXE_ATMACK,
+ RXE_IETH,
+ RXE_RDETH,
+ RXE_DETH,
+ RXE_IMMDT,
+ RXE_PAYLOAD,
+ NUM_HDR_TYPES
+};
+
+enum rxe_hdr_mask {
+ RXE_LRH_MASK = BIT(RXE_LRH),
+ RXE_GRH_MASK = BIT(RXE_GRH),
+ RXE_BTH_MASK = BIT(RXE_BTH),
+ RXE_IMMDT_MASK = BIT(RXE_IMMDT),
+ RXE_RETH_MASK = BIT(RXE_RETH),
+ RXE_AETH_MASK = BIT(RXE_AETH),
+ RXE_ATMETH_MASK = BIT(RXE_ATMETH),
+ RXE_ATMACK_MASK = BIT(RXE_ATMACK),
+ RXE_IETH_MASK = BIT(RXE_IETH),
+ RXE_RDETH_MASK = BIT(RXE_RDETH),
+ RXE_DETH_MASK = BIT(RXE_DETH),
+ RXE_PAYLOAD_MASK = BIT(RXE_PAYLOAD),
+
+ RXE_REQ_MASK = BIT(NUM_HDR_TYPES + 0),
+ RXE_ACK_MASK = BIT(NUM_HDR_TYPES + 1),
+ RXE_SEND_MASK = BIT(NUM_HDR_TYPES + 2),
+ RXE_WRITE_MASK = BIT(NUM_HDR_TYPES + 3),
+ RXE_READ_MASK = BIT(NUM_HDR_TYPES + 4),
+ RXE_ATOMIC_MASK = BIT(NUM_HDR_TYPES + 5),
+
+ RXE_RWR_MASK = BIT(NUM_HDR_TYPES + 6),
+ RXE_COMP_MASK = BIT(NUM_HDR_TYPES + 7),
+
+ RXE_START_MASK = BIT(NUM_HDR_TYPES + 8),
+ RXE_MIDDLE_MASK = BIT(NUM_HDR_TYPES + 9),
+ RXE_END_MASK = BIT(NUM_HDR_TYPES + 10),
+
+ RXE_LOOPBACK_MASK = BIT(NUM_HDR_TYPES + 12),
+
+ RXE_READ_OR_ATOMIC = (RXE_READ_MASK | RXE_ATOMIC_MASK),
+ RXE_WRITE_OR_SEND = (RXE_WRITE_MASK | RXE_SEND_MASK),
+};
+
+#define OPCODE_NONE (-1)
+#define RXE_NUM_OPCODE 256
+
+struct rxe_opcode_info {
+ char *name;
+ enum rxe_hdr_mask mask;
+ int length;
+ int offset[NUM_HDR_TYPES];
+};
+
+extern struct rxe_opcode_info rxe_opcode[RXE_NUM_OPCODE];
+
+#endif /* RXE_OPCODE_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_param.h b/drivers/infiniband/sw/rxe/rxe_param.h
new file mode 100644
index 000000000000..f459c43a77c8
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_param.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_PARAM_H
+#define RXE_PARAM_H
+
+static inline enum ib_mtu rxe_mtu_int_to_enum(int mtu)
+{
+ if (mtu < 256)
+ return 0;
+ else if (mtu < 512)
+ return IB_MTU_256;
+ else if (mtu < 1024)
+ return IB_MTU_512;
+ else if (mtu < 2048)
+ return IB_MTU_1024;
+ else if (mtu < 4096)
+ return IB_MTU_2048;
+ else
+ return IB_MTU_4096;
+}
+
+/* Find the IB mtu for a given network MTU. */
+static inline enum ib_mtu eth_mtu_int_to_enum(int mtu)
+{
+ mtu -= RXE_MAX_HDR_LENGTH;
+
+ return rxe_mtu_int_to_enum(mtu);
+}
+
+/* default/initial rxe device parameter settings */
+enum rxe_device_param {
+ RXE_FW_VER = 0,
+ RXE_MAX_MR_SIZE = -1ull,
+ RXE_PAGE_SIZE_CAP = 0xfffff000,
+ RXE_VENDOR_ID = 0,
+ RXE_VENDOR_PART_ID = 0,
+ RXE_HW_VER = 0,
+ RXE_MAX_QP = 0x10000,
+ RXE_MAX_QP_WR = 0x4000,
+ RXE_MAX_INLINE_DATA = 400,
+ RXE_DEVICE_CAP_FLAGS = IB_DEVICE_BAD_PKEY_CNTR
+ | IB_DEVICE_BAD_QKEY_CNTR
+ | IB_DEVICE_AUTO_PATH_MIG
+ | IB_DEVICE_CHANGE_PHY_PORT
+ | IB_DEVICE_UD_AV_PORT_ENFORCE
+ | IB_DEVICE_PORT_ACTIVE_EVENT
+ | IB_DEVICE_SYS_IMAGE_GUID
+ | IB_DEVICE_RC_RNR_NAK_GEN
+ | IB_DEVICE_SRQ_RESIZE
+ | IB_DEVICE_MEM_MGT_EXTENSIONS,
+ RXE_MAX_SGE = 32,
+ RXE_MAX_SGE_RD = 32,
+ RXE_MAX_CQ = 16384,
+ RXE_MAX_LOG_CQE = 13,
+ RXE_MAX_MR = 2 * 1024,
+ RXE_MAX_PD = 0x7ffc,
+ RXE_MAX_QP_RD_ATOM = 128,
+ RXE_MAX_EE_RD_ATOM = 0,
+ RXE_MAX_RES_RD_ATOM = 0x3f000,
+ RXE_MAX_QP_INIT_RD_ATOM = 128,
+ RXE_MAX_EE_INIT_RD_ATOM = 0,
+ RXE_ATOMIC_CAP = 1,
+ RXE_MAX_EE = 0,
+ RXE_MAX_RDD = 0,
+ RXE_MAX_MW = 0,
+ RXE_MAX_RAW_IPV6_QP = 0,
+ RXE_MAX_RAW_ETHY_QP = 0,
+ RXE_MAX_MCAST_GRP = 8192,
+ RXE_MAX_MCAST_QP_ATTACH = 56,
+ RXE_MAX_TOT_MCAST_QP_ATTACH = 0x70000,
+ RXE_MAX_AH = 100,
+ RXE_MAX_FMR = 0,
+ RXE_MAX_MAP_PER_FMR = 0,
+ RXE_MAX_SRQ = 960,
+ RXE_MAX_SRQ_WR = 0x4000,
+ RXE_MIN_SRQ_WR = 1,
+ RXE_MAX_SRQ_SGE = 27,
+ RXE_MIN_SRQ_SGE = 1,
+ RXE_MAX_FMR_PAGE_LIST_LEN = 512,
+ RXE_MAX_PKEYS = 64,
+ RXE_LOCAL_CA_ACK_DELAY = 15,
+
+ RXE_MAX_UCONTEXT = 512,
+
+ RXE_NUM_PORT = 1,
+ RXE_NUM_COMP_VECTORS = 1,
+
+ RXE_MIN_QP_INDEX = 16,
+ RXE_MAX_QP_INDEX = 0x00020000,
+
+ RXE_MIN_SRQ_INDEX = 0x00020001,
+ RXE_MAX_SRQ_INDEX = 0x00040000,
+
+ RXE_MIN_MR_INDEX = 0x00000001,
+ RXE_MAX_MR_INDEX = 0x00040000,
+ RXE_MIN_MW_INDEX = 0x00040001,
+ RXE_MAX_MW_INDEX = 0x00060000,
+ RXE_MAX_PKT_PER_ACK = 64,
+
+ RXE_MAX_UNACKED_PSNS = 128,
+
+ /* Max inflight SKBs per queue pair */
+ RXE_INFLIGHT_SKBS_PER_QP_HIGH = 64,
+ RXE_INFLIGHT_SKBS_PER_QP_LOW = 16,
+
+ /* Delay before calling arbiter timer */
+ RXE_NSEC_ARB_TIMER_DELAY = 200,
+};
+
+/* default/initial rxe port parameters */
+enum rxe_port_param {
+ RXE_PORT_STATE = IB_PORT_DOWN,
+ RXE_PORT_MAX_MTU = IB_MTU_4096,
+ RXE_PORT_ACTIVE_MTU = IB_MTU_256,
+ RXE_PORT_GID_TBL_LEN = 1024,
+ RXE_PORT_PORT_CAP_FLAGS = RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP,
+ RXE_PORT_MAX_MSG_SZ = 0x800000,
+ RXE_PORT_BAD_PKEY_CNTR = 0,
+ RXE_PORT_QKEY_VIOL_CNTR = 0,
+ RXE_PORT_LID = 0,
+ RXE_PORT_SM_LID = 0,
+ RXE_PORT_SM_SL = 0,
+ RXE_PORT_LMC = 0,
+ RXE_PORT_MAX_VL_NUM = 1,
+ RXE_PORT_SUBNET_TIMEOUT = 0,
+ RXE_PORT_INIT_TYPE_REPLY = 0,
+ RXE_PORT_ACTIVE_WIDTH = IB_WIDTH_1X,
+ RXE_PORT_ACTIVE_SPEED = 1,
+ RXE_PORT_PKEY_TBL_LEN = 64,
+ RXE_PORT_PHYS_STATE = 2,
+ RXE_PORT_SUBNET_PREFIX = 0xfe80000000000000ULL,
+};
+
+/* default/initial port info parameters */
+enum rxe_port_info_param {
+ RXE_PORT_INFO_VL_CAP = 4, /* 1-8 */
+ RXE_PORT_INFO_MTU_CAP = 5, /* 4096 */
+ RXE_PORT_INFO_OPER_VL = 1, /* 1 */
+};
+
+#endif /* RXE_PARAM_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c
new file mode 100644
index 000000000000..6bac0717c540
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_pool.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+/* info about object pools
+ * note that mr and mw share a single index space
+ * so that one can map an lkey to the correct type of object
+ */
+struct rxe_type_info rxe_type_info[RXE_NUM_TYPES] = {
+ [RXE_TYPE_UC] = {
+ .name = "rxe-uc",
+ .size = sizeof(struct rxe_ucontext),
+ },
+ [RXE_TYPE_PD] = {
+ .name = "rxe-pd",
+ .size = sizeof(struct rxe_pd),
+ },
+ [RXE_TYPE_AH] = {
+ .name = "rxe-ah",
+ .size = sizeof(struct rxe_ah),
+ .flags = RXE_POOL_ATOMIC,
+ },
+ [RXE_TYPE_SRQ] = {
+ .name = "rxe-srq",
+ .size = sizeof(struct rxe_srq),
+ .flags = RXE_POOL_INDEX,
+ .min_index = RXE_MIN_SRQ_INDEX,
+ .max_index = RXE_MAX_SRQ_INDEX,
+ },
+ [RXE_TYPE_QP] = {
+ .name = "rxe-qp",
+ .size = sizeof(struct rxe_qp),
+ .cleanup = rxe_qp_cleanup,
+ .flags = RXE_POOL_INDEX,
+ .min_index = RXE_MIN_QP_INDEX,
+ .max_index = RXE_MAX_QP_INDEX,
+ },
+ [RXE_TYPE_CQ] = {
+ .name = "rxe-cq",
+ .size = sizeof(struct rxe_cq),
+ .cleanup = rxe_cq_cleanup,
+ },
+ [RXE_TYPE_MR] = {
+ .name = "rxe-mr",
+ .size = sizeof(struct rxe_mem),
+ .cleanup = rxe_mem_cleanup,
+ .flags = RXE_POOL_INDEX,
+ .max_index = RXE_MAX_MR_INDEX,
+ .min_index = RXE_MIN_MR_INDEX,
+ },
+ [RXE_TYPE_MW] = {
+ .name = "rxe-mw",
+ .size = sizeof(struct rxe_mem),
+ .flags = RXE_POOL_INDEX,
+ .max_index = RXE_MAX_MW_INDEX,
+ .min_index = RXE_MIN_MW_INDEX,
+ },
+ [RXE_TYPE_MC_GRP] = {
+ .name = "rxe-mc_grp",
+ .size = sizeof(struct rxe_mc_grp),
+ .cleanup = rxe_mc_cleanup,
+ .flags = RXE_POOL_KEY,
+ .key_offset = offsetof(struct rxe_mc_grp, mgid),
+ .key_size = sizeof(union ib_gid),
+ },
+ [RXE_TYPE_MC_ELEM] = {
+ .name = "rxe-mc_elem",
+ .size = sizeof(struct rxe_mc_elem),
+ .flags = RXE_POOL_ATOMIC,
+ },
+};
+
+static inline char *pool_name(struct rxe_pool *pool)
+{
+ return rxe_type_info[pool->type].name;
+}
+
+static inline struct kmem_cache *pool_cache(struct rxe_pool *pool)
+{
+ return rxe_type_info[pool->type].cache;
+}
+
+static inline enum rxe_elem_type rxe_type(void *arg)
+{
+ struct rxe_pool_entry *elem = arg;
+
+ return elem->pool->type;
+}
+
+int rxe_cache_init(void)
+{
+ int err;
+ int i;
+ size_t size;
+ struct rxe_type_info *type;
+
+ for (i = 0; i < RXE_NUM_TYPES; i++) {
+ type = &rxe_type_info[i];
+ size = ALIGN(type->size, RXE_POOL_ALIGN);
+ type->cache = kmem_cache_create(type->name, size,
+ RXE_POOL_ALIGN,
+ RXE_POOL_CACHE_FLAGS, NULL);
+ if (!type->cache) {
+ pr_err("Unable to init kmem cache for %s\n",
+ type->name);
+ err = -ENOMEM;
+ goto err1;
+ }
+ }
+
+ return 0;
+
+err1:
+ while (--i >= 0) {
+ kmem_cache_destroy(type->cache);
+ type->cache = NULL;
+ }
+
+ return err;
+}
+
+void rxe_cache_exit(void)
+{
+ int i;
+ struct rxe_type_info *type;
+
+ for (i = 0; i < RXE_NUM_TYPES; i++) {
+ type = &rxe_type_info[i];
+ kmem_cache_destroy(type->cache);
+ type->cache = NULL;
+ }
+}
+
+static int rxe_pool_init_index(struct rxe_pool *pool, u32 max, u32 min)
+{
+ int err = 0;
+ size_t size;
+
+ if ((max - min + 1) < pool->max_elem) {
+ pr_warn("not enough indices for max_elem\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ pool->max_index = max;
+ pool->min_index = min;
+
+ size = BITS_TO_LONGS(max - min + 1) * sizeof(long);
+ pool->table = kmalloc(size, GFP_KERNEL);
+ if (!pool->table) {
+ pr_warn("no memory for bit table\n");
+ err = -ENOMEM;
+ goto out;
+ }
+
+ pool->table_size = size;
+ bitmap_zero(pool->table, max - min + 1);
+
+out:
+ return err;
+}
+
+int rxe_pool_init(
+ struct rxe_dev *rxe,
+ struct rxe_pool *pool,
+ enum rxe_elem_type type,
+ unsigned max_elem)
+{
+ int err = 0;
+ size_t size = rxe_type_info[type].size;
+
+ memset(pool, 0, sizeof(*pool));
+
+ pool->rxe = rxe;
+ pool->type = type;
+ pool->max_elem = max_elem;
+ pool->elem_size = ALIGN(size, RXE_POOL_ALIGN);
+ pool->flags = rxe_type_info[type].flags;
+ pool->tree = RB_ROOT;
+ pool->cleanup = rxe_type_info[type].cleanup;
+
+ atomic_set(&pool->num_elem, 0);
+
+ kref_init(&pool->ref_cnt);
+
+ spin_lock_init(&pool->pool_lock);
+
+ if (rxe_type_info[type].flags & RXE_POOL_INDEX) {
+ err = rxe_pool_init_index(pool,
+ rxe_type_info[type].max_index,
+ rxe_type_info[type].min_index);
+ if (err)
+ goto out;
+ }
+
+ if (rxe_type_info[type].flags & RXE_POOL_KEY) {
+ pool->key_offset = rxe_type_info[type].key_offset;
+ pool->key_size = rxe_type_info[type].key_size;
+ }
+
+ pool->state = rxe_pool_valid;
+
+out:
+ return err;
+}
+
+static void rxe_pool_release(struct kref *kref)
+{
+ struct rxe_pool *pool = container_of(kref, struct rxe_pool, ref_cnt);
+
+ pool->state = rxe_pool_invalid;
+ kfree(pool->table);
+}
+
+static void rxe_pool_put(struct rxe_pool *pool)
+{
+ kref_put(&pool->ref_cnt, rxe_pool_release);
+}
+
+int rxe_pool_cleanup(struct rxe_pool *pool)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ pool->state = rxe_pool_invalid;
+ if (atomic_read(&pool->num_elem) > 0)
+ pr_warn("%s pool destroyed with unfree'd elem\n",
+ pool_name(pool));
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+
+ rxe_pool_put(pool);
+
+ return 0;
+}
+
+static u32 alloc_index(struct rxe_pool *pool)
+{
+ u32 index;
+ u32 range = pool->max_index - pool->min_index + 1;
+
+ index = find_next_zero_bit(pool->table, range, pool->last);
+ if (index >= range)
+ index = find_first_zero_bit(pool->table, range);
+
+ set_bit(index, pool->table);
+ pool->last = index;
+ return index + pool->min_index;
+}
+
+static void insert_index(struct rxe_pool *pool, struct rxe_pool_entry *new)
+{
+ struct rb_node **link = &pool->tree.rb_node;
+ struct rb_node *parent = NULL;
+ struct rxe_pool_entry *elem;
+
+ while (*link) {
+ parent = *link;
+ elem = rb_entry(parent, struct rxe_pool_entry, node);
+
+ if (elem->index == new->index) {
+ pr_warn("element already exists!\n");
+ goto out;
+ }
+
+ if (elem->index > new->index)
+ link = &(*link)->rb_left;
+ else
+ link = &(*link)->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, link);
+ rb_insert_color(&new->node, &pool->tree);
+out:
+ return;
+}
+
+static void insert_key(struct rxe_pool *pool, struct rxe_pool_entry *new)
+{
+ struct rb_node **link = &pool->tree.rb_node;
+ struct rb_node *parent = NULL;
+ struct rxe_pool_entry *elem;
+ int cmp;
+
+ while (*link) {
+ parent = *link;
+ elem = rb_entry(parent, struct rxe_pool_entry, node);
+
+ cmp = memcmp((u8 *)elem + pool->key_offset,
+ (u8 *)new + pool->key_offset, pool->key_size);
+
+ if (cmp == 0) {
+ pr_warn("key already exists!\n");
+ goto out;
+ }
+
+ if (cmp > 0)
+ link = &(*link)->rb_left;
+ else
+ link = &(*link)->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, link);
+ rb_insert_color(&new->node, &pool->tree);
+out:
+ return;
+}
+
+void rxe_add_key(void *arg, void *key)
+{
+ struct rxe_pool_entry *elem = arg;
+ struct rxe_pool *pool = elem->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ memcpy((u8 *)elem + pool->key_offset, key, pool->key_size);
+ insert_key(pool, elem);
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+}
+
+void rxe_drop_key(void *arg)
+{
+ struct rxe_pool_entry *elem = arg;
+ struct rxe_pool *pool = elem->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ rb_erase(&elem->node, &pool->tree);
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+}
+
+void rxe_add_index(void *arg)
+{
+ struct rxe_pool_entry *elem = arg;
+ struct rxe_pool *pool = elem->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ elem->index = alloc_index(pool);
+ insert_index(pool, elem);
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+}
+
+void rxe_drop_index(void *arg)
+{
+ struct rxe_pool_entry *elem = arg;
+ struct rxe_pool *pool = elem->pool;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ clear_bit(elem->index - pool->min_index, pool->table);
+ rb_erase(&elem->node, &pool->tree);
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+}
+
+void *rxe_alloc(struct rxe_pool *pool)
+{
+ struct rxe_pool_entry *elem;
+ unsigned long flags;
+
+ might_sleep_if(!(pool->flags & RXE_POOL_ATOMIC));
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+ if (pool->state != rxe_pool_valid) {
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+ return NULL;
+ }
+ kref_get(&pool->ref_cnt);
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+
+ kref_get(&pool->rxe->ref_cnt);
+
+ if (atomic_inc_return(&pool->num_elem) > pool->max_elem) {
+ atomic_dec(&pool->num_elem);
+ rxe_dev_put(pool->rxe);
+ rxe_pool_put(pool);
+ return NULL;
+ }
+
+ elem = kmem_cache_zalloc(pool_cache(pool),
+ (pool->flags & RXE_POOL_ATOMIC) ?
+ GFP_ATOMIC : GFP_KERNEL);
+
+ elem->pool = pool;
+ kref_init(&elem->ref_cnt);
+
+ return elem;
+}
+
+void rxe_elem_release(struct kref *kref)
+{
+ struct rxe_pool_entry *elem =
+ container_of(kref, struct rxe_pool_entry, ref_cnt);
+ struct rxe_pool *pool = elem->pool;
+
+ if (pool->cleanup)
+ pool->cleanup(elem);
+
+ kmem_cache_free(pool_cache(pool), elem);
+ atomic_dec(&pool->num_elem);
+ rxe_dev_put(pool->rxe);
+ rxe_pool_put(pool);
+}
+
+void *rxe_pool_get_index(struct rxe_pool *pool, u32 index)
+{
+ struct rb_node *node = NULL;
+ struct rxe_pool_entry *elem = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+
+ if (pool->state != rxe_pool_valid)
+ goto out;
+
+ node = pool->tree.rb_node;
+
+ while (node) {
+ elem = rb_entry(node, struct rxe_pool_entry, node);
+
+ if (elem->index > index)
+ node = node->rb_left;
+ else if (elem->index < index)
+ node = node->rb_right;
+ else
+ break;
+ }
+
+ if (node)
+ kref_get(&elem->ref_cnt);
+
+out:
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+ return node ? (void *)elem : NULL;
+}
+
+void *rxe_pool_get_key(struct rxe_pool *pool, void *key)
+{
+ struct rb_node *node = NULL;
+ struct rxe_pool_entry *elem = NULL;
+ int cmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pool->pool_lock, flags);
+
+ if (pool->state != rxe_pool_valid)
+ goto out;
+
+ node = pool->tree.rb_node;
+
+ while (node) {
+ elem = rb_entry(node, struct rxe_pool_entry, node);
+
+ cmp = memcmp((u8 *)elem + pool->key_offset,
+ key, pool->key_size);
+
+ if (cmp > 0)
+ node = node->rb_left;
+ else if (cmp < 0)
+ node = node->rb_right;
+ else
+ break;
+ }
+
+ if (node)
+ kref_get(&elem->ref_cnt);
+
+out:
+ spin_unlock_irqrestore(&pool->pool_lock, flags);
+ return node ? ((void *)elem) : NULL;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_pool.h b/drivers/infiniband/sw/rxe/rxe_pool.h
new file mode 100644
index 000000000000..4d04830adcae
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_pool.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_POOL_H
+#define RXE_POOL_H
+
+#define RXE_POOL_ALIGN (16)
+#define RXE_POOL_CACHE_FLAGS (0)
+
+enum rxe_pool_flags {
+ RXE_POOL_ATOMIC = BIT(0),
+ RXE_POOL_INDEX = BIT(1),
+ RXE_POOL_KEY = BIT(2),
+};
+
+enum rxe_elem_type {
+ RXE_TYPE_UC,
+ RXE_TYPE_PD,
+ RXE_TYPE_AH,
+ RXE_TYPE_SRQ,
+ RXE_TYPE_QP,
+ RXE_TYPE_CQ,
+ RXE_TYPE_MR,
+ RXE_TYPE_MW,
+ RXE_TYPE_MC_GRP,
+ RXE_TYPE_MC_ELEM,
+ RXE_NUM_TYPES, /* keep me last */
+};
+
+struct rxe_type_info {
+ char *name;
+ size_t size;
+ void (*cleanup)(void *obj);
+ enum rxe_pool_flags flags;
+ u32 max_index;
+ u32 min_index;
+ size_t key_offset;
+ size_t key_size;
+ struct kmem_cache *cache;
+};
+
+extern struct rxe_type_info rxe_type_info[];
+
+enum rxe_pool_state {
+ rxe_pool_invalid,
+ rxe_pool_valid,
+};
+
+struct rxe_pool_entry {
+ struct rxe_pool *pool;
+ struct kref ref_cnt;
+ struct list_head list;
+
+ /* only used if indexed or keyed */
+ struct rb_node node;
+ u32 index;
+};
+
+struct rxe_pool {
+ struct rxe_dev *rxe;
+ spinlock_t pool_lock; /* pool spinlock */
+ size_t elem_size;
+ struct kref ref_cnt;
+ void (*cleanup)(void *obj);
+ enum rxe_pool_state state;
+ enum rxe_pool_flags flags;
+ enum rxe_elem_type type;
+
+ unsigned int max_elem;
+ atomic_t num_elem;
+
+ /* only used if indexed or keyed */
+ struct rb_root tree;
+ unsigned long *table;
+ size_t table_size;
+ u32 max_index;
+ u32 min_index;
+ u32 last;
+ size_t key_offset;
+ size_t key_size;
+};
+
+/* initialize slab caches for managed objects */
+int rxe_cache_init(void);
+
+/* cleanup slab caches for managed objects */
+void rxe_cache_exit(void);
+
+/* initialize a pool of objects with given limit on
+ * number of elements. gets parameters from rxe_type_info
+ * pool elements will be allocated out of a slab cache
+ */
+int rxe_pool_init(struct rxe_dev *rxe, struct rxe_pool *pool,
+ enum rxe_elem_type type, u32 max_elem);
+
+/* free resources from object pool */
+int rxe_pool_cleanup(struct rxe_pool *pool);
+
+/* allocate an object from pool */
+void *rxe_alloc(struct rxe_pool *pool);
+
+/* assign an index to an indexed object and insert object into
+ * pool's rb tree
+ */
+void rxe_add_index(void *elem);
+
+/* drop an index and remove object from rb tree */
+void rxe_drop_index(void *elem);
+
+/* assign a key to a keyed object and insert object into
+ * pool's rb tree
+ */
+void rxe_add_key(void *elem, void *key);
+
+/* remove elem from rb tree */
+void rxe_drop_key(void *elem);
+
+/* lookup an indexed object from index. takes a reference on object */
+void *rxe_pool_get_index(struct rxe_pool *pool, u32 index);
+
+/* lookup keyed object from key. takes a reference on the object */
+void *rxe_pool_get_key(struct rxe_pool *pool, void *key);
+
+/* cleanup an object when all references are dropped */
+void rxe_elem_release(struct kref *kref);
+
+/* take a reference on an object */
+#define rxe_add_ref(elem) kref_get(&(elem)->pelem.ref_cnt)
+
+/* drop a reference on an object */
+#define rxe_drop_ref(elem) kref_put(&(elem)->pelem.ref_cnt, rxe_elem_release)
+
+#endif /* RXE_POOL_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c
new file mode 100644
index 000000000000..22ba24f2a2c1
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_qp.c
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+#include "rxe_task.h"
+
+char *rxe_qp_state_name[] = {
+ [QP_STATE_RESET] = "RESET",
+ [QP_STATE_INIT] = "INIT",
+ [QP_STATE_READY] = "READY",
+ [QP_STATE_DRAIN] = "DRAIN",
+ [QP_STATE_DRAINED] = "DRAINED",
+ [QP_STATE_ERROR] = "ERROR",
+};
+
+static int rxe_qp_chk_cap(struct rxe_dev *rxe, struct ib_qp_cap *cap,
+ int has_srq)
+{
+ if (cap->max_send_wr > rxe->attr.max_qp_wr) {
+ pr_warn("invalid send wr = %d > %d\n",
+ cap->max_send_wr, rxe->attr.max_qp_wr);
+ goto err1;
+ }
+
+ if (cap->max_send_sge > rxe->attr.max_sge) {
+ pr_warn("invalid send sge = %d > %d\n",
+ cap->max_send_sge, rxe->attr.max_sge);
+ goto err1;
+ }
+
+ if (!has_srq) {
+ if (cap->max_recv_wr > rxe->attr.max_qp_wr) {
+ pr_warn("invalid recv wr = %d > %d\n",
+ cap->max_recv_wr, rxe->attr.max_qp_wr);
+ goto err1;
+ }
+
+ if (cap->max_recv_sge > rxe->attr.max_sge) {
+ pr_warn("invalid recv sge = %d > %d\n",
+ cap->max_recv_sge, rxe->attr.max_sge);
+ goto err1;
+ }
+ }
+
+ if (cap->max_inline_data > rxe->max_inline_data) {
+ pr_warn("invalid max inline data = %d > %d\n",
+ cap->max_inline_data, rxe->max_inline_data);
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+int rxe_qp_chk_init(struct rxe_dev *rxe, struct ib_qp_init_attr *init)
+{
+ struct ib_qp_cap *cap = &init->cap;
+ struct rxe_port *port;
+ int port_num = init->port_num;
+
+ if (!init->recv_cq || !init->send_cq) {
+ pr_warn("missing cq\n");
+ goto err1;
+ }
+
+ if (rxe_qp_chk_cap(rxe, cap, !!init->srq))
+ goto err1;
+
+ if (init->qp_type == IB_QPT_SMI || init->qp_type == IB_QPT_GSI) {
+ if (port_num != 1) {
+ pr_warn("invalid port = %d\n", port_num);
+ goto err1;
+ }
+
+ port = &rxe->port;
+
+ if (init->qp_type == IB_QPT_SMI && port->qp_smi_index) {
+ pr_warn("SMI QP exists for port %d\n", port_num);
+ goto err1;
+ }
+
+ if (init->qp_type == IB_QPT_GSI && port->qp_gsi_index) {
+ pr_warn("GSI QP exists for port %d\n", port_num);
+ goto err1;
+ }
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static int alloc_rd_atomic_resources(struct rxe_qp *qp, unsigned int n)
+{
+ qp->resp.res_head = 0;
+ qp->resp.res_tail = 0;
+ qp->resp.resources = kcalloc(n, sizeof(struct resp_res), GFP_KERNEL);
+
+ if (!qp->resp.resources)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void free_rd_atomic_resources(struct rxe_qp *qp)
+{
+ if (qp->resp.resources) {
+ int i;
+
+ for (i = 0; i < qp->attr.max_rd_atomic; i++) {
+ struct resp_res *res = &qp->resp.resources[i];
+
+ free_rd_atomic_resource(qp, res);
+ }
+ kfree(qp->resp.resources);
+ qp->resp.resources = NULL;
+ }
+}
+
+void free_rd_atomic_resource(struct rxe_qp *qp, struct resp_res *res)
+{
+ if (res->type == RXE_ATOMIC_MASK) {
+ rxe_drop_ref(qp);
+ kfree_skb(res->atomic.skb);
+ } else if (res->type == RXE_READ_MASK) {
+ if (res->read.mr)
+ rxe_drop_ref(res->read.mr);
+ }
+ res->type = 0;
+}
+
+static void cleanup_rd_atomic_resources(struct rxe_qp *qp)
+{
+ int i;
+ struct resp_res *res;
+
+ if (qp->resp.resources) {
+ for (i = 0; i < qp->attr.max_rd_atomic; i++) {
+ res = &qp->resp.resources[i];
+ free_rd_atomic_resource(qp, res);
+ }
+ }
+}
+
+static void rxe_qp_init_misc(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct ib_qp_init_attr *init)
+{
+ struct rxe_port *port;
+ u32 qpn;
+
+ qp->sq_sig_type = init->sq_sig_type;
+ qp->attr.path_mtu = 1;
+ qp->mtu = ib_mtu_enum_to_int(qp->attr.path_mtu);
+
+ qpn = qp->pelem.index;
+ port = &rxe->port;
+
+ switch (init->qp_type) {
+ case IB_QPT_SMI:
+ qp->ibqp.qp_num = 0;
+ port->qp_smi_index = qpn;
+ qp->attr.port_num = init->port_num;
+ break;
+
+ case IB_QPT_GSI:
+ qp->ibqp.qp_num = 1;
+ port->qp_gsi_index = qpn;
+ qp->attr.port_num = init->port_num;
+ break;
+
+ default:
+ qp->ibqp.qp_num = qpn;
+ break;
+ }
+
+ INIT_LIST_HEAD(&qp->grp_list);
+
+ skb_queue_head_init(&qp->send_pkts);
+
+ spin_lock_init(&qp->grp_lock);
+ spin_lock_init(&qp->state_lock);
+
+ atomic_set(&qp->ssn, 0);
+ atomic_set(&qp->skb_out, 0);
+}
+
+static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct ib_qp_init_attr *init,
+ struct ib_ucontext *context, struct ib_udata *udata)
+{
+ int err;
+ int wqe_size;
+
+ err = sock_create_kern(&init_net, AF_INET, SOCK_DGRAM, 0, &qp->sk);
+ if (err < 0)
+ return err;
+ qp->sk->sk->sk_user_data = qp;
+
+ qp->sq.max_wr = init->cap.max_send_wr;
+ qp->sq.max_sge = init->cap.max_send_sge;
+ qp->sq.max_inline = init->cap.max_inline_data;
+
+ wqe_size = max_t(int, sizeof(struct rxe_send_wqe) +
+ qp->sq.max_sge * sizeof(struct ib_sge),
+ sizeof(struct rxe_send_wqe) +
+ qp->sq.max_inline);
+
+ qp->sq.queue = rxe_queue_init(rxe,
+ &qp->sq.max_wr,
+ wqe_size);
+ if (!qp->sq.queue)
+ return -ENOMEM;
+
+ err = do_mmap_info(rxe, udata, true,
+ context, qp->sq.queue->buf,
+ qp->sq.queue->buf_size, &qp->sq.queue->ip);
+
+ if (err) {
+ kvfree(qp->sq.queue->buf);
+ kfree(qp->sq.queue);
+ return err;
+ }
+
+ qp->req.wqe_index = producer_index(qp->sq.queue);
+ qp->req.state = QP_STATE_RESET;
+ qp->req.opcode = -1;
+ qp->comp.opcode = -1;
+
+ spin_lock_init(&qp->sq.sq_lock);
+ skb_queue_head_init(&qp->req_pkts);
+
+ rxe_init_task(rxe, &qp->req.task, qp,
+ rxe_requester, "req");
+ rxe_init_task(rxe, &qp->comp.task, qp,
+ rxe_completer, "comp");
+
+ init_timer(&qp->rnr_nak_timer);
+ qp->rnr_nak_timer.function = rnr_nak_timer;
+ qp->rnr_nak_timer.data = (unsigned long)qp;
+
+ init_timer(&qp->retrans_timer);
+ qp->retrans_timer.function = retransmit_timer;
+ qp->retrans_timer.data = (unsigned long)qp;
+ qp->qp_timeout_jiffies = 0; /* Can't be set for UD/UC in modify_qp */
+
+ return 0;
+}
+
+static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct ib_qp_init_attr *init,
+ struct ib_ucontext *context, struct ib_udata *udata)
+{
+ int err;
+ int wqe_size;
+
+ if (!qp->srq) {
+ qp->rq.max_wr = init->cap.max_recv_wr;
+ qp->rq.max_sge = init->cap.max_recv_sge;
+
+ wqe_size = rcv_wqe_size(qp->rq.max_sge);
+
+ pr_debug("max_wr = %d, max_sge = %d, wqe_size = %d\n",
+ qp->rq.max_wr, qp->rq.max_sge, wqe_size);
+
+ qp->rq.queue = rxe_queue_init(rxe,
+ &qp->rq.max_wr,
+ wqe_size);
+ if (!qp->rq.queue)
+ return -ENOMEM;
+
+ err = do_mmap_info(rxe, udata, false, context,
+ qp->rq.queue->buf,
+ qp->rq.queue->buf_size,
+ &qp->rq.queue->ip);
+ if (err) {
+ kvfree(qp->rq.queue->buf);
+ kfree(qp->rq.queue);
+ return err;
+ }
+ }
+
+ spin_lock_init(&qp->rq.producer_lock);
+ spin_lock_init(&qp->rq.consumer_lock);
+
+ skb_queue_head_init(&qp->resp_pkts);
+
+ rxe_init_task(rxe, &qp->resp.task, qp,
+ rxe_responder, "resp");
+
+ qp->resp.opcode = OPCODE_NONE;
+ qp->resp.msn = 0;
+ qp->resp.state = QP_STATE_RESET;
+
+ return 0;
+}
+
+/* called by the create qp verb */
+int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
+ struct ib_qp_init_attr *init, struct ib_udata *udata,
+ struct ib_pd *ibpd)
+{
+ int err;
+ struct rxe_cq *rcq = to_rcq(init->recv_cq);
+ struct rxe_cq *scq = to_rcq(init->send_cq);
+ struct rxe_srq *srq = init->srq ? to_rsrq(init->srq) : NULL;
+ struct ib_ucontext *context = udata ? ibpd->uobject->context : NULL;
+
+ rxe_add_ref(pd);
+ rxe_add_ref(rcq);
+ rxe_add_ref(scq);
+ if (srq)
+ rxe_add_ref(srq);
+
+ qp->pd = pd;
+ qp->rcq = rcq;
+ qp->scq = scq;
+ qp->srq = srq;
+
+ rxe_qp_init_misc(rxe, qp, init);
+
+ err = rxe_qp_init_req(rxe, qp, init, context, udata);
+ if (err)
+ goto err1;
+
+ err = rxe_qp_init_resp(rxe, qp, init, context, udata);
+ if (err)
+ goto err2;
+
+ qp->attr.qp_state = IB_QPS_RESET;
+ qp->valid = 1;
+
+ return 0;
+
+err2:
+ rxe_queue_cleanup(qp->sq.queue);
+err1:
+ if (srq)
+ rxe_drop_ref(srq);
+ rxe_drop_ref(scq);
+ rxe_drop_ref(rcq);
+ rxe_drop_ref(pd);
+
+ return err;
+}
+
+/* called by the query qp verb */
+int rxe_qp_to_init(struct rxe_qp *qp, struct ib_qp_init_attr *init)
+{
+ init->event_handler = qp->ibqp.event_handler;
+ init->qp_context = qp->ibqp.qp_context;
+ init->send_cq = qp->ibqp.send_cq;
+ init->recv_cq = qp->ibqp.recv_cq;
+ init->srq = qp->ibqp.srq;
+
+ init->cap.max_send_wr = qp->sq.max_wr;
+ init->cap.max_send_sge = qp->sq.max_sge;
+ init->cap.max_inline_data = qp->sq.max_inline;
+
+ if (!qp->srq) {
+ init->cap.max_recv_wr = qp->rq.max_wr;
+ init->cap.max_recv_sge = qp->rq.max_sge;
+ }
+
+ init->sq_sig_type = qp->sq_sig_type;
+
+ init->qp_type = qp->ibqp.qp_type;
+ init->port_num = 1;
+
+ return 0;
+}
+
+/* called by the modify qp verb, this routine checks all the parameters before
+ * making any changes
+ */
+int rxe_qp_chk_attr(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct ib_qp_attr *attr, int mask)
+{
+ enum ib_qp_state cur_state = (mask & IB_QP_CUR_STATE) ?
+ attr->cur_qp_state : qp->attr.qp_state;
+ enum ib_qp_state new_state = (mask & IB_QP_STATE) ?
+ attr->qp_state : cur_state;
+
+ if (!ib_modify_qp_is_ok(cur_state, new_state, qp_type(qp), mask,
+ IB_LINK_LAYER_ETHERNET)) {
+ pr_warn("invalid mask or state for qp\n");
+ goto err1;
+ }
+
+ if (mask & IB_QP_STATE) {
+ if (cur_state == IB_QPS_SQD) {
+ if (qp->req.state == QP_STATE_DRAIN &&
+ new_state != IB_QPS_ERR)
+ goto err1;
+ }
+ }
+
+ if (mask & IB_QP_PORT) {
+ if (attr->port_num != 1) {
+ pr_warn("invalid port %d\n", attr->port_num);
+ goto err1;
+ }
+ }
+
+ if (mask & IB_QP_CAP && rxe_qp_chk_cap(rxe, &attr->cap, !!qp->srq))
+ goto err1;
+
+ if (mask & IB_QP_AV && rxe_av_chk_attr(rxe, &attr->ah_attr))
+ goto err1;
+
+ if (mask & IB_QP_ALT_PATH) {
+ if (rxe_av_chk_attr(rxe, &attr->alt_ah_attr))
+ goto err1;
+ if (attr->alt_port_num != 1) {
+ pr_warn("invalid alt port %d\n", attr->alt_port_num);
+ goto err1;
+ }
+ if (attr->alt_timeout > 31) {
+ pr_warn("invalid QP alt timeout %d > 31\n",
+ attr->alt_timeout);
+ goto err1;
+ }
+ }
+
+ if (mask & IB_QP_PATH_MTU) {
+ struct rxe_port *port = &rxe->port;
+
+ enum ib_mtu max_mtu = port->attr.max_mtu;
+ enum ib_mtu mtu = attr->path_mtu;
+
+ if (mtu > max_mtu) {
+ pr_debug("invalid mtu (%d) > (%d)\n",
+ ib_mtu_enum_to_int(mtu),
+ ib_mtu_enum_to_int(max_mtu));
+ goto err1;
+ }
+ }
+
+ if (mask & IB_QP_MAX_QP_RD_ATOMIC) {
+ if (attr->max_rd_atomic > rxe->attr.max_qp_rd_atom) {
+ pr_warn("invalid max_rd_atomic %d > %d\n",
+ attr->max_rd_atomic,
+ rxe->attr.max_qp_rd_atom);
+ goto err1;
+ }
+ }
+
+ if (mask & IB_QP_TIMEOUT) {
+ if (attr->timeout > 31) {
+ pr_warn("invalid QP timeout %d > 31\n",
+ attr->timeout);
+ goto err1;
+ }
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+/* move the qp to the reset state */
+static void rxe_qp_reset(struct rxe_qp *qp)
+{
+ /* stop tasks from running */
+ rxe_disable_task(&qp->resp.task);
+
+ /* stop request/comp */
+ if (qp->sq.queue) {
+ if (qp_type(qp) == IB_QPT_RC)
+ rxe_disable_task(&qp->comp.task);
+ rxe_disable_task(&qp->req.task);
+ }
+
+ /* move qp to the reset state */
+ qp->req.state = QP_STATE_RESET;
+ qp->resp.state = QP_STATE_RESET;
+
+ /* let state machines reset themselves drain work and packet queues
+ * etc.
+ */
+ __rxe_do_task(&qp->resp.task);
+
+ if (qp->sq.queue) {
+ __rxe_do_task(&qp->comp.task);
+ __rxe_do_task(&qp->req.task);
+ }
+
+ /* cleanup attributes */
+ atomic_set(&qp->ssn, 0);
+ qp->req.opcode = -1;
+ qp->req.need_retry = 0;
+ qp->req.noack_pkts = 0;
+ qp->resp.msn = 0;
+ qp->resp.opcode = -1;
+ qp->resp.drop_msg = 0;
+ qp->resp.goto_error = 0;
+ qp->resp.sent_psn_nak = 0;
+
+ if (qp->resp.mr) {
+ rxe_drop_ref(qp->resp.mr);
+ qp->resp.mr = NULL;
+ }
+
+ cleanup_rd_atomic_resources(qp);
+
+ /* reenable tasks */
+ rxe_enable_task(&qp->resp.task);
+
+ if (qp->sq.queue) {
+ if (qp_type(qp) == IB_QPT_RC)
+ rxe_enable_task(&qp->comp.task);
+
+ rxe_enable_task(&qp->req.task);
+ }
+}
+
+/* drain the send queue */
+static void rxe_qp_drain(struct rxe_qp *qp)
+{
+ if (qp->sq.queue) {
+ if (qp->req.state != QP_STATE_DRAINED) {
+ qp->req.state = QP_STATE_DRAIN;
+ if (qp_type(qp) == IB_QPT_RC)
+ rxe_run_task(&qp->comp.task, 1);
+ else
+ __rxe_do_task(&qp->comp.task);
+ rxe_run_task(&qp->req.task, 1);
+ }
+ }
+}
+
+/* move the qp to the error state */
+void rxe_qp_error(struct rxe_qp *qp)
+{
+ qp->req.state = QP_STATE_ERROR;
+ qp->resp.state = QP_STATE_ERROR;
+
+ /* drain work and packet queues */
+ rxe_run_task(&qp->resp.task, 1);
+
+ if (qp_type(qp) == IB_QPT_RC)
+ rxe_run_task(&qp->comp.task, 1);
+ else
+ __rxe_do_task(&qp->comp.task);
+ rxe_run_task(&qp->req.task, 1);
+}
+
+/* called by the modify qp verb */
+int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ union ib_gid sgid;
+ struct ib_gid_attr sgid_attr;
+
+ if (mask & IB_QP_MAX_QP_RD_ATOMIC) {
+ int max_rd_atomic = __roundup_pow_of_two(attr->max_rd_atomic);
+
+ free_rd_atomic_resources(qp);
+
+ err = alloc_rd_atomic_resources(qp, max_rd_atomic);
+ if (err)
+ return err;
+
+ qp->attr.max_rd_atomic = max_rd_atomic;
+ atomic_set(&qp->req.rd_atomic, max_rd_atomic);
+ }
+
+ if (mask & IB_QP_CUR_STATE)
+ qp->attr.cur_qp_state = attr->qp_state;
+
+ if (mask & IB_QP_EN_SQD_ASYNC_NOTIFY)
+ qp->attr.en_sqd_async_notify = attr->en_sqd_async_notify;
+
+ if (mask & IB_QP_ACCESS_FLAGS)
+ qp->attr.qp_access_flags = attr->qp_access_flags;
+
+ if (mask & IB_QP_PKEY_INDEX)
+ qp->attr.pkey_index = attr->pkey_index;
+
+ if (mask & IB_QP_PORT)
+ qp->attr.port_num = attr->port_num;
+
+ if (mask & IB_QP_QKEY)
+ qp->attr.qkey = attr->qkey;
+
+ if (mask & IB_QP_AV) {
+ ib_get_cached_gid(&rxe->ib_dev, 1,
+ attr->ah_attr.grh.sgid_index, &sgid,
+ &sgid_attr);
+ rxe_av_from_attr(rxe, attr->port_num, &qp->pri_av,
+ &attr->ah_attr);
+ rxe_av_fill_ip_info(rxe, &qp->pri_av, &attr->ah_attr,
+ &sgid_attr, &sgid);
+ if (sgid_attr.ndev)
+ dev_put(sgid_attr.ndev);
+ }
+
+ if (mask & IB_QP_ALT_PATH) {
+ ib_get_cached_gid(&rxe->ib_dev, 1,
+ attr->alt_ah_attr.grh.sgid_index, &sgid,
+ &sgid_attr);
+
+ rxe_av_from_attr(rxe, attr->alt_port_num, &qp->alt_av,
+ &attr->alt_ah_attr);
+ rxe_av_fill_ip_info(rxe, &qp->alt_av, &attr->alt_ah_attr,
+ &sgid_attr, &sgid);
+ if (sgid_attr.ndev)
+ dev_put(sgid_attr.ndev);
+
+ qp->attr.alt_port_num = attr->alt_port_num;
+ qp->attr.alt_pkey_index = attr->alt_pkey_index;
+ qp->attr.alt_timeout = attr->alt_timeout;
+ }
+
+ if (mask & IB_QP_PATH_MTU) {
+ qp->attr.path_mtu = attr->path_mtu;
+ qp->mtu = ib_mtu_enum_to_int(attr->path_mtu);
+ }
+
+ if (mask & IB_QP_TIMEOUT) {
+ qp->attr.timeout = attr->timeout;
+ if (attr->timeout == 0) {
+ qp->qp_timeout_jiffies = 0;
+ } else {
+ /* According to the spec, timeout = 4.096 * 2 ^ attr->timeout [us] */
+ int j = nsecs_to_jiffies(4096ULL << attr->timeout);
+
+ qp->qp_timeout_jiffies = j ? j : 1;
+ }
+ }
+
+ if (mask & IB_QP_RETRY_CNT) {
+ qp->attr.retry_cnt = attr->retry_cnt;
+ qp->comp.retry_cnt = attr->retry_cnt;
+ pr_debug("set retry count = %d\n", attr->retry_cnt);
+ }
+
+ if (mask & IB_QP_RNR_RETRY) {
+ qp->attr.rnr_retry = attr->rnr_retry;
+ qp->comp.rnr_retry = attr->rnr_retry;
+ pr_debug("set rnr retry count = %d\n", attr->rnr_retry);
+ }
+
+ if (mask & IB_QP_RQ_PSN) {
+ qp->attr.rq_psn = (attr->rq_psn & BTH_PSN_MASK);
+ qp->resp.psn = qp->attr.rq_psn;
+ pr_debug("set resp psn = 0x%x\n", qp->resp.psn);
+ }
+
+ if (mask & IB_QP_MIN_RNR_TIMER) {
+ qp->attr.min_rnr_timer = attr->min_rnr_timer;
+ pr_debug("set min rnr timer = 0x%x\n",
+ attr->min_rnr_timer);
+ }
+
+ if (mask & IB_QP_SQ_PSN) {
+ qp->attr.sq_psn = (attr->sq_psn & BTH_PSN_MASK);
+ qp->req.psn = qp->attr.sq_psn;
+ qp->comp.psn = qp->attr.sq_psn;
+ pr_debug("set req psn = 0x%x\n", qp->req.psn);
+ }
+
+ if (mask & IB_QP_MAX_DEST_RD_ATOMIC) {
+ qp->attr.max_dest_rd_atomic =
+ __roundup_pow_of_two(attr->max_dest_rd_atomic);
+ }
+
+ if (mask & IB_QP_PATH_MIG_STATE)
+ qp->attr.path_mig_state = attr->path_mig_state;
+
+ if (mask & IB_QP_DEST_QPN)
+ qp->attr.dest_qp_num = attr->dest_qp_num;
+
+ if (mask & IB_QP_STATE) {
+ qp->attr.qp_state = attr->qp_state;
+
+ switch (attr->qp_state) {
+ case IB_QPS_RESET:
+ pr_debug("qp state -> RESET\n");
+ rxe_qp_reset(qp);
+ break;
+
+ case IB_QPS_INIT:
+ pr_debug("qp state -> INIT\n");
+ qp->req.state = QP_STATE_INIT;
+ qp->resp.state = QP_STATE_INIT;
+ break;
+
+ case IB_QPS_RTR:
+ pr_debug("qp state -> RTR\n");
+ qp->resp.state = QP_STATE_READY;
+ break;
+
+ case IB_QPS_RTS:
+ pr_debug("qp state -> RTS\n");
+ qp->req.state = QP_STATE_READY;
+ break;
+
+ case IB_QPS_SQD:
+ pr_debug("qp state -> SQD\n");
+ rxe_qp_drain(qp);
+ break;
+
+ case IB_QPS_SQE:
+ pr_warn("qp state -> SQE !!?\n");
+ /* Not possible from modify_qp. */
+ break;
+
+ case IB_QPS_ERR:
+ pr_debug("qp state -> ERR\n");
+ rxe_qp_error(qp);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* called by the query qp verb */
+int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+
+ *attr = qp->attr;
+
+ attr->rq_psn = qp->resp.psn;
+ attr->sq_psn = qp->req.psn;
+
+ attr->cap.max_send_wr = qp->sq.max_wr;
+ attr->cap.max_send_sge = qp->sq.max_sge;
+ attr->cap.max_inline_data = qp->sq.max_inline;
+
+ if (!qp->srq) {
+ attr->cap.max_recv_wr = qp->rq.max_wr;
+ attr->cap.max_recv_sge = qp->rq.max_sge;
+ }
+
+ rxe_av_to_attr(rxe, &qp->pri_av, &attr->ah_attr);
+ rxe_av_to_attr(rxe, &qp->alt_av, &attr->alt_ah_attr);
+
+ if (qp->req.state == QP_STATE_DRAIN) {
+ attr->sq_draining = 1;
+ /* applications that get this state
+ * typically spin on it. yield the
+ * processor
+ */
+ cond_resched();
+ } else {
+ attr->sq_draining = 0;
+ }
+
+ pr_debug("attr->sq_draining = %d\n", attr->sq_draining);
+
+ return 0;
+}
+
+/* called by the destroy qp verb */
+void rxe_qp_destroy(struct rxe_qp *qp)
+{
+ qp->valid = 0;
+ qp->qp_timeout_jiffies = 0;
+ rxe_cleanup_task(&qp->resp.task);
+
+ del_timer_sync(&qp->retrans_timer);
+ del_timer_sync(&qp->rnr_nak_timer);
+
+ rxe_cleanup_task(&qp->req.task);
+ if (qp_type(qp) == IB_QPT_RC)
+ rxe_cleanup_task(&qp->comp.task);
+
+ /* flush out any receive wr's or pending requests */
+ __rxe_do_task(&qp->req.task);
+ if (qp->sq.queue) {
+ __rxe_do_task(&qp->comp.task);
+ __rxe_do_task(&qp->req.task);
+ }
+}
+
+/* called when the last reference to the qp is dropped */
+void rxe_qp_cleanup(void *arg)
+{
+ struct rxe_qp *qp = arg;
+
+ rxe_drop_all_mcast_groups(qp);
+
+ if (qp->sq.queue)
+ rxe_queue_cleanup(qp->sq.queue);
+
+ if (qp->srq)
+ rxe_drop_ref(qp->srq);
+
+ if (qp->rq.queue)
+ rxe_queue_cleanup(qp->rq.queue);
+
+ if (qp->scq)
+ rxe_drop_ref(qp->scq);
+ if (qp->rcq)
+ rxe_drop_ref(qp->rcq);
+ if (qp->pd)
+ rxe_drop_ref(qp->pd);
+
+ if (qp->resp.mr) {
+ rxe_drop_ref(qp->resp.mr);
+ qp->resp.mr = NULL;
+ }
+
+ free_rd_atomic_resources(qp);
+
+ kernel_sock_shutdown(qp->sk, SHUT_RDWR);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c
new file mode 100644
index 000000000000..08274254eb88
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_queue.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must retailuce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/vmalloc.h>
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+int do_mmap_info(struct rxe_dev *rxe,
+ struct ib_udata *udata,
+ bool is_req,
+ struct ib_ucontext *context,
+ struct rxe_queue_buf *buf,
+ size_t buf_size,
+ struct rxe_mmap_info **ip_p)
+{
+ int err;
+ u32 len, offset;
+ struct rxe_mmap_info *ip = NULL;
+
+ if (udata) {
+ if (is_req) {
+ len = udata->outlen - sizeof(struct mminfo);
+ offset = sizeof(struct mminfo);
+ } else {
+ len = udata->outlen;
+ offset = 0;
+ }
+
+ if (len < sizeof(ip->info))
+ goto err1;
+
+ ip = rxe_create_mmap_info(rxe, buf_size, context, buf);
+ if (!ip)
+ goto err1;
+
+ err = copy_to_user(udata->outbuf + offset, &ip->info,
+ sizeof(ip->info));
+ if (err)
+ goto err2;
+
+ spin_lock_bh(&rxe->pending_lock);
+ list_add(&ip->pending_mmaps, &rxe->pending_mmaps);
+ spin_unlock_bh(&rxe->pending_lock);
+ }
+
+ *ip_p = ip;
+
+ return 0;
+
+err2:
+ kfree(ip);
+err1:
+ return -EINVAL;
+}
+
+struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe,
+ int *num_elem,
+ unsigned int elem_size)
+{
+ struct rxe_queue *q;
+ size_t buf_size;
+ unsigned int num_slots;
+
+ /* num_elem == 0 is allowed, but uninteresting */
+ if (*num_elem < 0)
+ goto err1;
+
+ q = kmalloc(sizeof(*q), GFP_KERNEL);
+ if (!q)
+ goto err1;
+
+ q->rxe = rxe;
+
+ /* used in resize, only need to copy used part of queue */
+ q->elem_size = elem_size;
+
+ /* pad element up to at least a cacheline and always a power of 2 */
+ if (elem_size < cache_line_size())
+ elem_size = cache_line_size();
+ elem_size = roundup_pow_of_two(elem_size);
+
+ q->log2_elem_size = order_base_2(elem_size);
+
+ num_slots = *num_elem + 1;
+ num_slots = roundup_pow_of_two(num_slots);
+ q->index_mask = num_slots - 1;
+
+ buf_size = sizeof(struct rxe_queue_buf) + num_slots * elem_size;
+
+ q->buf = vmalloc_user(buf_size);
+ if (!q->buf)
+ goto err2;
+
+ q->buf->log2_elem_size = q->log2_elem_size;
+ q->buf->index_mask = q->index_mask;
+
+ q->buf_size = buf_size;
+
+ *num_elem = num_slots - 1;
+ return q;
+
+err2:
+ kfree(q);
+err1:
+ return NULL;
+}
+
+/* copies elements from original q to new q and then swaps the contents of the
+ * two q headers. This is so that if anyone is holding a pointer to q it will
+ * still work
+ */
+static int resize_finish(struct rxe_queue *q, struct rxe_queue *new_q,
+ unsigned int num_elem)
+{
+ if (!queue_empty(q) && (num_elem < queue_count(q)))
+ return -EINVAL;
+
+ while (!queue_empty(q)) {
+ memcpy(producer_addr(new_q), consumer_addr(q),
+ new_q->elem_size);
+ advance_producer(new_q);
+ advance_consumer(q);
+ }
+
+ swap(*q, *new_q);
+
+ return 0;
+}
+
+int rxe_queue_resize(struct rxe_queue *q,
+ unsigned int *num_elem_p,
+ unsigned int elem_size,
+ struct ib_ucontext *context,
+ struct ib_udata *udata,
+ spinlock_t *producer_lock,
+ spinlock_t *consumer_lock)
+{
+ struct rxe_queue *new_q;
+ unsigned int num_elem = *num_elem_p;
+ int err;
+ unsigned long flags = 0, flags1;
+
+ new_q = rxe_queue_init(q->rxe, &num_elem, elem_size);
+ if (!new_q)
+ return -ENOMEM;
+
+ err = do_mmap_info(new_q->rxe, udata, false, context, new_q->buf,
+ new_q->buf_size, &new_q->ip);
+ if (err) {
+ vfree(new_q->buf);
+ kfree(new_q);
+ goto err1;
+ }
+
+ spin_lock_irqsave(consumer_lock, flags1);
+
+ if (producer_lock) {
+ spin_lock_irqsave(producer_lock, flags);
+ err = resize_finish(q, new_q, num_elem);
+ spin_unlock_irqrestore(producer_lock, flags);
+ } else {
+ err = resize_finish(q, new_q, num_elem);
+ }
+
+ spin_unlock_irqrestore(consumer_lock, flags1);
+
+ rxe_queue_cleanup(new_q); /* new/old dep on err */
+ if (err)
+ goto err1;
+
+ *num_elem_p = num_elem;
+ return 0;
+
+err1:
+ return err;
+}
+
+void rxe_queue_cleanup(struct rxe_queue *q)
+{
+ if (q->ip)
+ kref_put(&q->ip->ref, rxe_mmap_release);
+ else
+ vfree(q->buf);
+
+ kfree(q);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_queue.h b/drivers/infiniband/sw/rxe/rxe_queue.h
new file mode 100644
index 000000000000..239fd609c31e
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_queue.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_QUEUE_H
+#define RXE_QUEUE_H
+
+/* implements a simple circular buffer that can optionally be
+ * shared between user space and the kernel and can be resized
+
+ * the requested element size is rounded up to a power of 2
+ * and the number of elements in the buffer is also rounded
+ * up to a power of 2. Since the queue is empty when the
+ * producer and consumer indices match the maximum capacity
+ * of the queue is one less than the number of element slots
+ */
+
+/* this data structure is shared between user space and kernel
+ * space for those cases where the queue is shared. It contains
+ * the producer and consumer indices. Is also contains a copy
+ * of the queue size parameters for user space to use but the
+ * kernel must use the parameters in the rxe_queue struct
+ * this MUST MATCH the corresponding librxe struct
+ * for performance reasons arrange to have producer and consumer
+ * pointers in separate cache lines
+ * the kernel should always mask the indices to avoid accessing
+ * memory outside of the data area
+ */
+struct rxe_queue_buf {
+ __u32 log2_elem_size;
+ __u32 index_mask;
+ __u32 pad_1[30];
+ __u32 producer_index;
+ __u32 pad_2[31];
+ __u32 consumer_index;
+ __u32 pad_3[31];
+ __u8 data[0];
+};
+
+struct rxe_queue {
+ struct rxe_dev *rxe;
+ struct rxe_queue_buf *buf;
+ struct rxe_mmap_info *ip;
+ size_t buf_size;
+ size_t elem_size;
+ unsigned int log2_elem_size;
+ unsigned int index_mask;
+};
+
+int do_mmap_info(struct rxe_dev *rxe,
+ struct ib_udata *udata,
+ bool is_req,
+ struct ib_ucontext *context,
+ struct rxe_queue_buf *buf,
+ size_t buf_size,
+ struct rxe_mmap_info **ip_p);
+
+struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe,
+ int *num_elem,
+ unsigned int elem_size);
+
+int rxe_queue_resize(struct rxe_queue *q,
+ unsigned int *num_elem_p,
+ unsigned int elem_size,
+ struct ib_ucontext *context,
+ struct ib_udata *udata,
+ /* Protect producers while resizing queue */
+ spinlock_t *producer_lock,
+ /* Protect consumers while resizing queue */
+ spinlock_t *consumer_lock);
+
+void rxe_queue_cleanup(struct rxe_queue *queue);
+
+static inline int next_index(struct rxe_queue *q, int index)
+{
+ return (index + 1) & q->buf->index_mask;
+}
+
+static inline int queue_empty(struct rxe_queue *q)
+{
+ return ((q->buf->producer_index - q->buf->consumer_index)
+ & q->index_mask) == 0;
+}
+
+static inline int queue_full(struct rxe_queue *q)
+{
+ return ((q->buf->producer_index + 1 - q->buf->consumer_index)
+ & q->index_mask) == 0;
+}
+
+static inline void advance_producer(struct rxe_queue *q)
+{
+ q->buf->producer_index = (q->buf->producer_index + 1)
+ & q->index_mask;
+}
+
+static inline void advance_consumer(struct rxe_queue *q)
+{
+ q->buf->consumer_index = (q->buf->consumer_index + 1)
+ & q->index_mask;
+}
+
+static inline void *producer_addr(struct rxe_queue *q)
+{
+ return q->buf->data + ((q->buf->producer_index & q->index_mask)
+ << q->log2_elem_size);
+}
+
+static inline void *consumer_addr(struct rxe_queue *q)
+{
+ return q->buf->data + ((q->buf->consumer_index & q->index_mask)
+ << q->log2_elem_size);
+}
+
+static inline unsigned int producer_index(struct rxe_queue *q)
+{
+ return q->buf->producer_index;
+}
+
+static inline unsigned int consumer_index(struct rxe_queue *q)
+{
+ return q->buf->consumer_index;
+}
+
+static inline void *addr_from_index(struct rxe_queue *q, unsigned int index)
+{
+ return q->buf->data + ((index & q->index_mask)
+ << q->buf->log2_elem_size);
+}
+
+static inline unsigned int index_from_addr(const struct rxe_queue *q,
+ const void *addr)
+{
+ return (((u8 *)addr - q->buf->data) >> q->log2_elem_size)
+ & q->index_mask;
+}
+
+static inline unsigned int queue_count(const struct rxe_queue *q)
+{
+ return (q->buf->producer_index - q->buf->consumer_index)
+ & q->index_mask;
+}
+
+static inline void *queue_head(struct rxe_queue *q)
+{
+ return queue_empty(q) ? NULL : consumer_addr(q);
+}
+
+#endif /* RXE_QUEUE_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c
new file mode 100644
index 000000000000..3d464c23e08b
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_recv.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+
+static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct rxe_qp *qp)
+{
+ if (unlikely(!qp->valid))
+ goto err1;
+
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ if (unlikely((pkt->opcode & IB_OPCODE_RC) != 0)) {
+ pr_warn_ratelimited("bad qp type\n");
+ goto err1;
+ }
+ break;
+ case IB_QPT_UC:
+ if (unlikely(!(pkt->opcode & IB_OPCODE_UC))) {
+ pr_warn_ratelimited("bad qp type\n");
+ goto err1;
+ }
+ break;
+ case IB_QPT_UD:
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ if (unlikely(!(pkt->opcode & IB_OPCODE_UD))) {
+ pr_warn_ratelimited("bad qp type\n");
+ goto err1;
+ }
+ break;
+ default:
+ pr_warn_ratelimited("unsupported qp type\n");
+ goto err1;
+ }
+
+ if (pkt->mask & RXE_REQ_MASK) {
+ if (unlikely(qp->resp.state != QP_STATE_READY))
+ goto err1;
+ } else if (unlikely(qp->req.state < QP_STATE_READY ||
+ qp->req.state > QP_STATE_DRAINED)) {
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static void set_bad_pkey_cntr(struct rxe_port *port)
+{
+ spin_lock_bh(&port->port_lock);
+ port->attr.bad_pkey_cntr = min((u32)0xffff,
+ port->attr.bad_pkey_cntr + 1);
+ spin_unlock_bh(&port->port_lock);
+}
+
+static void set_qkey_viol_cntr(struct rxe_port *port)
+{
+ spin_lock_bh(&port->port_lock);
+ port->attr.qkey_viol_cntr = min((u32)0xffff,
+ port->attr.qkey_viol_cntr + 1);
+ spin_unlock_bh(&port->port_lock);
+}
+
+static int check_keys(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ u32 qpn, struct rxe_qp *qp)
+{
+ int i;
+ int found_pkey = 0;
+ struct rxe_port *port = &rxe->port;
+ u16 pkey = bth_pkey(pkt);
+
+ pkt->pkey_index = 0;
+
+ if (qpn == 1) {
+ for (i = 0; i < port->attr.pkey_tbl_len; i++) {
+ if (pkey_match(pkey, port->pkey_tbl[i])) {
+ pkt->pkey_index = i;
+ found_pkey = 1;
+ break;
+ }
+ }
+
+ if (!found_pkey) {
+ pr_warn_ratelimited("bad pkey = 0x%x\n", pkey);
+ set_bad_pkey_cntr(port);
+ goto err1;
+ }
+ } else if (qpn != 0) {
+ if (unlikely(!pkey_match(pkey,
+ port->pkey_tbl[qp->attr.pkey_index]
+ ))) {
+ pr_warn_ratelimited("bad pkey = 0x%0x\n", pkey);
+ set_bad_pkey_cntr(port);
+ goto err1;
+ }
+ pkt->pkey_index = qp->attr.pkey_index;
+ }
+
+ if ((qp_type(qp) == IB_QPT_UD || qp_type(qp) == IB_QPT_GSI) &&
+ qpn != 0 && pkt->mask) {
+ u32 qkey = (qpn == 1) ? GSI_QKEY : qp->attr.qkey;
+
+ if (unlikely(deth_qkey(pkt) != qkey)) {
+ pr_warn_ratelimited("bad qkey, got 0x%x expected 0x%x for qpn 0x%x\n",
+ deth_qkey(pkt), qkey, qpn);
+ set_qkey_viol_cntr(port);
+ goto err1;
+ }
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static int check_addr(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct rxe_qp *qp)
+{
+ struct sk_buff *skb = PKT_TO_SKB(pkt);
+
+ if (qp_type(qp) != IB_QPT_RC && qp_type(qp) != IB_QPT_UC)
+ goto done;
+
+ if (unlikely(pkt->port_num != qp->attr.port_num)) {
+ pr_warn_ratelimited("port %d != qp port %d\n",
+ pkt->port_num, qp->attr.port_num);
+ goto err1;
+ }
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ struct in_addr *saddr =
+ &qp->pri_av.sgid_addr._sockaddr_in.sin_addr;
+ struct in_addr *daddr =
+ &qp->pri_av.dgid_addr._sockaddr_in.sin_addr;
+
+ if (ip_hdr(skb)->daddr != saddr->s_addr) {
+ pr_warn_ratelimited("dst addr %pI4 != qp source addr %pI4\n",
+ &ip_hdr(skb)->daddr,
+ &saddr->s_addr);
+ goto err1;
+ }
+
+ if (ip_hdr(skb)->saddr != daddr->s_addr) {
+ pr_warn_ratelimited("source addr %pI4 != qp dst addr %pI4\n",
+ &ip_hdr(skb)->saddr,
+ &daddr->s_addr);
+ goto err1;
+ }
+
+ } else if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct in6_addr *saddr =
+ &qp->pri_av.sgid_addr._sockaddr_in6.sin6_addr;
+ struct in6_addr *daddr =
+ &qp->pri_av.dgid_addr._sockaddr_in6.sin6_addr;
+
+ if (memcmp(&ipv6_hdr(skb)->daddr, saddr, sizeof(*saddr))) {
+ pr_warn_ratelimited("dst addr %pI6 != qp source addr %pI6\n",
+ &ipv6_hdr(skb)->daddr, saddr);
+ goto err1;
+ }
+
+ if (memcmp(&ipv6_hdr(skb)->saddr, daddr, sizeof(*daddr))) {
+ pr_warn_ratelimited("source addr %pI6 != qp dst addr %pI6\n",
+ &ipv6_hdr(skb)->saddr, daddr);
+ goto err1;
+ }
+ }
+
+done:
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static int hdr_check(struct rxe_pkt_info *pkt)
+{
+ struct rxe_dev *rxe = pkt->rxe;
+ struct rxe_port *port = &rxe->port;
+ struct rxe_qp *qp = NULL;
+ u32 qpn = bth_qpn(pkt);
+ int index;
+ int err;
+
+ if (unlikely(bth_tver(pkt) != BTH_TVER)) {
+ pr_warn_ratelimited("bad tver\n");
+ goto err1;
+ }
+
+ if (qpn != IB_MULTICAST_QPN) {
+ index = (qpn == 0) ? port->qp_smi_index :
+ ((qpn == 1) ? port->qp_gsi_index : qpn);
+ qp = rxe_pool_get_index(&rxe->qp_pool, index);
+ if (unlikely(!qp)) {
+ pr_warn_ratelimited("no qp matches qpn 0x%x\n", qpn);
+ goto err1;
+ }
+
+ err = check_type_state(rxe, pkt, qp);
+ if (unlikely(err))
+ goto err2;
+
+ err = check_addr(rxe, pkt, qp);
+ if (unlikely(err))
+ goto err2;
+
+ err = check_keys(rxe, pkt, qpn, qp);
+ if (unlikely(err))
+ goto err2;
+ } else {
+ if (unlikely((pkt->mask & RXE_GRH_MASK) == 0)) {
+ pr_warn_ratelimited("no grh for mcast qpn\n");
+ goto err1;
+ }
+ }
+
+ pkt->qp = qp;
+ return 0;
+
+err2:
+ if (qp)
+ rxe_drop_ref(qp);
+err1:
+ return -EINVAL;
+}
+
+static inline void rxe_rcv_pkt(struct rxe_dev *rxe,
+ struct rxe_pkt_info *pkt,
+ struct sk_buff *skb)
+{
+ if (pkt->mask & RXE_REQ_MASK)
+ rxe_resp_queue_pkt(rxe, pkt->qp, skb);
+ else
+ rxe_comp_queue_pkt(rxe, pkt->qp, skb);
+}
+
+static void rxe_rcv_mcast_pkt(struct rxe_dev *rxe, struct sk_buff *skb)
+{
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+ struct rxe_mc_grp *mcg;
+ struct sk_buff *skb_copy;
+ struct rxe_mc_elem *mce;
+ struct rxe_qp *qp;
+ union ib_gid dgid;
+ int err;
+
+ if (skb->protocol == htons(ETH_P_IP))
+ ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr,
+ (struct in6_addr *)&dgid);
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ memcpy(&dgid, &ipv6_hdr(skb)->daddr, sizeof(dgid));
+
+ /* lookup mcast group corresponding to mgid, takes a ref */
+ mcg = rxe_pool_get_key(&rxe->mc_grp_pool, &dgid);
+ if (!mcg)
+ goto err1; /* mcast group not registered */
+
+ spin_lock_bh(&mcg->mcg_lock);
+
+ list_for_each_entry(mce, &mcg->qp_list, qp_list) {
+ qp = mce->qp;
+ pkt = SKB_TO_PKT(skb);
+
+ /* validate qp for incoming packet */
+ err = check_type_state(rxe, pkt, qp);
+ if (err)
+ continue;
+
+ err = check_keys(rxe, pkt, bth_qpn(pkt), qp);
+ if (err)
+ continue;
+
+ /* if *not* the last qp in the list
+ * make a copy of the skb to post to the next qp
+ */
+ skb_copy = (mce->qp_list.next != &mcg->qp_list) ?
+ skb_clone(skb, GFP_KERNEL) : NULL;
+
+ pkt->qp = qp;
+ rxe_add_ref(qp);
+ rxe_rcv_pkt(rxe, pkt, skb);
+
+ skb = skb_copy;
+ if (!skb)
+ break;
+ }
+
+ spin_unlock_bh(&mcg->mcg_lock);
+
+ rxe_drop_ref(mcg); /* drop ref from rxe_pool_get_key. */
+
+err1:
+ if (skb)
+ kfree_skb(skb);
+}
+
+static int rxe_match_dgid(struct rxe_dev *rxe, struct sk_buff *skb)
+{
+ union ib_gid dgid;
+ union ib_gid *pdgid;
+ u16 index;
+
+ if (skb->protocol == htons(ETH_P_IP)) {
+ ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr,
+ (struct in6_addr *)&dgid);
+ pdgid = &dgid;
+ } else {
+ pdgid = (union ib_gid *)&ipv6_hdr(skb)->daddr;
+ }
+
+ return ib_find_cached_gid_by_port(&rxe->ib_dev, pdgid,
+ IB_GID_TYPE_ROCE_UDP_ENCAP,
+ 1, rxe->ndev, &index);
+}
+
+/* rxe_rcv is called from the interface driver */
+int rxe_rcv(struct sk_buff *skb)
+{
+ int err;
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+ struct rxe_dev *rxe = pkt->rxe;
+ __be32 *icrcp;
+ u32 calc_icrc, pack_icrc;
+
+ pkt->offset = 0;
+
+ if (unlikely(skb->len < pkt->offset + RXE_BTH_BYTES))
+ goto drop;
+
+ if (unlikely(rxe_match_dgid(rxe, skb) < 0)) {
+ pr_warn_ratelimited("failed matching dgid\n");
+ goto drop;
+ }
+
+ pkt->opcode = bth_opcode(pkt);
+ pkt->psn = bth_psn(pkt);
+ pkt->qp = NULL;
+ pkt->mask |= rxe_opcode[pkt->opcode].mask;
+
+ if (unlikely(skb->len < header_size(pkt)))
+ goto drop;
+
+ err = hdr_check(pkt);
+ if (unlikely(err))
+ goto drop;
+
+ /* Verify ICRC */
+ icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
+ pack_icrc = be32_to_cpu(*icrcp);
+
+ calc_icrc = rxe_icrc_hdr(pkt, skb);
+ calc_icrc = crc32_le(calc_icrc, (u8 *)payload_addr(pkt), payload_size(pkt));
+ calc_icrc = cpu_to_be32(~calc_icrc);
+ if (unlikely(calc_icrc != pack_icrc)) {
+ char saddr[sizeof(struct in6_addr)];
+
+ if (skb->protocol == htons(ETH_P_IPV6))
+ sprintf(saddr, "%pI6", &ipv6_hdr(skb)->saddr);
+ else if (skb->protocol == htons(ETH_P_IP))
+ sprintf(saddr, "%pI4", &ip_hdr(skb)->saddr);
+ else
+ sprintf(saddr, "unknown");
+
+ pr_warn_ratelimited("bad ICRC from %s\n", saddr);
+ goto drop;
+ }
+
+ if (unlikely(bth_qpn(pkt) == IB_MULTICAST_QPN))
+ rxe_rcv_mcast_pkt(rxe, skb);
+ else
+ rxe_rcv_pkt(rxe, pkt, skb);
+
+ return 0;
+
+drop:
+ if (pkt->qp)
+ rxe_drop_ref(pkt->qp);
+
+ kfree_skb(skb);
+ return 0;
+}
+EXPORT_SYMBOL(rxe_rcv);
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
new file mode 100644
index 000000000000..33b2d9d77021
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+static int next_opcode(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
+ unsigned opcode);
+
+static inline void retry_first_write_send(struct rxe_qp *qp,
+ struct rxe_send_wqe *wqe,
+ unsigned mask, int npsn)
+{
+ int i;
+
+ for (i = 0; i < npsn; i++) {
+ int to_send = (wqe->dma.resid > qp->mtu) ?
+ qp->mtu : wqe->dma.resid;
+
+ qp->req.opcode = next_opcode(qp, wqe,
+ wqe->wr.opcode);
+
+ if (wqe->wr.send_flags & IB_SEND_INLINE) {
+ wqe->dma.resid -= to_send;
+ wqe->dma.sge_offset += to_send;
+ } else {
+ advance_dma_data(&wqe->dma, to_send);
+ }
+ if (mask & WR_WRITE_MASK)
+ wqe->iova += qp->mtu;
+ }
+}
+
+static void req_retry(struct rxe_qp *qp)
+{
+ struct rxe_send_wqe *wqe;
+ unsigned int wqe_index;
+ unsigned int mask;
+ int npsn;
+ int first = 1;
+
+ wqe = queue_head(qp->sq.queue);
+ npsn = (qp->comp.psn - wqe->first_psn) & BTH_PSN_MASK;
+
+ qp->req.wqe_index = consumer_index(qp->sq.queue);
+ qp->req.psn = qp->comp.psn;
+ qp->req.opcode = -1;
+
+ for (wqe_index = consumer_index(qp->sq.queue);
+ wqe_index != producer_index(qp->sq.queue);
+ wqe_index = next_index(qp->sq.queue, wqe_index)) {
+ wqe = addr_from_index(qp->sq.queue, wqe_index);
+ mask = wr_opcode_mask(wqe->wr.opcode, qp);
+
+ if (wqe->state == wqe_state_posted)
+ break;
+
+ if (wqe->state == wqe_state_done)
+ continue;
+
+ wqe->iova = (mask & WR_ATOMIC_MASK) ?
+ wqe->wr.wr.atomic.remote_addr :
+ (mask & WR_READ_OR_WRITE_MASK) ?
+ wqe->wr.wr.rdma.remote_addr :
+ 0;
+
+ if (!first || (mask & WR_READ_MASK) == 0) {
+ wqe->dma.resid = wqe->dma.length;
+ wqe->dma.cur_sge = 0;
+ wqe->dma.sge_offset = 0;
+ }
+
+ if (first) {
+ first = 0;
+
+ if (mask & WR_WRITE_OR_SEND_MASK)
+ retry_first_write_send(qp, wqe, mask, npsn);
+
+ if (mask & WR_READ_MASK)
+ wqe->iova += npsn * qp->mtu;
+ }
+
+ wqe->state = wqe_state_posted;
+ }
+}
+
+void rnr_nak_timer(unsigned long data)
+{
+ struct rxe_qp *qp = (struct rxe_qp *)data;
+
+ pr_debug("rnr nak timer fired\n");
+ rxe_run_task(&qp->req.task, 1);
+}
+
+static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp)
+{
+ struct rxe_send_wqe *wqe = queue_head(qp->sq.queue);
+ unsigned long flags;
+
+ if (unlikely(qp->req.state == QP_STATE_DRAIN)) {
+ /* check to see if we are drained;
+ * state_lock used by requester and completer
+ */
+ spin_lock_irqsave(&qp->state_lock, flags);
+ do {
+ if (qp->req.state != QP_STATE_DRAIN) {
+ /* comp just finished */
+ spin_unlock_irqrestore(&qp->state_lock,
+ flags);
+ break;
+ }
+
+ if (wqe && ((qp->req.wqe_index !=
+ consumer_index(qp->sq.queue)) ||
+ (wqe->state != wqe_state_posted))) {
+ /* comp not done yet */
+ spin_unlock_irqrestore(&qp->state_lock,
+ flags);
+ break;
+ }
+
+ qp->req.state = QP_STATE_DRAINED;
+ spin_unlock_irqrestore(&qp->state_lock, flags);
+
+ if (qp->ibqp.event_handler) {
+ struct ib_event ev;
+
+ ev.device = qp->ibqp.device;
+ ev.element.qp = &qp->ibqp;
+ ev.event = IB_EVENT_SQ_DRAINED;
+ qp->ibqp.event_handler(&ev,
+ qp->ibqp.qp_context);
+ }
+ } while (0);
+ }
+
+ if (qp->req.wqe_index == producer_index(qp->sq.queue))
+ return NULL;
+
+ wqe = addr_from_index(qp->sq.queue, qp->req.wqe_index);
+
+ if (unlikely((qp->req.state == QP_STATE_DRAIN ||
+ qp->req.state == QP_STATE_DRAINED) &&
+ (wqe->state != wqe_state_processing)))
+ return NULL;
+
+ if (unlikely((wqe->wr.send_flags & IB_SEND_FENCE) &&
+ (qp->req.wqe_index != consumer_index(qp->sq.queue)))) {
+ qp->req.wait_fence = 1;
+ return NULL;
+ }
+
+ wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp);
+ return wqe;
+}
+
+static int next_opcode_rc(struct rxe_qp *qp, unsigned opcode, int fits)
+{
+ switch (opcode) {
+ case IB_WR_RDMA_WRITE:
+ if (qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_FIRST ||
+ qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_MIDDLE)
+ return fits ?
+ IB_OPCODE_RC_RDMA_WRITE_LAST :
+ IB_OPCODE_RC_RDMA_WRITE_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_RC_RDMA_WRITE_ONLY :
+ IB_OPCODE_RC_RDMA_WRITE_FIRST;
+
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ if (qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_FIRST ||
+ qp->req.opcode == IB_OPCODE_RC_RDMA_WRITE_MIDDLE)
+ return fits ?
+ IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE :
+ IB_OPCODE_RC_RDMA_WRITE_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_RC_RDMA_WRITE_ONLY_WITH_IMMEDIATE :
+ IB_OPCODE_RC_RDMA_WRITE_FIRST;
+
+ case IB_WR_SEND:
+ if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
+ qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
+ return fits ?
+ IB_OPCODE_RC_SEND_LAST :
+ IB_OPCODE_RC_SEND_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_RC_SEND_ONLY :
+ IB_OPCODE_RC_SEND_FIRST;
+
+ case IB_WR_SEND_WITH_IMM:
+ if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
+ qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
+ return fits ?
+ IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE :
+ IB_OPCODE_RC_SEND_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_RC_SEND_ONLY_WITH_IMMEDIATE :
+ IB_OPCODE_RC_SEND_FIRST;
+
+ case IB_WR_RDMA_READ:
+ return IB_OPCODE_RC_RDMA_READ_REQUEST;
+
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ return IB_OPCODE_RC_COMPARE_SWAP;
+
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ return IB_OPCODE_RC_FETCH_ADD;
+
+ case IB_WR_SEND_WITH_INV:
+ if (qp->req.opcode == IB_OPCODE_RC_SEND_FIRST ||
+ qp->req.opcode == IB_OPCODE_RC_SEND_MIDDLE)
+ return fits ? IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE :
+ IB_OPCODE_RC_SEND_MIDDLE;
+ else
+ return fits ? IB_OPCODE_RC_SEND_ONLY_WITH_INVALIDATE :
+ IB_OPCODE_RC_SEND_FIRST;
+ case IB_WR_REG_MR:
+ case IB_WR_LOCAL_INV:
+ return opcode;
+ }
+
+ return -EINVAL;
+}
+
+static int next_opcode_uc(struct rxe_qp *qp, unsigned opcode, int fits)
+{
+ switch (opcode) {
+ case IB_WR_RDMA_WRITE:
+ if (qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_FIRST ||
+ qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_MIDDLE)
+ return fits ?
+ IB_OPCODE_UC_RDMA_WRITE_LAST :
+ IB_OPCODE_UC_RDMA_WRITE_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_UC_RDMA_WRITE_ONLY :
+ IB_OPCODE_UC_RDMA_WRITE_FIRST;
+
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ if (qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_FIRST ||
+ qp->req.opcode == IB_OPCODE_UC_RDMA_WRITE_MIDDLE)
+ return fits ?
+ IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE :
+ IB_OPCODE_UC_RDMA_WRITE_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_UC_RDMA_WRITE_ONLY_WITH_IMMEDIATE :
+ IB_OPCODE_UC_RDMA_WRITE_FIRST;
+
+ case IB_WR_SEND:
+ if (qp->req.opcode == IB_OPCODE_UC_SEND_FIRST ||
+ qp->req.opcode == IB_OPCODE_UC_SEND_MIDDLE)
+ return fits ?
+ IB_OPCODE_UC_SEND_LAST :
+ IB_OPCODE_UC_SEND_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_UC_SEND_ONLY :
+ IB_OPCODE_UC_SEND_FIRST;
+
+ case IB_WR_SEND_WITH_IMM:
+ if (qp->req.opcode == IB_OPCODE_UC_SEND_FIRST ||
+ qp->req.opcode == IB_OPCODE_UC_SEND_MIDDLE)
+ return fits ?
+ IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE :
+ IB_OPCODE_UC_SEND_MIDDLE;
+ else
+ return fits ?
+ IB_OPCODE_UC_SEND_ONLY_WITH_IMMEDIATE :
+ IB_OPCODE_UC_SEND_FIRST;
+ }
+
+ return -EINVAL;
+}
+
+static int next_opcode(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
+ unsigned opcode)
+{
+ int fits = (wqe->dma.resid <= qp->mtu);
+
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ return next_opcode_rc(qp, opcode, fits);
+
+ case IB_QPT_UC:
+ return next_opcode_uc(qp, opcode, fits);
+
+ case IB_QPT_SMI:
+ case IB_QPT_UD:
+ case IB_QPT_GSI:
+ switch (opcode) {
+ case IB_WR_SEND:
+ return IB_OPCODE_UD_SEND_ONLY;
+
+ case IB_WR_SEND_WITH_IMM:
+ return IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static inline int check_init_depth(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
+{
+ int depth;
+
+ if (wqe->has_rd_atomic)
+ return 0;
+
+ qp->req.need_rd_atomic = 1;
+ depth = atomic_dec_return(&qp->req.rd_atomic);
+
+ if (depth >= 0) {
+ qp->req.need_rd_atomic = 0;
+ wqe->has_rd_atomic = 1;
+ return 0;
+ }
+
+ atomic_inc(&qp->req.rd_atomic);
+ return -EAGAIN;
+}
+
+static inline int get_mtu(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct rxe_port *port;
+ struct rxe_av *av;
+
+ if ((qp_type(qp) == IB_QPT_RC) || (qp_type(qp) == IB_QPT_UC))
+ return qp->mtu;
+
+ av = &wqe->av;
+ port = &rxe->port;
+
+ return port->mtu_cap;
+}
+
+static struct sk_buff *init_req_packet(struct rxe_qp *qp,
+ struct rxe_send_wqe *wqe,
+ int opcode, int payload,
+ struct rxe_pkt_info *pkt)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct rxe_port *port = &rxe->port;
+ struct sk_buff *skb;
+ struct rxe_send_wr *ibwr = &wqe->wr;
+ struct rxe_av *av;
+ int pad = (-payload) & 0x3;
+ int paylen;
+ int solicited;
+ u16 pkey;
+ u32 qp_num;
+ int ack_req;
+
+ /* length from start of bth to end of icrc */
+ paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
+
+ /* pkt->hdr, rxe, port_num and mask are initialized in ifc
+ * layer
+ */
+ pkt->opcode = opcode;
+ pkt->qp = qp;
+ pkt->psn = qp->req.psn;
+ pkt->mask = rxe_opcode[opcode].mask;
+ pkt->paylen = paylen;
+ pkt->offset = 0;
+ pkt->wqe = wqe;
+
+ /* init skb */
+ av = rxe_get_av(pkt);
+ skb = rxe->ifc_ops->init_packet(rxe, av, paylen, pkt);
+ if (unlikely(!skb))
+ return NULL;
+
+ /* init bth */
+ solicited = (ibwr->send_flags & IB_SEND_SOLICITED) &&
+ (pkt->mask & RXE_END_MASK) &&
+ ((pkt->mask & (RXE_SEND_MASK)) ||
+ (pkt->mask & (RXE_WRITE_MASK | RXE_IMMDT_MASK)) ==
+ (RXE_WRITE_MASK | RXE_IMMDT_MASK));
+
+ pkey = (qp_type(qp) == IB_QPT_GSI) ?
+ port->pkey_tbl[ibwr->wr.ud.pkey_index] :
+ port->pkey_tbl[qp->attr.pkey_index];
+
+ qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn :
+ qp->attr.dest_qp_num;
+
+ ack_req = ((pkt->mask & RXE_END_MASK) ||
+ (qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
+ if (ack_req)
+ qp->req.noack_pkts = 0;
+
+ bth_init(pkt, pkt->opcode, solicited, 0, pad, pkey, qp_num,
+ ack_req, pkt->psn);
+
+ /* init optional headers */
+ if (pkt->mask & RXE_RETH_MASK) {
+ reth_set_rkey(pkt, ibwr->wr.rdma.rkey);
+ reth_set_va(pkt, wqe->iova);
+ reth_set_len(pkt, wqe->dma.length);
+ }
+
+ if (pkt->mask & RXE_IMMDT_MASK)
+ immdt_set_imm(pkt, ibwr->ex.imm_data);
+
+ if (pkt->mask & RXE_IETH_MASK)
+ ieth_set_rkey(pkt, ibwr->ex.invalidate_rkey);
+
+ if (pkt->mask & RXE_ATMETH_MASK) {
+ atmeth_set_va(pkt, wqe->iova);
+ if (opcode == IB_OPCODE_RC_COMPARE_SWAP ||
+ opcode == IB_OPCODE_RD_COMPARE_SWAP) {
+ atmeth_set_swap_add(pkt, ibwr->wr.atomic.swap);
+ atmeth_set_comp(pkt, ibwr->wr.atomic.compare_add);
+ } else {
+ atmeth_set_swap_add(pkt, ibwr->wr.atomic.compare_add);
+ }
+ atmeth_set_rkey(pkt, ibwr->wr.atomic.rkey);
+ }
+
+ if (pkt->mask & RXE_DETH_MASK) {
+ if (qp->ibqp.qp_num == 1)
+ deth_set_qkey(pkt, GSI_QKEY);
+ else
+ deth_set_qkey(pkt, ibwr->wr.ud.remote_qkey);
+ deth_set_sqp(pkt, qp->ibqp.qp_num);
+ }
+
+ return skb;
+}
+
+static int fill_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
+ struct rxe_pkt_info *pkt, struct sk_buff *skb,
+ int paylen)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ u32 crc = 0;
+ u32 *p;
+ int err;
+
+ err = rxe->ifc_ops->prepare(rxe, pkt, skb, &crc);
+ if (err)
+ return err;
+
+ if (pkt->mask & RXE_WRITE_OR_SEND) {
+ if (wqe->wr.send_flags & IB_SEND_INLINE) {
+ u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
+
+ crc = crc32_le(crc, tmp, paylen);
+
+ memcpy(payload_addr(pkt), tmp, paylen);
+
+ wqe->dma.resid -= paylen;
+ wqe->dma.sge_offset += paylen;
+ } else {
+ err = copy_data(rxe, qp->pd, 0, &wqe->dma,
+ payload_addr(pkt), paylen,
+ from_mem_obj,
+ &crc);
+ if (err)
+ return err;
+ }
+ }
+ p = payload_addr(pkt) + paylen + bth_pad(pkt);
+
+ *p = ~crc;
+
+ return 0;
+}
+
+static void update_wqe_state(struct rxe_qp *qp,
+ struct rxe_send_wqe *wqe,
+ struct rxe_pkt_info *pkt,
+ enum wqe_state *prev_state)
+{
+ enum wqe_state prev_state_ = wqe->state;
+
+ if (pkt->mask & RXE_END_MASK) {
+ if (qp_type(qp) == IB_QPT_RC)
+ wqe->state = wqe_state_pending;
+ } else {
+ wqe->state = wqe_state_processing;
+ }
+
+ *prev_state = prev_state_;
+}
+
+static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
+ struct rxe_pkt_info *pkt, int payload)
+{
+ /* number of packets left to send including current one */
+ int num_pkt = (wqe->dma.resid + payload + qp->mtu - 1) / qp->mtu;
+
+ /* handle zero length packet case */
+ if (num_pkt == 0)
+ num_pkt = 1;
+
+ if (pkt->mask & RXE_START_MASK) {
+ wqe->first_psn = qp->req.psn;
+ wqe->last_psn = (qp->req.psn + num_pkt - 1) & BTH_PSN_MASK;
+ }
+
+ if (pkt->mask & RXE_READ_MASK)
+ qp->req.psn = (wqe->first_psn + num_pkt) & BTH_PSN_MASK;
+ else
+ qp->req.psn = (qp->req.psn + 1) & BTH_PSN_MASK;
+
+ qp->req.opcode = pkt->opcode;
+
+
+ if (pkt->mask & RXE_END_MASK)
+ qp->req.wqe_index = next_index(qp->sq.queue, qp->req.wqe_index);
+
+ qp->need_req_skb = 0;
+
+ if (qp->qp_timeout_jiffies && !timer_pending(&qp->retrans_timer))
+ mod_timer(&qp->retrans_timer,
+ jiffies + qp->qp_timeout_jiffies);
+}
+
+int rxe_requester(void *arg)
+{
+ struct rxe_qp *qp = (struct rxe_qp *)arg;
+ struct rxe_pkt_info pkt;
+ struct sk_buff *skb;
+ struct rxe_send_wqe *wqe;
+ unsigned mask;
+ int payload;
+ int mtu;
+ int opcode;
+ int ret;
+ enum wqe_state prev_state;
+
+next_wqe:
+ if (unlikely(!qp->valid || qp->req.state == QP_STATE_ERROR))
+ goto exit;
+
+ if (unlikely(qp->req.state == QP_STATE_RESET)) {
+ qp->req.wqe_index = consumer_index(qp->sq.queue);
+ qp->req.opcode = -1;
+ qp->req.need_rd_atomic = 0;
+ qp->req.wait_psn = 0;
+ qp->req.need_retry = 0;
+ goto exit;
+ }
+
+ if (unlikely(qp->req.need_retry)) {
+ req_retry(qp);
+ qp->req.need_retry = 0;
+ }
+
+ wqe = req_next_wqe(qp);
+ if (unlikely(!wqe))
+ goto exit;
+
+ if (wqe->mask & WR_REG_MASK) {
+ if (wqe->wr.opcode == IB_WR_LOCAL_INV) {
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct rxe_mem *rmr;
+
+ rmr = rxe_pool_get_index(&rxe->mr_pool,
+ wqe->wr.ex.invalidate_rkey >> 8);
+ if (!rmr) {
+ pr_err("No mr for key %#x\n", wqe->wr.ex.invalidate_rkey);
+ wqe->state = wqe_state_error;
+ wqe->status = IB_WC_MW_BIND_ERR;
+ goto exit;
+ }
+ rmr->state = RXE_MEM_STATE_FREE;
+ wqe->state = wqe_state_done;
+ wqe->status = IB_WC_SUCCESS;
+ } else if (wqe->wr.opcode == IB_WR_REG_MR) {
+ struct rxe_mem *rmr = to_rmr(wqe->wr.wr.reg.mr);
+
+ rmr->state = RXE_MEM_STATE_VALID;
+ rmr->access = wqe->wr.wr.reg.access;
+ rmr->lkey = wqe->wr.wr.reg.key;
+ rmr->rkey = wqe->wr.wr.reg.key;
+ wqe->state = wqe_state_done;
+ wqe->status = IB_WC_SUCCESS;
+ } else {
+ goto exit;
+ }
+ qp->req.wqe_index = next_index(qp->sq.queue,
+ qp->req.wqe_index);
+ goto next_wqe;
+ }
+
+ if (unlikely(qp_type(qp) == IB_QPT_RC &&
+ qp->req.psn > (qp->comp.psn + RXE_MAX_UNACKED_PSNS))) {
+ qp->req.wait_psn = 1;
+ goto exit;
+ }
+
+ /* Limit the number of inflight SKBs per QP */
+ if (unlikely(atomic_read(&qp->skb_out) >
+ RXE_INFLIGHT_SKBS_PER_QP_HIGH)) {
+ qp->need_req_skb = 1;
+ goto exit;
+ }
+
+ opcode = next_opcode(qp, wqe, wqe->wr.opcode);
+ if (unlikely(opcode < 0)) {
+ wqe->status = IB_WC_LOC_QP_OP_ERR;
+ goto exit;
+ }
+
+ mask = rxe_opcode[opcode].mask;
+ if (unlikely(mask & RXE_READ_OR_ATOMIC)) {
+ if (check_init_depth(qp, wqe))
+ goto exit;
+ }
+
+ mtu = get_mtu(qp, wqe);
+ payload = (mask & RXE_WRITE_OR_SEND) ? wqe->dma.resid : 0;
+ if (payload > mtu) {
+ if (qp_type(qp) == IB_QPT_UD) {
+ /* C10-93.1.1: If the total sum of all the buffer lengths specified for a
+ * UD message exceeds the MTU of the port as returned by QueryHCA, the CI
+ * shall not emit any packets for this message. Further, the CI shall not
+ * generate an error due to this condition.
+ */
+
+ /* fake a successful UD send */
+ wqe->first_psn = qp->req.psn;
+ wqe->last_psn = qp->req.psn;
+ qp->req.psn = (qp->req.psn + 1) & BTH_PSN_MASK;
+ qp->req.opcode = IB_OPCODE_UD_SEND_ONLY;
+ qp->req.wqe_index = next_index(qp->sq.queue,
+ qp->req.wqe_index);
+ wqe->state = wqe_state_done;
+ wqe->status = IB_WC_SUCCESS;
+ goto complete;
+ }
+ payload = mtu;
+ }
+
+ skb = init_req_packet(qp, wqe, opcode, payload, &pkt);
+ if (unlikely(!skb)) {
+ pr_err("Failed allocating skb\n");
+ goto err;
+ }
+
+ if (fill_packet(qp, wqe, &pkt, skb, payload)) {
+ pr_debug("Error during fill packet\n");
+ goto err;
+ }
+
+ update_wqe_state(qp, wqe, &pkt, &prev_state);
+ ret = rxe_xmit_packet(to_rdev(qp->ibqp.device), qp, &pkt, skb);
+ if (ret) {
+ qp->need_req_skb = 1;
+ kfree_skb(skb);
+
+ wqe->state = prev_state;
+
+ if (ret == -EAGAIN) {
+ rxe_run_task(&qp->req.task, 1);
+ goto exit;
+ }
+
+ goto err;
+ }
+
+ update_state(qp, wqe, &pkt, payload);
+
+ goto next_wqe;
+
+err:
+ kfree_skb(skb);
+ wqe->status = IB_WC_LOC_PROT_ERR;
+ wqe->state = wqe_state_error;
+
+complete:
+ if (qp_type(qp) != IB_QPT_RC) {
+ while (rxe_completer(qp) == 0)
+ ;
+ }
+
+ return 0;
+
+exit:
+ return -EAGAIN;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
new file mode 100644
index 000000000000..ebb03b46e2ad
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -0,0 +1,1380 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/skbuff.h>
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+enum resp_states {
+ RESPST_NONE,
+ RESPST_GET_REQ,
+ RESPST_CHK_PSN,
+ RESPST_CHK_OP_SEQ,
+ RESPST_CHK_OP_VALID,
+ RESPST_CHK_RESOURCE,
+ RESPST_CHK_LENGTH,
+ RESPST_CHK_RKEY,
+ RESPST_EXECUTE,
+ RESPST_READ_REPLY,
+ RESPST_COMPLETE,
+ RESPST_ACKNOWLEDGE,
+ RESPST_CLEANUP,
+ RESPST_DUPLICATE_REQUEST,
+ RESPST_ERR_MALFORMED_WQE,
+ RESPST_ERR_UNSUPPORTED_OPCODE,
+ RESPST_ERR_MISALIGNED_ATOMIC,
+ RESPST_ERR_PSN_OUT_OF_SEQ,
+ RESPST_ERR_MISSING_OPCODE_FIRST,
+ RESPST_ERR_MISSING_OPCODE_LAST_C,
+ RESPST_ERR_MISSING_OPCODE_LAST_D1E,
+ RESPST_ERR_TOO_MANY_RDMA_ATM_REQ,
+ RESPST_ERR_RNR,
+ RESPST_ERR_RKEY_VIOLATION,
+ RESPST_ERR_LENGTH,
+ RESPST_ERR_CQ_OVERFLOW,
+ RESPST_ERROR,
+ RESPST_RESET,
+ RESPST_DONE,
+ RESPST_EXIT,
+};
+
+static char *resp_state_name[] = {
+ [RESPST_NONE] = "NONE",
+ [RESPST_GET_REQ] = "GET_REQ",
+ [RESPST_CHK_PSN] = "CHK_PSN",
+ [RESPST_CHK_OP_SEQ] = "CHK_OP_SEQ",
+ [RESPST_CHK_OP_VALID] = "CHK_OP_VALID",
+ [RESPST_CHK_RESOURCE] = "CHK_RESOURCE",
+ [RESPST_CHK_LENGTH] = "CHK_LENGTH",
+ [RESPST_CHK_RKEY] = "CHK_RKEY",
+ [RESPST_EXECUTE] = "EXECUTE",
+ [RESPST_READ_REPLY] = "READ_REPLY",
+ [RESPST_COMPLETE] = "COMPLETE",
+ [RESPST_ACKNOWLEDGE] = "ACKNOWLEDGE",
+ [RESPST_CLEANUP] = "CLEANUP",
+ [RESPST_DUPLICATE_REQUEST] = "DUPLICATE_REQUEST",
+ [RESPST_ERR_MALFORMED_WQE] = "ERR_MALFORMED_WQE",
+ [RESPST_ERR_UNSUPPORTED_OPCODE] = "ERR_UNSUPPORTED_OPCODE",
+ [RESPST_ERR_MISALIGNED_ATOMIC] = "ERR_MISALIGNED_ATOMIC",
+ [RESPST_ERR_PSN_OUT_OF_SEQ] = "ERR_PSN_OUT_OF_SEQ",
+ [RESPST_ERR_MISSING_OPCODE_FIRST] = "ERR_MISSING_OPCODE_FIRST",
+ [RESPST_ERR_MISSING_OPCODE_LAST_C] = "ERR_MISSING_OPCODE_LAST_C",
+ [RESPST_ERR_MISSING_OPCODE_LAST_D1E] = "ERR_MISSING_OPCODE_LAST_D1E",
+ [RESPST_ERR_TOO_MANY_RDMA_ATM_REQ] = "ERR_TOO_MANY_RDMA_ATM_REQ",
+ [RESPST_ERR_RNR] = "ERR_RNR",
+ [RESPST_ERR_RKEY_VIOLATION] = "ERR_RKEY_VIOLATION",
+ [RESPST_ERR_LENGTH] = "ERR_LENGTH",
+ [RESPST_ERR_CQ_OVERFLOW] = "ERR_CQ_OVERFLOW",
+ [RESPST_ERROR] = "ERROR",
+ [RESPST_RESET] = "RESET",
+ [RESPST_DONE] = "DONE",
+ [RESPST_EXIT] = "EXIT",
+};
+
+/* rxe_recv calls here to add a request packet to the input queue */
+void rxe_resp_queue_pkt(struct rxe_dev *rxe, struct rxe_qp *qp,
+ struct sk_buff *skb)
+{
+ int must_sched;
+ struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
+
+ skb_queue_tail(&qp->req_pkts, skb);
+
+ must_sched = (pkt->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST) ||
+ (skb_queue_len(&qp->req_pkts) > 1);
+
+ rxe_run_task(&qp->resp.task, must_sched);
+}
+
+static inline enum resp_states get_req(struct rxe_qp *qp,
+ struct rxe_pkt_info **pkt_p)
+{
+ struct sk_buff *skb;
+
+ if (qp->resp.state == QP_STATE_ERROR) {
+ skb = skb_dequeue(&qp->req_pkts);
+ if (skb) {
+ /* drain request packet queue */
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ return RESPST_GET_REQ;
+ }
+
+ /* go drain recv wr queue */
+ return RESPST_CHK_RESOURCE;
+ }
+
+ skb = skb_peek(&qp->req_pkts);
+ if (!skb)
+ return RESPST_EXIT;
+
+ *pkt_p = SKB_TO_PKT(skb);
+
+ return (qp->resp.res) ? RESPST_READ_REPLY : RESPST_CHK_PSN;
+}
+
+static enum resp_states check_psn(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ int diff = psn_compare(pkt->psn, qp->resp.psn);
+
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ if (diff > 0) {
+ if (qp->resp.sent_psn_nak)
+ return RESPST_CLEANUP;
+
+ qp->resp.sent_psn_nak = 1;
+ return RESPST_ERR_PSN_OUT_OF_SEQ;
+
+ } else if (diff < 0) {
+ return RESPST_DUPLICATE_REQUEST;
+ }
+
+ if (qp->resp.sent_psn_nak)
+ qp->resp.sent_psn_nak = 0;
+
+ break;
+
+ case IB_QPT_UC:
+ if (qp->resp.drop_msg || diff != 0) {
+ if (pkt->mask & RXE_START_MASK) {
+ qp->resp.drop_msg = 0;
+ return RESPST_CHK_OP_SEQ;
+ }
+
+ qp->resp.drop_msg = 1;
+ return RESPST_CLEANUP;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return RESPST_CHK_OP_SEQ;
+}
+
+static enum resp_states check_op_seq(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ switch (qp->resp.opcode) {
+ case IB_OPCODE_RC_SEND_FIRST:
+ case IB_OPCODE_RC_SEND_MIDDLE:
+ switch (pkt->opcode) {
+ case IB_OPCODE_RC_SEND_MIDDLE:
+ case IB_OPCODE_RC_SEND_LAST:
+ case IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE:
+ case IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE:
+ return RESPST_CHK_OP_VALID;
+ default:
+ return RESPST_ERR_MISSING_OPCODE_LAST_C;
+ }
+
+ case IB_OPCODE_RC_RDMA_WRITE_FIRST:
+ case IB_OPCODE_RC_RDMA_WRITE_MIDDLE:
+ switch (pkt->opcode) {
+ case IB_OPCODE_RC_RDMA_WRITE_MIDDLE:
+ case IB_OPCODE_RC_RDMA_WRITE_LAST:
+ case IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE:
+ return RESPST_CHK_OP_VALID;
+ default:
+ return RESPST_ERR_MISSING_OPCODE_LAST_C;
+ }
+
+ default:
+ switch (pkt->opcode) {
+ case IB_OPCODE_RC_SEND_MIDDLE:
+ case IB_OPCODE_RC_SEND_LAST:
+ case IB_OPCODE_RC_SEND_LAST_WITH_IMMEDIATE:
+ case IB_OPCODE_RC_SEND_LAST_WITH_INVALIDATE:
+ case IB_OPCODE_RC_RDMA_WRITE_MIDDLE:
+ case IB_OPCODE_RC_RDMA_WRITE_LAST:
+ case IB_OPCODE_RC_RDMA_WRITE_LAST_WITH_IMMEDIATE:
+ return RESPST_ERR_MISSING_OPCODE_FIRST;
+ default:
+ return RESPST_CHK_OP_VALID;
+ }
+ }
+ break;
+
+ case IB_QPT_UC:
+ switch (qp->resp.opcode) {
+ case IB_OPCODE_UC_SEND_FIRST:
+ case IB_OPCODE_UC_SEND_MIDDLE:
+ switch (pkt->opcode) {
+ case IB_OPCODE_UC_SEND_MIDDLE:
+ case IB_OPCODE_UC_SEND_LAST:
+ case IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE:
+ return RESPST_CHK_OP_VALID;
+ default:
+ return RESPST_ERR_MISSING_OPCODE_LAST_D1E;
+ }
+
+ case IB_OPCODE_UC_RDMA_WRITE_FIRST:
+ case IB_OPCODE_UC_RDMA_WRITE_MIDDLE:
+ switch (pkt->opcode) {
+ case IB_OPCODE_UC_RDMA_WRITE_MIDDLE:
+ case IB_OPCODE_UC_RDMA_WRITE_LAST:
+ case IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE:
+ return RESPST_CHK_OP_VALID;
+ default:
+ return RESPST_ERR_MISSING_OPCODE_LAST_D1E;
+ }
+
+ default:
+ switch (pkt->opcode) {
+ case IB_OPCODE_UC_SEND_MIDDLE:
+ case IB_OPCODE_UC_SEND_LAST:
+ case IB_OPCODE_UC_SEND_LAST_WITH_IMMEDIATE:
+ case IB_OPCODE_UC_RDMA_WRITE_MIDDLE:
+ case IB_OPCODE_UC_RDMA_WRITE_LAST:
+ case IB_OPCODE_UC_RDMA_WRITE_LAST_WITH_IMMEDIATE:
+ qp->resp.drop_msg = 1;
+ return RESPST_CLEANUP;
+ default:
+ return RESPST_CHK_OP_VALID;
+ }
+ }
+ break;
+
+ default:
+ return RESPST_CHK_OP_VALID;
+ }
+}
+
+static enum resp_states check_op_valid(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ if (((pkt->mask & RXE_READ_MASK) &&
+ !(qp->attr.qp_access_flags & IB_ACCESS_REMOTE_READ)) ||
+ ((pkt->mask & RXE_WRITE_MASK) &&
+ !(qp->attr.qp_access_flags & IB_ACCESS_REMOTE_WRITE)) ||
+ ((pkt->mask & RXE_ATOMIC_MASK) &&
+ !(qp->attr.qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) {
+ return RESPST_ERR_UNSUPPORTED_OPCODE;
+ }
+
+ break;
+
+ case IB_QPT_UC:
+ if ((pkt->mask & RXE_WRITE_MASK) &&
+ !(qp->attr.qp_access_flags & IB_ACCESS_REMOTE_WRITE)) {
+ qp->resp.drop_msg = 1;
+ return RESPST_CLEANUP;
+ }
+
+ break;
+
+ case IB_QPT_UD:
+ case IB_QPT_SMI:
+ case IB_QPT_GSI:
+ break;
+
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return RESPST_CHK_RESOURCE;
+}
+
+static enum resp_states get_srq_wqe(struct rxe_qp *qp)
+{
+ struct rxe_srq *srq = qp->srq;
+ struct rxe_queue *q = srq->rq.queue;
+ struct rxe_recv_wqe *wqe;
+ struct ib_event ev;
+
+ if (srq->error)
+ return RESPST_ERR_RNR;
+
+ spin_lock_bh(&srq->rq.consumer_lock);
+
+ wqe = queue_head(q);
+ if (!wqe) {
+ spin_unlock_bh(&srq->rq.consumer_lock);
+ return RESPST_ERR_RNR;
+ }
+
+ /* note kernel and user space recv wqes have same size */
+ memcpy(&qp->resp.srq_wqe, wqe, sizeof(qp->resp.srq_wqe));
+
+ qp->resp.wqe = &qp->resp.srq_wqe.wqe;
+ advance_consumer(q);
+
+ if (srq->limit && srq->ibsrq.event_handler &&
+ (queue_count(q) < srq->limit)) {
+ srq->limit = 0;
+ goto event;
+ }
+
+ spin_unlock_bh(&srq->rq.consumer_lock);
+ return RESPST_CHK_LENGTH;
+
+event:
+ spin_unlock_bh(&srq->rq.consumer_lock);
+ ev.device = qp->ibqp.device;
+ ev.element.srq = qp->ibqp.srq;
+ ev.event = IB_EVENT_SRQ_LIMIT_REACHED;
+ srq->ibsrq.event_handler(&ev, srq->ibsrq.srq_context);
+ return RESPST_CHK_LENGTH;
+}
+
+static enum resp_states check_resource(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ struct rxe_srq *srq = qp->srq;
+
+ if (qp->resp.state == QP_STATE_ERROR) {
+ if (qp->resp.wqe) {
+ qp->resp.status = IB_WC_WR_FLUSH_ERR;
+ return RESPST_COMPLETE;
+ } else if (!srq) {
+ qp->resp.wqe = queue_head(qp->rq.queue);
+ if (qp->resp.wqe) {
+ qp->resp.status = IB_WC_WR_FLUSH_ERR;
+ return RESPST_COMPLETE;
+ } else {
+ return RESPST_EXIT;
+ }
+ } else {
+ return RESPST_EXIT;
+ }
+ }
+
+ if (pkt->mask & RXE_READ_OR_ATOMIC) {
+ /* it is the requesters job to not send
+ * too many read/atomic ops, we just
+ * recycle the responder resource queue
+ */
+ if (likely(qp->attr.max_rd_atomic > 0))
+ return RESPST_CHK_LENGTH;
+ else
+ return RESPST_ERR_TOO_MANY_RDMA_ATM_REQ;
+ }
+
+ if (pkt->mask & RXE_RWR_MASK) {
+ if (srq)
+ return get_srq_wqe(qp);
+
+ qp->resp.wqe = queue_head(qp->rq.queue);
+ return (qp->resp.wqe) ? RESPST_CHK_LENGTH : RESPST_ERR_RNR;
+ }
+
+ return RESPST_CHK_LENGTH;
+}
+
+static enum resp_states check_length(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ switch (qp_type(qp)) {
+ case IB_QPT_RC:
+ return RESPST_CHK_RKEY;
+
+ case IB_QPT_UC:
+ return RESPST_CHK_RKEY;
+
+ default:
+ return RESPST_CHK_RKEY;
+ }
+}
+
+static enum resp_states check_rkey(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ struct rxe_mem *mem;
+ u64 va;
+ u32 rkey;
+ u32 resid;
+ u32 pktlen;
+ int mtu = qp->mtu;
+ enum resp_states state;
+ int access;
+
+ if (pkt->mask & (RXE_READ_MASK | RXE_WRITE_MASK)) {
+ if (pkt->mask & RXE_RETH_MASK) {
+ qp->resp.va = reth_va(pkt);
+ qp->resp.rkey = reth_rkey(pkt);
+ qp->resp.resid = reth_len(pkt);
+ }
+ access = (pkt->mask & RXE_READ_MASK) ? IB_ACCESS_REMOTE_READ
+ : IB_ACCESS_REMOTE_WRITE;
+ } else if (pkt->mask & RXE_ATOMIC_MASK) {
+ qp->resp.va = atmeth_va(pkt);
+ qp->resp.rkey = atmeth_rkey(pkt);
+ qp->resp.resid = sizeof(u64);
+ access = IB_ACCESS_REMOTE_ATOMIC;
+ } else {
+ return RESPST_EXECUTE;
+ }
+
+ va = qp->resp.va;
+ rkey = qp->resp.rkey;
+ resid = qp->resp.resid;
+ pktlen = payload_size(pkt);
+
+ mem = lookup_mem(qp->pd, access, rkey, lookup_remote);
+ if (!mem) {
+ state = RESPST_ERR_RKEY_VIOLATION;
+ goto err1;
+ }
+
+ if (unlikely(mem->state == RXE_MEM_STATE_FREE)) {
+ state = RESPST_ERR_RKEY_VIOLATION;
+ goto err1;
+ }
+
+ if (mem_check_range(mem, va, resid)) {
+ state = RESPST_ERR_RKEY_VIOLATION;
+ goto err2;
+ }
+
+ if (pkt->mask & RXE_WRITE_MASK) {
+ if (resid > mtu) {
+ if (pktlen != mtu || bth_pad(pkt)) {
+ state = RESPST_ERR_LENGTH;
+ goto err2;
+ }
+
+ resid = mtu;
+ } else {
+ if (pktlen != resid) {
+ state = RESPST_ERR_LENGTH;
+ goto err2;
+ }
+ if ((bth_pad(pkt) != (0x3 & (-resid)))) {
+ /* This case may not be exactly that
+ * but nothing else fits.
+ */
+ state = RESPST_ERR_LENGTH;
+ goto err2;
+ }
+ }
+ }
+
+ WARN_ON(qp->resp.mr);
+
+ qp->resp.mr = mem;
+ return RESPST_EXECUTE;
+
+err2:
+ rxe_drop_ref(mem);
+err1:
+ return state;
+}
+
+static enum resp_states send_data_in(struct rxe_qp *qp, void *data_addr,
+ int data_len)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+
+ err = copy_data(rxe, qp->pd, IB_ACCESS_LOCAL_WRITE, &qp->resp.wqe->dma,
+ data_addr, data_len, to_mem_obj, NULL);
+ if (unlikely(err))
+ return (err == -ENOSPC) ? RESPST_ERR_LENGTH
+ : RESPST_ERR_MALFORMED_WQE;
+
+ return RESPST_NONE;
+}
+
+static enum resp_states write_data_in(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ enum resp_states rc = RESPST_NONE;
+ int err;
+ int data_len = payload_size(pkt);
+
+ err = rxe_mem_copy(qp->resp.mr, qp->resp.va, payload_addr(pkt),
+ data_len, to_mem_obj, NULL);
+ if (err) {
+ rc = RESPST_ERR_RKEY_VIOLATION;
+ goto out;
+ }
+
+ qp->resp.va += data_len;
+ qp->resp.resid -= data_len;
+
+out:
+ return rc;
+}
+
+/* Guarantee atomicity of atomic operations at the machine level. */
+static DEFINE_SPINLOCK(atomic_ops_lock);
+
+static enum resp_states process_atomic(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ u64 iova = atmeth_va(pkt);
+ u64 *vaddr;
+ enum resp_states ret;
+ struct rxe_mem *mr = qp->resp.mr;
+
+ if (mr->state != RXE_MEM_STATE_VALID) {
+ ret = RESPST_ERR_RKEY_VIOLATION;
+ goto out;
+ }
+
+ vaddr = iova_to_vaddr(mr, iova, sizeof(u64));
+
+ /* check vaddr is 8 bytes aligned. */
+ if (!vaddr || (uintptr_t)vaddr & 7) {
+ ret = RESPST_ERR_MISALIGNED_ATOMIC;
+ goto out;
+ }
+
+ spin_lock_bh(&atomic_ops_lock);
+
+ qp->resp.atomic_orig = *vaddr;
+
+ if (pkt->opcode == IB_OPCODE_RC_COMPARE_SWAP ||
+ pkt->opcode == IB_OPCODE_RD_COMPARE_SWAP) {
+ if (*vaddr == atmeth_comp(pkt))
+ *vaddr = atmeth_swap_add(pkt);
+ } else {
+ *vaddr += atmeth_swap_add(pkt);
+ }
+
+ spin_unlock_bh(&atomic_ops_lock);
+
+ ret = RESPST_NONE;
+out:
+ return ret;
+}
+
+static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt,
+ struct rxe_pkt_info *ack,
+ int opcode,
+ int payload,
+ u32 psn,
+ u8 syndrome,
+ u32 *crcp)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct sk_buff *skb;
+ u32 crc = 0;
+ u32 *p;
+ int paylen;
+ int pad;
+ int err;
+
+ /*
+ * allocate packet
+ */
+ pad = (-payload) & 0x3;
+ paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
+
+ skb = rxe->ifc_ops->init_packet(rxe, &qp->pri_av, paylen, ack);
+ if (!skb)
+ return NULL;
+
+ ack->qp = qp;
+ ack->opcode = opcode;
+ ack->mask = rxe_opcode[opcode].mask;
+ ack->offset = pkt->offset;
+ ack->paylen = paylen;
+
+ /* fill in bth using the request packet headers */
+ memcpy(ack->hdr, pkt->hdr, pkt->offset + RXE_BTH_BYTES);
+
+ bth_set_opcode(ack, opcode);
+ bth_set_qpn(ack, qp->attr.dest_qp_num);
+ bth_set_pad(ack, pad);
+ bth_set_se(ack, 0);
+ bth_set_psn(ack, psn);
+ bth_set_ack(ack, 0);
+ ack->psn = psn;
+
+ if (ack->mask & RXE_AETH_MASK) {
+ aeth_set_syn(ack, syndrome);
+ aeth_set_msn(ack, qp->resp.msn);
+ }
+
+ if (ack->mask & RXE_ATMACK_MASK)
+ atmack_set_orig(ack, qp->resp.atomic_orig);
+
+ err = rxe->ifc_ops->prepare(rxe, ack, skb, &crc);
+ if (err) {
+ kfree_skb(skb);
+ return NULL;
+ }
+
+ if (crcp) {
+ /* CRC computation will be continued by the caller */
+ *crcp = crc;
+ } else {
+ p = payload_addr(ack) + payload + bth_pad(ack);
+ *p = ~crc;
+ }
+
+ return skb;
+}
+
+/* RDMA read response. If res is not NULL, then we have a current RDMA request
+ * being processed or replayed.
+ */
+static enum resp_states read_reply(struct rxe_qp *qp,
+ struct rxe_pkt_info *req_pkt)
+{
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct rxe_pkt_info ack_pkt;
+ struct sk_buff *skb;
+ int mtu = qp->mtu;
+ enum resp_states state;
+ int payload;
+ int opcode;
+ int err;
+ struct resp_res *res = qp->resp.res;
+ u32 icrc;
+ u32 *p;
+
+ if (!res) {
+ /* This is the first time we process that request. Get a
+ * resource
+ */
+ res = &qp->resp.resources[qp->resp.res_head];
+
+ free_rd_atomic_resource(qp, res);
+ rxe_advance_resp_resource(qp);
+
+ res->type = RXE_READ_MASK;
+
+ res->read.va = qp->resp.va;
+ res->read.va_org = qp->resp.va;
+
+ res->first_psn = req_pkt->psn;
+ res->last_psn = req_pkt->psn +
+ (reth_len(req_pkt) + mtu - 1) /
+ mtu - 1;
+ res->cur_psn = req_pkt->psn;
+
+ res->read.resid = qp->resp.resid;
+ res->read.length = qp->resp.resid;
+ res->read.rkey = qp->resp.rkey;
+
+ /* note res inherits the reference to mr from qp */
+ res->read.mr = qp->resp.mr;
+ qp->resp.mr = NULL;
+
+ qp->resp.res = res;
+ res->state = rdatm_res_state_new;
+ }
+
+ if (res->state == rdatm_res_state_new) {
+ if (res->read.resid <= mtu)
+ opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_ONLY;
+ else
+ opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST;
+ } else {
+ if (res->read.resid > mtu)
+ opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE;
+ else
+ opcode = IB_OPCODE_RC_RDMA_READ_RESPONSE_LAST;
+ }
+
+ res->state = rdatm_res_state_next;
+
+ payload = min_t(int, res->read.resid, mtu);
+
+ skb = prepare_ack_packet(qp, req_pkt, &ack_pkt, opcode, payload,
+ res->cur_psn, AETH_ACK_UNLIMITED, &icrc);
+ if (!skb)
+ return RESPST_ERR_RNR;
+
+ err = rxe_mem_copy(res->read.mr, res->read.va, payload_addr(&ack_pkt),
+ payload, from_mem_obj, &icrc);
+ if (err)
+ pr_err("Failed copying memory\n");
+
+ p = payload_addr(&ack_pkt) + payload + bth_pad(&ack_pkt);
+ *p = ~icrc;
+
+ err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb);
+ if (err) {
+ pr_err("Failed sending RDMA reply.\n");
+ kfree_skb(skb);
+ return RESPST_ERR_RNR;
+ }
+
+ res->read.va += payload;
+ res->read.resid -= payload;
+ res->cur_psn = (res->cur_psn + 1) & BTH_PSN_MASK;
+
+ if (res->read.resid > 0) {
+ state = RESPST_DONE;
+ } else {
+ qp->resp.res = NULL;
+ qp->resp.opcode = -1;
+ qp->resp.psn = res->cur_psn;
+ state = RESPST_CLEANUP;
+ }
+
+ return state;
+}
+
+/* Executes a new request. A retried request never reach that function (send
+ * and writes are discarded, and reads and atomics are retried elsewhere.
+ */
+static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
+{
+ enum resp_states err;
+
+ if (pkt->mask & RXE_SEND_MASK) {
+ if (qp_type(qp) == IB_QPT_UD ||
+ qp_type(qp) == IB_QPT_SMI ||
+ qp_type(qp) == IB_QPT_GSI) {
+ union rdma_network_hdr hdr;
+ struct sk_buff *skb = PKT_TO_SKB(pkt);
+
+ memset(&hdr, 0, sizeof(hdr));
+ if (skb->protocol == htons(ETH_P_IP))
+ memcpy(&hdr.roce4grh, ip_hdr(skb), sizeof(hdr.roce4grh));
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ memcpy(&hdr.ibgrh, ipv6_hdr(skb), sizeof(hdr.ibgrh));
+
+ err = send_data_in(qp, &hdr, sizeof(hdr));
+ if (err)
+ return err;
+ }
+ err = send_data_in(qp, payload_addr(pkt), payload_size(pkt));
+ if (err)
+ return err;
+ } else if (pkt->mask & RXE_WRITE_MASK) {
+ err = write_data_in(qp, pkt);
+ if (err)
+ return err;
+ } else if (pkt->mask & RXE_READ_MASK) {
+ /* For RDMA Read we can increment the msn now. See C9-148. */
+ qp->resp.msn++;
+ return RESPST_READ_REPLY;
+ } else if (pkt->mask & RXE_ATOMIC_MASK) {
+ err = process_atomic(qp, pkt);
+ if (err)
+ return err;
+ } else
+ /* Unreachable */
+ WARN_ON(1);
+
+ /* We successfully processed this new request. */
+ qp->resp.msn++;
+
+ /* next expected psn, read handles this separately */
+ qp->resp.psn = (pkt->psn + 1) & BTH_PSN_MASK;
+
+ qp->resp.opcode = pkt->opcode;
+ qp->resp.status = IB_WC_SUCCESS;
+
+ if (pkt->mask & RXE_COMP_MASK)
+ return RESPST_COMPLETE;
+ else if (qp_type(qp) == IB_QPT_RC)
+ return RESPST_ACKNOWLEDGE;
+ else
+ return RESPST_CLEANUP;
+}
+
+static enum resp_states do_complete(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ struct rxe_cqe cqe;
+ struct ib_wc *wc = &cqe.ibwc;
+ struct ib_uverbs_wc *uwc = &cqe.uibwc;
+ struct rxe_recv_wqe *wqe = qp->resp.wqe;
+
+ if (unlikely(!wqe))
+ return RESPST_CLEANUP;
+
+ memset(&cqe, 0, sizeof(cqe));
+
+ wc->wr_id = wqe->wr_id;
+ wc->status = qp->resp.status;
+ wc->qp = &qp->ibqp;
+
+ /* fields after status are not required for errors */
+ if (wc->status == IB_WC_SUCCESS) {
+ wc->opcode = (pkt->mask & RXE_IMMDT_MASK &&
+ pkt->mask & RXE_WRITE_MASK) ?
+ IB_WC_RECV_RDMA_WITH_IMM : IB_WC_RECV;
+ wc->vendor_err = 0;
+ wc->byte_len = wqe->dma.length - wqe->dma.resid;
+
+ /* fields after byte_len are different between kernel and user
+ * space
+ */
+ if (qp->rcq->is_user) {
+ uwc->wc_flags = IB_WC_GRH;
+
+ if (pkt->mask & RXE_IMMDT_MASK) {
+ uwc->wc_flags |= IB_WC_WITH_IMM;
+ uwc->ex.imm_data =
+ (__u32 __force)immdt_imm(pkt);
+ }
+
+ if (pkt->mask & RXE_IETH_MASK) {
+ uwc->wc_flags |= IB_WC_WITH_INVALIDATE;
+ uwc->ex.invalidate_rkey = ieth_rkey(pkt);
+ }
+
+ uwc->qp_num = qp->ibqp.qp_num;
+
+ if (pkt->mask & RXE_DETH_MASK)
+ uwc->src_qp = deth_sqp(pkt);
+
+ uwc->port_num = qp->attr.port_num;
+ } else {
+ struct sk_buff *skb = PKT_TO_SKB(pkt);
+
+ wc->wc_flags = IB_WC_GRH | IB_WC_WITH_NETWORK_HDR_TYPE;
+ if (skb->protocol == htons(ETH_P_IP))
+ wc->network_hdr_type = RDMA_NETWORK_IPV4;
+ else
+ wc->network_hdr_type = RDMA_NETWORK_IPV6;
+
+ if (pkt->mask & RXE_IMMDT_MASK) {
+ wc->wc_flags |= IB_WC_WITH_IMM;
+ wc->ex.imm_data = immdt_imm(pkt);
+ }
+
+ if (pkt->mask & RXE_IETH_MASK) {
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct rxe_mem *rmr;
+
+ wc->wc_flags |= IB_WC_WITH_INVALIDATE;
+ wc->ex.invalidate_rkey = ieth_rkey(pkt);
+
+ rmr = rxe_pool_get_index(&rxe->mr_pool,
+ wc->ex.invalidate_rkey >> 8);
+ if (unlikely(!rmr)) {
+ pr_err("Bad rkey %#x invalidation\n", wc->ex.invalidate_rkey);
+ return RESPST_ERROR;
+ }
+ rmr->state = RXE_MEM_STATE_FREE;
+ }
+
+ wc->qp = &qp->ibqp;
+
+ if (pkt->mask & RXE_DETH_MASK)
+ wc->src_qp = deth_sqp(pkt);
+
+ wc->port_num = qp->attr.port_num;
+ }
+ }
+
+ /* have copy for srq and reference for !srq */
+ if (!qp->srq)
+ advance_consumer(qp->rq.queue);
+
+ qp->resp.wqe = NULL;
+
+ if (rxe_cq_post(qp->rcq, &cqe, pkt ? bth_se(pkt) : 1))
+ return RESPST_ERR_CQ_OVERFLOW;
+
+ if (qp->resp.state == QP_STATE_ERROR)
+ return RESPST_CHK_RESOURCE;
+
+ if (!pkt)
+ return RESPST_DONE;
+ else if (qp_type(qp) == IB_QPT_RC)
+ return RESPST_ACKNOWLEDGE;
+ else
+ return RESPST_CLEANUP;
+}
+
+static int send_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
+ u8 syndrome, u32 psn)
+{
+ int err = 0;
+ struct rxe_pkt_info ack_pkt;
+ struct sk_buff *skb;
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+
+ skb = prepare_ack_packet(qp, pkt, &ack_pkt, IB_OPCODE_RC_ACKNOWLEDGE,
+ 0, psn, syndrome, NULL);
+ if (!skb) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ err = rxe_xmit_packet(rxe, qp, &ack_pkt, skb);
+ if (err) {
+ pr_err_ratelimited("Failed sending ack\n");
+ kfree_skb(skb);
+ }
+
+err1:
+ return err;
+}
+
+static int send_atomic_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
+ u8 syndrome)
+{
+ int rc = 0;
+ struct rxe_pkt_info ack_pkt;
+ struct sk_buff *skb;
+ struct sk_buff *skb_copy;
+ struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+ struct resp_res *res;
+
+ skb = prepare_ack_packet(qp, pkt, &ack_pkt,
+ IB_OPCODE_RC_ATOMIC_ACKNOWLEDGE, 0, pkt->psn,
+ syndrome, NULL);
+ if (!skb) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ skb_copy = skb_clone(skb, GFP_ATOMIC);
+ if (skb_copy)
+ rxe_add_ref(qp); /* for the new SKB */
+ else {
+ pr_warn("Could not clone atomic response\n");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ res = &qp->resp.resources[qp->resp.res_head];
+ free_rd_atomic_resource(qp, res);
+ rxe_advance_resp_resource(qp);
+
+ res->type = RXE_ATOMIC_MASK;
+ res->atomic.skb = skb;
+ res->first_psn = qp->resp.psn;
+ res->last_psn = qp->resp.psn;
+ res->cur_psn = qp->resp.psn;
+
+ rc = rxe_xmit_packet(rxe, qp, &ack_pkt, skb_copy);
+ if (rc) {
+ pr_err_ratelimited("Failed sending ack\n");
+ rxe_drop_ref(qp);
+ kfree_skb(skb_copy);
+ }
+
+out:
+ return rc;
+}
+
+static enum resp_states acknowledge(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ if (qp_type(qp) != IB_QPT_RC)
+ return RESPST_CLEANUP;
+
+ if (qp->resp.aeth_syndrome != AETH_ACK_UNLIMITED)
+ send_ack(qp, pkt, qp->resp.aeth_syndrome, pkt->psn);
+ else if (pkt->mask & RXE_ATOMIC_MASK)
+ send_atomic_ack(qp, pkt, AETH_ACK_UNLIMITED);
+ else if (bth_ack(pkt))
+ send_ack(qp, pkt, AETH_ACK_UNLIMITED, pkt->psn);
+
+ return RESPST_CLEANUP;
+}
+
+static enum resp_states cleanup(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ struct sk_buff *skb;
+
+ if (pkt) {
+ skb = skb_dequeue(&qp->req_pkts);
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ }
+
+ if (qp->resp.mr) {
+ rxe_drop_ref(qp->resp.mr);
+ qp->resp.mr = NULL;
+ }
+
+ return RESPST_DONE;
+}
+
+static struct resp_res *find_resource(struct rxe_qp *qp, u32 psn)
+{
+ int i;
+
+ for (i = 0; i < qp->attr.max_rd_atomic; i++) {
+ struct resp_res *res = &qp->resp.resources[i];
+
+ if (res->type == 0)
+ continue;
+
+ if (psn_compare(psn, res->first_psn) >= 0 &&
+ psn_compare(psn, res->last_psn) <= 0) {
+ return res;
+ }
+ }
+
+ return NULL;
+}
+
+static enum resp_states duplicate_request(struct rxe_qp *qp,
+ struct rxe_pkt_info *pkt)
+{
+ enum resp_states rc;
+
+ if (pkt->mask & RXE_SEND_MASK ||
+ pkt->mask & RXE_WRITE_MASK) {
+ /* SEND. Ack again and cleanup. C9-105. */
+ if (bth_ack(pkt))
+ send_ack(qp, pkt, AETH_ACK_UNLIMITED, qp->resp.psn - 1);
+ rc = RESPST_CLEANUP;
+ goto out;
+ } else if (pkt->mask & RXE_READ_MASK) {
+ struct resp_res *res;
+
+ res = find_resource(qp, pkt->psn);
+ if (!res) {
+ /* Resource not found. Class D error. Drop the
+ * request.
+ */
+ rc = RESPST_CLEANUP;
+ goto out;
+ } else {
+ /* Ensure this new request is the same as the previous
+ * one or a subset of it.
+ */
+ u64 iova = reth_va(pkt);
+ u32 resid = reth_len(pkt);
+
+ if (iova < res->read.va_org ||
+ resid > res->read.length ||
+ (iova + resid) > (res->read.va_org +
+ res->read.length)) {
+ rc = RESPST_CLEANUP;
+ goto out;
+ }
+
+ if (reth_rkey(pkt) != res->read.rkey) {
+ rc = RESPST_CLEANUP;
+ goto out;
+ }
+
+ res->cur_psn = pkt->psn;
+ res->state = (pkt->psn == res->first_psn) ?
+ rdatm_res_state_new :
+ rdatm_res_state_replay;
+
+ /* Reset the resource, except length. */
+ res->read.va_org = iova;
+ res->read.va = iova;
+ res->read.resid = resid;
+
+ /* Replay the RDMA read reply. */
+ qp->resp.res = res;
+ rc = RESPST_READ_REPLY;
+ goto out;
+ }
+ } else {
+ struct resp_res *res;
+
+ /* Find the operation in our list of responder resources. */
+ res = find_resource(qp, pkt->psn);
+ if (res) {
+ struct sk_buff *skb_copy;
+
+ skb_copy = skb_clone(res->atomic.skb, GFP_ATOMIC);
+ if (skb_copy) {
+ rxe_add_ref(qp); /* for the new SKB */
+ } else {
+ pr_warn("Couldn't clone atomic resp\n");
+ rc = RESPST_CLEANUP;
+ goto out;
+ }
+ bth_set_psn(SKB_TO_PKT(skb_copy),
+ qp->resp.psn - 1);
+ /* Resend the result. */
+ rc = rxe_xmit_packet(to_rdev(qp->ibqp.device), qp,
+ pkt, skb_copy);
+ if (rc) {
+ pr_err("Failed resending result. This flow is not handled - skb ignored\n");
+ kfree_skb(skb_copy);
+ rc = RESPST_CLEANUP;
+ goto out;
+ }
+ }
+
+ /* Resource not found. Class D error. Drop the request. */
+ rc = RESPST_CLEANUP;
+ goto out;
+ }
+out:
+ return rc;
+}
+
+/* Process a class A or C. Both are treated the same in this implementation. */
+static void do_class_ac_error(struct rxe_qp *qp, u8 syndrome,
+ enum ib_wc_status status)
+{
+ qp->resp.aeth_syndrome = syndrome;
+ qp->resp.status = status;
+
+ /* indicate that we should go through the ERROR state */
+ qp->resp.goto_error = 1;
+}
+
+static enum resp_states do_class_d1e_error(struct rxe_qp *qp)
+{
+ /* UC */
+ if (qp->srq) {
+ /* Class E */
+ qp->resp.drop_msg = 1;
+ if (qp->resp.wqe) {
+ qp->resp.status = IB_WC_REM_INV_REQ_ERR;
+ return RESPST_COMPLETE;
+ } else {
+ return RESPST_CLEANUP;
+ }
+ } else {
+ /* Class D1. This packet may be the start of a
+ * new message and could be valid. The previous
+ * message is invalid and ignored. reset the
+ * recv wr to its original state
+ */
+ if (qp->resp.wqe) {
+ qp->resp.wqe->dma.resid = qp->resp.wqe->dma.length;
+ qp->resp.wqe->dma.cur_sge = 0;
+ qp->resp.wqe->dma.sge_offset = 0;
+ qp->resp.opcode = -1;
+ }
+
+ if (qp->resp.mr) {
+ rxe_drop_ref(qp->resp.mr);
+ qp->resp.mr = NULL;
+ }
+
+ return RESPST_CLEANUP;
+ }
+}
+
+int rxe_responder(void *arg)
+{
+ struct rxe_qp *qp = (struct rxe_qp *)arg;
+ enum resp_states state;
+ struct rxe_pkt_info *pkt = NULL;
+ int ret = 0;
+
+ qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;
+
+ if (!qp->valid) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ switch (qp->resp.state) {
+ case QP_STATE_RESET:
+ state = RESPST_RESET;
+ break;
+
+ default:
+ state = RESPST_GET_REQ;
+ break;
+ }
+
+ while (1) {
+ pr_debug("state = %s\n", resp_state_name[state]);
+ switch (state) {
+ case RESPST_GET_REQ:
+ state = get_req(qp, &pkt);
+ break;
+ case RESPST_CHK_PSN:
+ state = check_psn(qp, pkt);
+ break;
+ case RESPST_CHK_OP_SEQ:
+ state = check_op_seq(qp, pkt);
+ break;
+ case RESPST_CHK_OP_VALID:
+ state = check_op_valid(qp, pkt);
+ break;
+ case RESPST_CHK_RESOURCE:
+ state = check_resource(qp, pkt);
+ break;
+ case RESPST_CHK_LENGTH:
+ state = check_length(qp, pkt);
+ break;
+ case RESPST_CHK_RKEY:
+ state = check_rkey(qp, pkt);
+ break;
+ case RESPST_EXECUTE:
+ state = execute(qp, pkt);
+ break;
+ case RESPST_COMPLETE:
+ state = do_complete(qp, pkt);
+ break;
+ case RESPST_READ_REPLY:
+ state = read_reply(qp, pkt);
+ break;
+ case RESPST_ACKNOWLEDGE:
+ state = acknowledge(qp, pkt);
+ break;
+ case RESPST_CLEANUP:
+ state = cleanup(qp, pkt);
+ break;
+ case RESPST_DUPLICATE_REQUEST:
+ state = duplicate_request(qp, pkt);
+ break;
+ case RESPST_ERR_PSN_OUT_OF_SEQ:
+ /* RC only - Class B. Drop packet. */
+ send_ack(qp, pkt, AETH_NAK_PSN_SEQ_ERROR, qp->resp.psn);
+ state = RESPST_CLEANUP;
+ break;
+
+ case RESPST_ERR_TOO_MANY_RDMA_ATM_REQ:
+ case RESPST_ERR_MISSING_OPCODE_FIRST:
+ case RESPST_ERR_MISSING_OPCODE_LAST_C:
+ case RESPST_ERR_UNSUPPORTED_OPCODE:
+ case RESPST_ERR_MISALIGNED_ATOMIC:
+ /* RC Only - Class C. */
+ do_class_ac_error(qp, AETH_NAK_INVALID_REQ,
+ IB_WC_REM_INV_REQ_ERR);
+ state = RESPST_COMPLETE;
+ break;
+
+ case RESPST_ERR_MISSING_OPCODE_LAST_D1E:
+ state = do_class_d1e_error(qp);
+ break;
+ case RESPST_ERR_RNR:
+ if (qp_type(qp) == IB_QPT_RC) {
+ /* RC - class B */
+ send_ack(qp, pkt, AETH_RNR_NAK |
+ (~AETH_TYPE_MASK &
+ qp->attr.min_rnr_timer),
+ pkt->psn);
+ } else {
+ /* UD/UC - class D */
+ qp->resp.drop_msg = 1;
+ }
+ state = RESPST_CLEANUP;
+ break;
+
+ case RESPST_ERR_RKEY_VIOLATION:
+ if (qp_type(qp) == IB_QPT_RC) {
+ /* Class C */
+ do_class_ac_error(qp, AETH_NAK_REM_ACC_ERR,
+ IB_WC_REM_ACCESS_ERR);
+ state = RESPST_COMPLETE;
+ } else {
+ qp->resp.drop_msg = 1;
+ if (qp->srq) {
+ /* UC/SRQ Class D */
+ qp->resp.status = IB_WC_REM_ACCESS_ERR;
+ state = RESPST_COMPLETE;
+ } else {
+ /* UC/non-SRQ Class E. */
+ state = RESPST_CLEANUP;
+ }
+ }
+ break;
+
+ case RESPST_ERR_LENGTH:
+ if (qp_type(qp) == IB_QPT_RC) {
+ /* Class C */
+ do_class_ac_error(qp, AETH_NAK_INVALID_REQ,
+ IB_WC_REM_INV_REQ_ERR);
+ state = RESPST_COMPLETE;
+ } else if (qp->srq) {
+ /* UC/UD - class E */
+ qp->resp.status = IB_WC_REM_INV_REQ_ERR;
+ state = RESPST_COMPLETE;
+ } else {
+ /* UC/UD - class D */
+ qp->resp.drop_msg = 1;
+ state = RESPST_CLEANUP;
+ }
+ break;
+
+ case RESPST_ERR_MALFORMED_WQE:
+ /* All, Class A. */
+ do_class_ac_error(qp, AETH_NAK_REM_OP_ERR,
+ IB_WC_LOC_QP_OP_ERR);
+ state = RESPST_COMPLETE;
+ break;
+
+ case RESPST_ERR_CQ_OVERFLOW:
+ /* All - Class G */
+ state = RESPST_ERROR;
+ break;
+
+ case RESPST_DONE:
+ if (qp->resp.goto_error) {
+ state = RESPST_ERROR;
+ break;
+ }
+
+ goto done;
+
+ case RESPST_EXIT:
+ if (qp->resp.goto_error) {
+ state = RESPST_ERROR;
+ break;
+ }
+
+ goto exit;
+
+ case RESPST_RESET: {
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&qp->req_pkts))) {
+ rxe_drop_ref(qp);
+ kfree_skb(skb);
+ }
+
+ while (!qp->srq && qp->rq.queue &&
+ queue_head(qp->rq.queue))
+ advance_consumer(qp->rq.queue);
+
+ qp->resp.wqe = NULL;
+ goto exit;
+ }
+
+ case RESPST_ERROR:
+ qp->resp.goto_error = 0;
+ pr_warn("qp#%d moved to error state\n", qp_num(qp));
+ rxe_qp_error(qp);
+ goto exit;
+
+ default:
+ WARN_ON(1);
+ }
+ }
+
+exit:
+ ret = -EAGAIN;
+done:
+ return ret;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_srq.c b/drivers/infiniband/sw/rxe/rxe_srq.c
new file mode 100644
index 000000000000..2a6e3cd2d4e8
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_srq.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+int rxe_srq_chk_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_attr *attr, enum ib_srq_attr_mask mask)
+{
+ if (srq && srq->error) {
+ pr_warn("srq in error state\n");
+ goto err1;
+ }
+
+ if (mask & IB_SRQ_MAX_WR) {
+ if (attr->max_wr > rxe->attr.max_srq_wr) {
+ pr_warn("max_wr(%d) > max_srq_wr(%d)\n",
+ attr->max_wr, rxe->attr.max_srq_wr);
+ goto err1;
+ }
+
+ if (attr->max_wr <= 0) {
+ pr_warn("max_wr(%d) <= 0\n", attr->max_wr);
+ goto err1;
+ }
+
+ if (srq && srq->limit && (attr->max_wr < srq->limit)) {
+ pr_warn("max_wr (%d) < srq->limit (%d)\n",
+ attr->max_wr, srq->limit);
+ goto err1;
+ }
+
+ if (attr->max_wr < RXE_MIN_SRQ_WR)
+ attr->max_wr = RXE_MIN_SRQ_WR;
+ }
+
+ if (mask & IB_SRQ_LIMIT) {
+ if (attr->srq_limit > rxe->attr.max_srq_wr) {
+ pr_warn("srq_limit(%d) > max_srq_wr(%d)\n",
+ attr->srq_limit, rxe->attr.max_srq_wr);
+ goto err1;
+ }
+
+ if (srq && (attr->srq_limit > srq->rq.queue->buf->index_mask)) {
+ pr_warn("srq_limit (%d) > cur limit(%d)\n",
+ attr->srq_limit,
+ srq->rq.queue->buf->index_mask);
+ goto err1;
+ }
+ }
+
+ if (mask == IB_SRQ_INIT_MASK) {
+ if (attr->max_sge > rxe->attr.max_srq_sge) {
+ pr_warn("max_sge(%d) > max_srq_sge(%d)\n",
+ attr->max_sge, rxe->attr.max_srq_sge);
+ goto err1;
+ }
+
+ if (attr->max_sge < RXE_MIN_SRQ_SGE)
+ attr->max_sge = RXE_MIN_SRQ_SGE;
+ }
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_init_attr *init,
+ struct ib_ucontext *context, struct ib_udata *udata)
+{
+ int err;
+ int srq_wqe_size;
+ struct rxe_queue *q;
+
+ srq->ibsrq.event_handler = init->event_handler;
+ srq->ibsrq.srq_context = init->srq_context;
+ srq->limit = init->attr.srq_limit;
+ srq->srq_num = srq->pelem.index;
+ srq->rq.max_wr = init->attr.max_wr;
+ srq->rq.max_sge = init->attr.max_sge;
+
+ srq_wqe_size = rcv_wqe_size(srq->rq.max_sge);
+
+ spin_lock_init(&srq->rq.producer_lock);
+ spin_lock_init(&srq->rq.consumer_lock);
+
+ q = rxe_queue_init(rxe, &srq->rq.max_wr,
+ srq_wqe_size);
+ if (!q) {
+ pr_warn("unable to allocate queue for srq\n");
+ return -ENOMEM;
+ }
+
+ srq->rq.queue = q;
+
+ err = do_mmap_info(rxe, udata, false, context, q->buf,
+ q->buf_size, &q->ip);
+ if (err)
+ return err;
+
+ if (udata && udata->outlen >= sizeof(struct mminfo) + sizeof(u32)) {
+ if (copy_to_user(udata->outbuf + sizeof(struct mminfo),
+ &srq->srq_num, sizeof(u32)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int rxe_srq_from_attr(struct rxe_dev *rxe, struct rxe_srq *srq,
+ struct ib_srq_attr *attr, enum ib_srq_attr_mask mask,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_queue *q = srq->rq.queue;
+ struct mminfo mi = { .offset = 1, .size = 0};
+
+ if (mask & IB_SRQ_MAX_WR) {
+ /* Check that we can write the mminfo struct to user space */
+ if (udata && udata->inlen >= sizeof(__u64)) {
+ __u64 mi_addr;
+
+ /* Get address of user space mminfo struct */
+ err = ib_copy_from_udata(&mi_addr, udata,
+ sizeof(mi_addr));
+ if (err)
+ goto err1;
+
+ udata->outbuf = (void __user *)(unsigned long)mi_addr;
+ udata->outlen = sizeof(mi);
+
+ if (!access_ok(VERIFY_WRITE,
+ (void __user *)udata->outbuf,
+ udata->outlen)) {
+ err = -EFAULT;
+ goto err1;
+ }
+ }
+
+ err = rxe_queue_resize(q, (unsigned int *)&attr->max_wr,
+ rcv_wqe_size(srq->rq.max_sge),
+ srq->rq.queue->ip ?
+ srq->rq.queue->ip->context :
+ NULL,
+ udata, &srq->rq.producer_lock,
+ &srq->rq.consumer_lock);
+ if (err)
+ goto err2;
+ }
+
+ if (mask & IB_SRQ_LIMIT)
+ srq->limit = attr->srq_limit;
+
+ return 0;
+
+err2:
+ rxe_queue_cleanup(q);
+ srq->rq.queue = NULL;
+err1:
+ return err;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_sysfs.c b/drivers/infiniband/sw/rxe/rxe_sysfs.c
new file mode 100644
index 000000000000..cf8e77800046
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_sysfs.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_net.h"
+
+/* Copy argument and remove trailing CR. Return the new length. */
+static int sanitize_arg(const char *val, char *intf, int intf_len)
+{
+ int len;
+
+ if (!val)
+ return 0;
+
+ /* Remove newline. */
+ for (len = 0; len < intf_len - 1 && val[len] && val[len] != '\n'; len++)
+ intf[len] = val[len];
+ intf[len] = 0;
+
+ if (len == 0 || (val[len] != 0 && val[len] != '\n'))
+ return 0;
+
+ return len;
+}
+
+static void rxe_set_port_state(struct net_device *ndev)
+{
+ struct rxe_dev *rxe = net_to_rxe(ndev);
+ bool is_up = netif_running(ndev) && netif_carrier_ok(ndev);
+
+ if (!rxe)
+ goto out;
+
+ if (is_up)
+ rxe_port_up(rxe);
+ else
+ rxe_port_down(rxe); /* down for unknown state */
+out:
+ return;
+}
+
+static int rxe_param_set_add(const char *val, const struct kernel_param *kp)
+{
+ int len;
+ int err = 0;
+ char intf[32];
+ struct net_device *ndev = NULL;
+ struct rxe_dev *rxe;
+
+ len = sanitize_arg(val, intf, sizeof(intf));
+ if (!len) {
+ pr_err("rxe: add: invalid interface name\n");
+ err = -EINVAL;
+ goto err;
+ }
+
+ ndev = dev_get_by_name(&init_net, intf);
+ if (!ndev) {
+ pr_err("interface %s not found\n", intf);
+ err = -EINVAL;
+ goto err;
+ }
+
+ if (net_to_rxe(ndev)) {
+ pr_err("rxe: already configured on %s\n", intf);
+ err = -EINVAL;
+ goto err;
+ }
+
+ rxe = rxe_net_add(ndev);
+ if (!rxe) {
+ pr_err("rxe: failed to add %s\n", intf);
+ err = -EINVAL;
+ goto err;
+ }
+
+ rxe_set_port_state(ndev);
+ pr_info("rxe: added %s to %s\n", rxe->ib_dev.name, intf);
+err:
+ if (ndev)
+ dev_put(ndev);
+ return err;
+}
+
+static int rxe_param_set_remove(const char *val, const struct kernel_param *kp)
+{
+ int len;
+ char intf[32];
+ struct rxe_dev *rxe;
+
+ len = sanitize_arg(val, intf, sizeof(intf));
+ if (!len) {
+ pr_err("rxe: add: invalid interface name\n");
+ return -EINVAL;
+ }
+
+ if (strncmp("all", intf, len) == 0) {
+ pr_info("rxe_sys: remove all");
+ rxe_remove_all();
+ return 0;
+ }
+
+ rxe = get_rxe_by_name(intf);
+
+ if (!rxe) {
+ pr_err("rxe: not configured on %s\n", intf);
+ return -EINVAL;
+ }
+
+ list_del(&rxe->list);
+ rxe_remove(rxe);
+
+ return 0;
+}
+
+static const struct kernel_param_ops rxe_add_ops = {
+ .set = rxe_param_set_add,
+};
+
+static const struct kernel_param_ops rxe_remove_ops = {
+ .set = rxe_param_set_remove,
+};
+
+module_param_cb(add, &rxe_add_ops, NULL, 0200);
+MODULE_PARM_DESC(add, "Create RXE device over network interface");
+module_param_cb(remove, &rxe_remove_ops, NULL, 0200);
+MODULE_PARM_DESC(remove, "Remove RXE device over network interface");
diff --git a/drivers/infiniband/sw/rxe/rxe_task.c b/drivers/infiniband/sw/rxe/rxe_task.c
new file mode 100644
index 000000000000..1e19bf828a6e
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_task.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
+
+#include "rxe_task.h"
+
+int __rxe_do_task(struct rxe_task *task)
+
+{
+ int ret;
+
+ while ((ret = task->func(task->arg)) == 0)
+ ;
+
+ task->ret = ret;
+
+ return ret;
+}
+
+/*
+ * this locking is due to a potential race where
+ * a second caller finds the task already running
+ * but looks just after the last call to func
+ */
+void rxe_do_task(unsigned long data)
+{
+ int cont;
+ int ret;
+ unsigned long flags;
+ struct rxe_task *task = (struct rxe_task *)data;
+
+ spin_lock_irqsave(&task->state_lock, flags);
+ switch (task->state) {
+ case TASK_STATE_START:
+ task->state = TASK_STATE_BUSY;
+ spin_unlock_irqrestore(&task->state_lock, flags);
+ break;
+
+ case TASK_STATE_BUSY:
+ task->state = TASK_STATE_ARMED;
+ /* fall through to */
+ case TASK_STATE_ARMED:
+ spin_unlock_irqrestore(&task->state_lock, flags);
+ return;
+
+ default:
+ spin_unlock_irqrestore(&task->state_lock, flags);
+ pr_warn("bad state = %d in rxe_do_task\n", task->state);
+ return;
+ }
+
+ do {
+ cont = 0;
+ ret = task->func(task->arg);
+
+ spin_lock_irqsave(&task->state_lock, flags);
+ switch (task->state) {
+ case TASK_STATE_BUSY:
+ if (ret)
+ task->state = TASK_STATE_START;
+ else
+ cont = 1;
+ break;
+
+ /* soneone tried to run the task since the last time we called
+ * func, so we will call one more time regardless of the
+ * return value
+ */
+ case TASK_STATE_ARMED:
+ task->state = TASK_STATE_BUSY;
+ cont = 1;
+ break;
+
+ default:
+ pr_warn("bad state = %d in rxe_do_task\n",
+ task->state);
+ }
+ spin_unlock_irqrestore(&task->state_lock, flags);
+ } while (cont);
+
+ task->ret = ret;
+}
+
+int rxe_init_task(void *obj, struct rxe_task *task,
+ void *arg, int (*func)(void *), char *name)
+{
+ task->obj = obj;
+ task->arg = arg;
+ task->func = func;
+ snprintf(task->name, sizeof(task->name), "%s", name);
+
+ tasklet_init(&task->tasklet, rxe_do_task, (unsigned long)task);
+
+ task->state = TASK_STATE_START;
+ spin_lock_init(&task->state_lock);
+
+ return 0;
+}
+
+void rxe_cleanup_task(struct rxe_task *task)
+{
+ tasklet_kill(&task->tasklet);
+}
+
+void rxe_run_task(struct rxe_task *task, int sched)
+{
+ if (sched)
+ tasklet_schedule(&task->tasklet);
+ else
+ rxe_do_task((unsigned long)task);
+}
+
+void rxe_disable_task(struct rxe_task *task)
+{
+ tasklet_disable(&task->tasklet);
+}
+
+void rxe_enable_task(struct rxe_task *task)
+{
+ tasklet_enable(&task->tasklet);
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_task.h b/drivers/infiniband/sw/rxe/rxe_task.h
new file mode 100644
index 000000000000..d14aa6daed05
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_task.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_TASK_H
+#define RXE_TASK_H
+
+enum {
+ TASK_STATE_START = 0,
+ TASK_STATE_BUSY = 1,
+ TASK_STATE_ARMED = 2,
+};
+
+/*
+ * data structure to describe a 'task' which is a short
+ * function that returns 0 as long as it needs to be
+ * called again.
+ */
+struct rxe_task {
+ void *obj;
+ struct tasklet_struct tasklet;
+ int state;
+ spinlock_t state_lock; /* spinlock for task state */
+ void *arg;
+ int (*func)(void *arg);
+ int ret;
+ char name[16];
+};
+
+/*
+ * init rxe_task structure
+ * arg => parameter to pass to fcn
+ * fcn => function to call until it returns != 0
+ */
+int rxe_init_task(void *obj, struct rxe_task *task,
+ void *arg, int (*func)(void *), char *name);
+
+/* cleanup task */
+void rxe_cleanup_task(struct rxe_task *task);
+
+/*
+ * raw call to func in loop without any checking
+ * can call when tasklets are disabled
+ */
+int __rxe_do_task(struct rxe_task *task);
+
+/*
+ * common function called by any of the main tasklets
+ * If there is any chance that there is additional
+ * work to do someone must reschedule the task before
+ * leaving
+ */
+void rxe_do_task(unsigned long data);
+
+/* run a task, else schedule it to run as a tasklet, The decision
+ * to run or schedule tasklet is based on the parameter sched.
+ */
+void rxe_run_task(struct rxe_task *task, int sched);
+
+/* keep a task from scheduling */
+void rxe_disable_task(struct rxe_task *task);
+
+/* allow task to run */
+void rxe_enable_task(struct rxe_task *task);
+
+#endif /* RXE_TASK_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
new file mode 100644
index 000000000000..4552be960c6a
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -0,0 +1,1330 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "rxe.h"
+#include "rxe_loc.h"
+#include "rxe_queue.h"
+
+static int rxe_query_device(struct ib_device *dev,
+ struct ib_device_attr *attr,
+ struct ib_udata *uhw)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+
+ if (uhw->inlen || uhw->outlen)
+ return -EINVAL;
+
+ *attr = rxe->attr;
+ return 0;
+}
+
+static void rxe_eth_speed_to_ib_speed(int speed, u8 *active_speed,
+ u8 *active_width)
+{
+ if (speed <= 1000) {
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_SDR;
+ } else if (speed <= 10000) {
+ *active_width = IB_WIDTH_1X;
+ *active_speed = IB_SPEED_FDR10;
+ } else if (speed <= 20000) {
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_DDR;
+ } else if (speed <= 30000) {
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_QDR;
+ } else if (speed <= 40000) {
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_FDR10;
+ } else {
+ *active_width = IB_WIDTH_4X;
+ *active_speed = IB_SPEED_EDR;
+ }
+}
+
+static int rxe_query_port(struct ib_device *dev,
+ u8 port_num, struct ib_port_attr *attr)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+ struct rxe_port *port;
+ u32 speed;
+
+ if (unlikely(port_num != 1)) {
+ pr_warn("invalid port_number %d\n", port_num);
+ goto err1;
+ }
+
+ port = &rxe->port;
+
+ *attr = port->attr;
+
+ mutex_lock(&rxe->usdev_lock);
+ if (rxe->ndev->ethtool_ops->get_link_ksettings) {
+ struct ethtool_link_ksettings ks;
+
+ rxe->ndev->ethtool_ops->get_link_ksettings(rxe->ndev, &ks);
+ speed = ks.base.speed;
+ } else if (rxe->ndev->ethtool_ops->get_settings) {
+ struct ethtool_cmd cmd;
+
+ rxe->ndev->ethtool_ops->get_settings(rxe->ndev, &cmd);
+ speed = cmd.speed;
+ } else {
+ pr_warn("%s speed is unknown, defaulting to 1000\n", rxe->ndev->name);
+ speed = 1000;
+ }
+ rxe_eth_speed_to_ib_speed(speed, &attr->active_speed, &attr->active_width);
+ mutex_unlock(&rxe->usdev_lock);
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static int rxe_query_gid(struct ib_device *device,
+ u8 port_num, int index, union ib_gid *gid)
+{
+ int ret;
+
+ if (index > RXE_PORT_GID_TBL_LEN)
+ return -EINVAL;
+
+ ret = ib_get_cached_gid(device, port_num, index, gid, NULL);
+ if (ret == -EAGAIN) {
+ memcpy(gid, &zgid, sizeof(*gid));
+ return 0;
+ }
+
+ return ret;
+}
+
+static int rxe_add_gid(struct ib_device *device, u8 port_num, unsigned int
+ index, const union ib_gid *gid,
+ const struct ib_gid_attr *attr, void **context)
+{
+ if (index >= RXE_PORT_GID_TBL_LEN)
+ return -EINVAL;
+ return 0;
+}
+
+static int rxe_del_gid(struct ib_device *device, u8 port_num, unsigned int
+ index, void **context)
+{
+ if (index >= RXE_PORT_GID_TBL_LEN)
+ return -EINVAL;
+ return 0;
+}
+
+static struct net_device *rxe_get_netdev(struct ib_device *device,
+ u8 port_num)
+{
+ struct rxe_dev *rxe = to_rdev(device);
+
+ if (rxe->ndev) {
+ dev_hold(rxe->ndev);
+ return rxe->ndev;
+ }
+
+ return NULL;
+}
+
+static int rxe_query_pkey(struct ib_device *device,
+ u8 port_num, u16 index, u16 *pkey)
+{
+ struct rxe_dev *rxe = to_rdev(device);
+ struct rxe_port *port;
+
+ if (unlikely(port_num != 1)) {
+ dev_warn(device->dma_device, "invalid port_num = %d\n",
+ port_num);
+ goto err1;
+ }
+
+ port = &rxe->port;
+
+ if (unlikely(index >= port->attr.pkey_tbl_len)) {
+ dev_warn(device->dma_device, "invalid index = %d\n",
+ index);
+ goto err1;
+ }
+
+ *pkey = port->pkey_tbl[index];
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static int rxe_modify_device(struct ib_device *dev,
+ int mask, struct ib_device_modify *attr)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+
+ if (mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID)
+ rxe->attr.sys_image_guid = cpu_to_be64(attr->sys_image_guid);
+
+ if (mask & IB_DEVICE_MODIFY_NODE_DESC) {
+ memcpy(rxe->ib_dev.node_desc,
+ attr->node_desc, sizeof(rxe->ib_dev.node_desc));
+ }
+
+ return 0;
+}
+
+static int rxe_modify_port(struct ib_device *dev,
+ u8 port_num, int mask, struct ib_port_modify *attr)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+ struct rxe_port *port;
+
+ if (unlikely(port_num != 1)) {
+ pr_warn("invalid port_num = %d\n", port_num);
+ goto err1;
+ }
+
+ port = &rxe->port;
+
+ port->attr.port_cap_flags |= attr->set_port_cap_mask;
+ port->attr.port_cap_flags &= ~attr->clr_port_cap_mask;
+
+ if (mask & IB_PORT_RESET_QKEY_CNTR)
+ port->attr.qkey_viol_cntr = 0;
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static enum rdma_link_layer rxe_get_link_layer(struct ib_device *dev,
+ u8 port_num)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+
+ return rxe->ifc_ops->link_layer(rxe, port_num);
+}
+
+static struct ib_ucontext *rxe_alloc_ucontext(struct ib_device *dev,
+ struct ib_udata *udata)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+ struct rxe_ucontext *uc;
+
+ uc = rxe_alloc(&rxe->uc_pool);
+ return uc ? &uc->ibuc : ERR_PTR(-ENOMEM);
+}
+
+static int rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
+{
+ struct rxe_ucontext *uc = to_ruc(ibuc);
+
+ rxe_drop_ref(uc);
+ return 0;
+}
+
+static int rxe_port_immutable(struct ib_device *dev, u8 port_num,
+ struct ib_port_immutable *immutable)
+{
+ int err;
+ struct ib_port_attr attr;
+
+ err = rxe_query_port(dev, port_num, &attr);
+ if (err)
+ return err;
+
+ immutable->pkey_tbl_len = attr.pkey_tbl_len;
+ immutable->gid_tbl_len = attr.gid_tbl_len;
+ immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
+ immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+
+ return 0;
+}
+
+static struct ib_pd *rxe_alloc_pd(struct ib_device *dev,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ struct rxe_dev *rxe = to_rdev(dev);
+ struct rxe_pd *pd;
+
+ pd = rxe_alloc(&rxe->pd_pool);
+ return pd ? &pd->ibpd : ERR_PTR(-ENOMEM);
+}
+
+static int rxe_dealloc_pd(struct ib_pd *ibpd)
+{
+ struct rxe_pd *pd = to_rpd(ibpd);
+
+ rxe_drop_ref(pd);
+ return 0;
+}
+
+static int rxe_init_av(struct rxe_dev *rxe, struct ib_ah_attr *attr,
+ struct rxe_av *av)
+{
+ int err;
+ union ib_gid sgid;
+ struct ib_gid_attr sgid_attr;
+
+ err = ib_get_cached_gid(&rxe->ib_dev, attr->port_num,
+ attr->grh.sgid_index, &sgid,
+ &sgid_attr);
+ if (err) {
+ pr_err("Failed to query sgid. err = %d\n", err);
+ return err;
+ }
+
+ err = rxe_av_from_attr(rxe, attr->port_num, av, attr);
+ if (!err)
+ err = rxe_av_fill_ip_info(rxe, av, attr, &sgid_attr, &sgid);
+
+ if (sgid_attr.ndev)
+ dev_put(sgid_attr.ndev);
+ return err;
+}
+
+static struct ib_ah *rxe_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_ah *ah;
+
+ err = rxe_av_chk_attr(rxe, attr);
+ if (err)
+ goto err1;
+
+ ah = rxe_alloc(&rxe->ah_pool);
+ if (!ah) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ rxe_add_ref(pd);
+ ah->pd = pd;
+
+ err = rxe_init_av(rxe, attr, &ah->av);
+ if (err)
+ goto err2;
+
+ return &ah->ibah;
+
+err2:
+ rxe_drop_ref(pd);
+ rxe_drop_ref(ah);
+err1:
+ return ERR_PTR(err);
+}
+
+static int rxe_modify_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibah->device);
+ struct rxe_ah *ah = to_rah(ibah);
+
+ err = rxe_av_chk_attr(rxe, attr);
+ if (err)
+ return err;
+
+ err = rxe_init_av(rxe, attr, &ah->av);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int rxe_query_ah(struct ib_ah *ibah, struct ib_ah_attr *attr)
+{
+ struct rxe_dev *rxe = to_rdev(ibah->device);
+ struct rxe_ah *ah = to_rah(ibah);
+
+ rxe_av_to_attr(rxe, &ah->av, attr);
+ return 0;
+}
+
+static int rxe_destroy_ah(struct ib_ah *ibah)
+{
+ struct rxe_ah *ah = to_rah(ibah);
+
+ rxe_drop_ref(ah->pd);
+ rxe_drop_ref(ah);
+ return 0;
+}
+
+static int post_one_recv(struct rxe_rq *rq, struct ib_recv_wr *ibwr)
+{
+ int err;
+ int i;
+ u32 length;
+ struct rxe_recv_wqe *recv_wqe;
+ int num_sge = ibwr->num_sge;
+
+ if (unlikely(queue_full(rq->queue))) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ if (unlikely(num_sge > rq->max_sge)) {
+ err = -EINVAL;
+ goto err1;
+ }
+
+ length = 0;
+ for (i = 0; i < num_sge; i++)
+ length += ibwr->sg_list[i].length;
+
+ recv_wqe = producer_addr(rq->queue);
+ recv_wqe->wr_id = ibwr->wr_id;
+ recv_wqe->num_sge = num_sge;
+
+ memcpy(recv_wqe->dma.sge, ibwr->sg_list,
+ num_sge * sizeof(struct ib_sge));
+
+ recv_wqe->dma.length = length;
+ recv_wqe->dma.resid = length;
+ recv_wqe->dma.num_sge = num_sge;
+ recv_wqe->dma.cur_sge = 0;
+ recv_wqe->dma.sge_offset = 0;
+
+ /* make sure all changes to the work queue are written before we
+ * update the producer pointer
+ */
+ smp_wmb();
+
+ advance_producer(rq->queue);
+ return 0;
+
+err1:
+ return err;
+}
+
+static struct ib_srq *rxe_create_srq(struct ib_pd *ibpd,
+ struct ib_srq_init_attr *init,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_srq *srq;
+ struct ib_ucontext *context = udata ? ibpd->uobject->context : NULL;
+
+ err = rxe_srq_chk_attr(rxe, NULL, &init->attr, IB_SRQ_INIT_MASK);
+ if (err)
+ goto err1;
+
+ srq = rxe_alloc(&rxe->srq_pool);
+ if (!srq) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ rxe_add_index(srq);
+ rxe_add_ref(pd);
+ srq->pd = pd;
+
+ err = rxe_srq_from_init(rxe, srq, init, context, udata);
+ if (err)
+ goto err2;
+
+ return &srq->ibsrq;
+
+err2:
+ rxe_drop_ref(pd);
+ rxe_drop_index(srq);
+ rxe_drop_ref(srq);
+err1:
+ return ERR_PTR(err);
+}
+
+static int rxe_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr,
+ enum ib_srq_attr_mask mask,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_srq *srq = to_rsrq(ibsrq);
+ struct rxe_dev *rxe = to_rdev(ibsrq->device);
+
+ err = rxe_srq_chk_attr(rxe, srq, attr, mask);
+ if (err)
+ goto err1;
+
+ err = rxe_srq_from_attr(rxe, srq, attr, mask, udata);
+ if (err)
+ goto err1;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+static int rxe_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr)
+{
+ struct rxe_srq *srq = to_rsrq(ibsrq);
+
+ if (srq->error)
+ return -EINVAL;
+
+ attr->max_wr = srq->rq.queue->buf->index_mask;
+ attr->max_sge = srq->rq.max_sge;
+ attr->srq_limit = srq->limit;
+ return 0;
+}
+
+static int rxe_destroy_srq(struct ib_srq *ibsrq)
+{
+ struct rxe_srq *srq = to_rsrq(ibsrq);
+
+ if (srq->rq.queue)
+ rxe_queue_cleanup(srq->rq.queue);
+
+ rxe_drop_ref(srq->pd);
+ rxe_drop_index(srq);
+ rxe_drop_ref(srq);
+
+ return 0;
+}
+
+static int rxe_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ int err = 0;
+ unsigned long flags;
+ struct rxe_srq *srq = to_rsrq(ibsrq);
+
+ spin_lock_irqsave(&srq->rq.producer_lock, flags);
+
+ while (wr) {
+ err = post_one_recv(&srq->rq, wr);
+ if (unlikely(err))
+ break;
+ wr = wr->next;
+ }
+
+ spin_unlock_irqrestore(&srq->rq.producer_lock, flags);
+
+ if (err)
+ *bad_wr = wr;
+
+ return err;
+}
+
+static struct ib_qp *rxe_create_qp(struct ib_pd *ibpd,
+ struct ib_qp_init_attr *init,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_qp *qp;
+
+ err = rxe_qp_chk_init(rxe, init);
+ if (err)
+ goto err1;
+
+ qp = rxe_alloc(&rxe->qp_pool);
+ if (!qp) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ if (udata) {
+ if (udata->inlen) {
+ err = -EINVAL;
+ goto err1;
+ }
+ qp->is_user = 1;
+ }
+
+ rxe_add_index(qp);
+
+ err = rxe_qp_from_init(rxe, qp, pd, init, udata, ibpd);
+ if (err)
+ goto err2;
+
+ return &qp->ibqp;
+
+err2:
+ rxe_drop_index(qp);
+ rxe_drop_ref(qp);
+err1:
+ return ERR_PTR(err);
+}
+
+static int rxe_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int mask, struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibqp->device);
+ struct rxe_qp *qp = to_rqp(ibqp);
+
+ err = rxe_qp_chk_attr(rxe, qp, attr, mask);
+ if (err)
+ goto err1;
+
+ err = rxe_qp_from_attr(qp, attr, mask, udata);
+ if (err)
+ goto err1;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+static int rxe_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int mask, struct ib_qp_init_attr *init)
+{
+ struct rxe_qp *qp = to_rqp(ibqp);
+
+ rxe_qp_to_init(qp, init);
+ rxe_qp_to_attr(qp, attr, mask);
+
+ return 0;
+}
+
+static int rxe_destroy_qp(struct ib_qp *ibqp)
+{
+ struct rxe_qp *qp = to_rqp(ibqp);
+
+ rxe_qp_destroy(qp);
+ rxe_drop_index(qp);
+ rxe_drop_ref(qp);
+ return 0;
+}
+
+static int validate_send_wr(struct rxe_qp *qp, struct ib_send_wr *ibwr,
+ unsigned int mask, unsigned int length)
+{
+ int num_sge = ibwr->num_sge;
+ struct rxe_sq *sq = &qp->sq;
+
+ if (unlikely(num_sge > sq->max_sge))
+ goto err1;
+
+ if (unlikely(mask & WR_ATOMIC_MASK)) {
+ if (length < 8)
+ goto err1;
+
+ if (atomic_wr(ibwr)->remote_addr & 0x7)
+ goto err1;
+ }
+
+ if (unlikely((ibwr->send_flags & IB_SEND_INLINE) &&
+ (length > sq->max_inline)))
+ goto err1;
+
+ return 0;
+
+err1:
+ return -EINVAL;
+}
+
+static void init_send_wr(struct rxe_qp *qp, struct rxe_send_wr *wr,
+ struct ib_send_wr *ibwr)
+{
+ wr->wr_id = ibwr->wr_id;
+ wr->num_sge = ibwr->num_sge;
+ wr->opcode = ibwr->opcode;
+ wr->send_flags = ibwr->send_flags;
+
+ if (qp_type(qp) == IB_QPT_UD ||
+ qp_type(qp) == IB_QPT_SMI ||
+ qp_type(qp) == IB_QPT_GSI) {
+ wr->wr.ud.remote_qpn = ud_wr(ibwr)->remote_qpn;
+ wr->wr.ud.remote_qkey = ud_wr(ibwr)->remote_qkey;
+ if (qp_type(qp) == IB_QPT_GSI)
+ wr->wr.ud.pkey_index = ud_wr(ibwr)->pkey_index;
+ if (wr->opcode == IB_WR_SEND_WITH_IMM)
+ wr->ex.imm_data = ibwr->ex.imm_data;
+ } else {
+ switch (wr->opcode) {
+ case IB_WR_RDMA_WRITE_WITH_IMM:
+ wr->ex.imm_data = ibwr->ex.imm_data;
+ case IB_WR_RDMA_READ:
+ case IB_WR_RDMA_WRITE:
+ wr->wr.rdma.remote_addr = rdma_wr(ibwr)->remote_addr;
+ wr->wr.rdma.rkey = rdma_wr(ibwr)->rkey;
+ break;
+ case IB_WR_SEND_WITH_IMM:
+ wr->ex.imm_data = ibwr->ex.imm_data;
+ break;
+ case IB_WR_SEND_WITH_INV:
+ wr->ex.invalidate_rkey = ibwr->ex.invalidate_rkey;
+ break;
+ case IB_WR_ATOMIC_CMP_AND_SWP:
+ case IB_WR_ATOMIC_FETCH_AND_ADD:
+ wr->wr.atomic.remote_addr =
+ atomic_wr(ibwr)->remote_addr;
+ wr->wr.atomic.compare_add =
+ atomic_wr(ibwr)->compare_add;
+ wr->wr.atomic.swap = atomic_wr(ibwr)->swap;
+ wr->wr.atomic.rkey = atomic_wr(ibwr)->rkey;
+ break;
+ case IB_WR_LOCAL_INV:
+ wr->ex.invalidate_rkey = ibwr->ex.invalidate_rkey;
+ break;
+ case IB_WR_REG_MR:
+ wr->wr.reg.mr = reg_wr(ibwr)->mr;
+ wr->wr.reg.key = reg_wr(ibwr)->key;
+ wr->wr.reg.access = reg_wr(ibwr)->access;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static int init_send_wqe(struct rxe_qp *qp, struct ib_send_wr *ibwr,
+ unsigned int mask, unsigned int length,
+ struct rxe_send_wqe *wqe)
+{
+ int num_sge = ibwr->num_sge;
+ struct ib_sge *sge;
+ int i;
+ u8 *p;
+
+ init_send_wr(qp, &wqe->wr, ibwr);
+
+ if (qp_type(qp) == IB_QPT_UD ||
+ qp_type(qp) == IB_QPT_SMI ||
+ qp_type(qp) == IB_QPT_GSI)
+ memcpy(&wqe->av, &to_rah(ud_wr(ibwr)->ah)->av, sizeof(wqe->av));
+
+ if (unlikely(ibwr->send_flags & IB_SEND_INLINE)) {
+ p = wqe->dma.inline_data;
+
+ sge = ibwr->sg_list;
+ for (i = 0; i < num_sge; i++, sge++) {
+ if (qp->is_user && copy_from_user(p, (__user void *)
+ (uintptr_t)sge->addr, sge->length))
+ return -EFAULT;
+
+ else if (!qp->is_user)
+ memcpy(p, (void *)(uintptr_t)sge->addr,
+ sge->length);
+
+ p += sge->length;
+ }
+ } else if (mask & WR_REG_MASK) {
+ wqe->mask = mask;
+ wqe->state = wqe_state_posted;
+ return 0;
+ } else
+ memcpy(wqe->dma.sge, ibwr->sg_list,
+ num_sge * sizeof(struct ib_sge));
+
+ wqe->iova = (mask & WR_ATOMIC_MASK) ?
+ atomic_wr(ibwr)->remote_addr :
+ rdma_wr(ibwr)->remote_addr;
+ wqe->mask = mask;
+ wqe->dma.length = length;
+ wqe->dma.resid = length;
+ wqe->dma.num_sge = num_sge;
+ wqe->dma.cur_sge = 0;
+ wqe->dma.sge_offset = 0;
+ wqe->state = wqe_state_posted;
+ wqe->ssn = atomic_add_return(1, &qp->ssn);
+
+ return 0;
+}
+
+static int post_one_send(struct rxe_qp *qp, struct ib_send_wr *ibwr,
+ unsigned mask, u32 length)
+{
+ int err;
+ struct rxe_sq *sq = &qp->sq;
+ struct rxe_send_wqe *send_wqe;
+ unsigned long flags;
+
+ err = validate_send_wr(qp, ibwr, mask, length);
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&qp->sq.sq_lock, flags);
+
+ if (unlikely(queue_full(sq->queue))) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ send_wqe = producer_addr(sq->queue);
+
+ err = init_send_wqe(qp, ibwr, mask, length, send_wqe);
+ if (unlikely(err))
+ goto err1;
+
+ /*
+ * make sure all changes to the work queue are
+ * written before we update the producer pointer
+ */
+ smp_wmb();
+
+ advance_producer(sq->queue);
+ spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
+
+ return 0;
+
+err1:
+ spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
+ return err;
+}
+
+static int rxe_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+ struct ib_send_wr **bad_wr)
+{
+ int err = 0;
+ struct rxe_qp *qp = to_rqp(ibqp);
+ unsigned int mask;
+ unsigned int length = 0;
+ int i;
+ int must_sched;
+
+ if (unlikely(!qp->valid)) {
+ *bad_wr = wr;
+ return -EINVAL;
+ }
+
+ if (unlikely(qp->req.state < QP_STATE_READY)) {
+ *bad_wr = wr;
+ return -EINVAL;
+ }
+
+ while (wr) {
+ mask = wr_opcode_mask(wr->opcode, qp);
+ if (unlikely(!mask)) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ break;
+ }
+
+ if (unlikely((wr->send_flags & IB_SEND_INLINE) &&
+ !(mask & WR_INLINE_MASK))) {
+ err = -EINVAL;
+ *bad_wr = wr;
+ break;
+ }
+
+ length = 0;
+ for (i = 0; i < wr->num_sge; i++)
+ length += wr->sg_list[i].length;
+
+ err = post_one_send(qp, wr, mask, length);
+
+ if (err) {
+ *bad_wr = wr;
+ break;
+ }
+ wr = wr->next;
+ }
+
+ /*
+ * Must sched in case of GSI QP because ib_send_mad() hold irq lock,
+ * and the requester call ip_local_out_sk() that takes spin_lock_bh.
+ */
+ must_sched = (qp_type(qp) == IB_QPT_GSI) ||
+ (queue_count(qp->sq.queue) > 1);
+
+ rxe_run_task(&qp->req.task, must_sched);
+
+ return err;
+}
+
+static int rxe_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ struct ib_recv_wr **bad_wr)
+{
+ int err = 0;
+ struct rxe_qp *qp = to_rqp(ibqp);
+ struct rxe_rq *rq = &qp->rq;
+ unsigned long flags;
+
+ if (unlikely((qp_state(qp) < IB_QPS_INIT) || !qp->valid)) {
+ *bad_wr = wr;
+ err = -EINVAL;
+ goto err1;
+ }
+
+ if (unlikely(qp->srq)) {
+ *bad_wr = wr;
+ err = -EINVAL;
+ goto err1;
+ }
+
+ spin_lock_irqsave(&rq->producer_lock, flags);
+
+ while (wr) {
+ err = post_one_recv(rq, wr);
+ if (unlikely(err)) {
+ *bad_wr = wr;
+ break;
+ }
+ wr = wr->next;
+ }
+
+ spin_unlock_irqrestore(&rq->producer_lock, flags);
+
+err1:
+ return err;
+}
+
+static struct ib_cq *rxe_create_cq(struct ib_device *dev,
+ const struct ib_cq_init_attr *attr,
+ struct ib_ucontext *context,
+ struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(dev);
+ struct rxe_cq *cq;
+
+ if (attr->flags)
+ return ERR_PTR(-EINVAL);
+
+ err = rxe_cq_chk_attr(rxe, NULL, attr->cqe, attr->comp_vector, udata);
+ if (err)
+ goto err1;
+
+ cq = rxe_alloc(&rxe->cq_pool);
+ if (!cq) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ err = rxe_cq_from_init(rxe, cq, attr->cqe, attr->comp_vector,
+ context, udata);
+ if (err)
+ goto err2;
+
+ return &cq->ibcq;
+
+err2:
+ rxe_drop_ref(cq);
+err1:
+ return ERR_PTR(err);
+}
+
+static int rxe_destroy_cq(struct ib_cq *ibcq)
+{
+ struct rxe_cq *cq = to_rcq(ibcq);
+
+ rxe_drop_ref(cq);
+ return 0;
+}
+
+static int rxe_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
+{
+ int err;
+ struct rxe_cq *cq = to_rcq(ibcq);
+ struct rxe_dev *rxe = to_rdev(ibcq->device);
+
+ err = rxe_cq_chk_attr(rxe, cq, cqe, 0, udata);
+ if (err)
+ goto err1;
+
+ err = rxe_cq_resize_queue(cq, cqe, udata);
+ if (err)
+ goto err1;
+
+ return 0;
+
+err1:
+ return err;
+}
+
+static int rxe_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
+{
+ int i;
+ struct rxe_cq *cq = to_rcq(ibcq);
+ struct rxe_cqe *cqe;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cq->cq_lock, flags);
+ for (i = 0; i < num_entries; i++) {
+ cqe = queue_head(cq->queue);
+ if (!cqe)
+ break;
+
+ memcpy(wc++, &cqe->ibwc, sizeof(*wc));
+ advance_consumer(cq->queue);
+ }
+ spin_unlock_irqrestore(&cq->cq_lock, flags);
+
+ return i;
+}
+
+static int rxe_peek_cq(struct ib_cq *ibcq, int wc_cnt)
+{
+ struct rxe_cq *cq = to_rcq(ibcq);
+ int count = queue_count(cq->queue);
+
+ return (count > wc_cnt) ? wc_cnt : count;
+}
+
+static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
+{
+ struct rxe_cq *cq = to_rcq(ibcq);
+
+ if (cq->notify != IB_CQ_NEXT_COMP)
+ cq->notify = flags & IB_CQ_SOLICITED_MASK;
+
+ return 0;
+}
+
+static struct ib_mr *rxe_get_dma_mr(struct ib_pd *ibpd, int access)
+{
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_mem *mr;
+ int err;
+
+ mr = rxe_alloc(&rxe->mr_pool);
+ if (!mr) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ rxe_add_index(mr);
+
+ rxe_add_ref(pd);
+
+ err = rxe_mem_init_dma(rxe, pd, access, mr);
+ if (err)
+ goto err2;
+
+ return &mr->ibmr;
+
+err2:
+ rxe_drop_ref(pd);
+ rxe_drop_index(mr);
+ rxe_drop_ref(mr);
+err1:
+ return ERR_PTR(err);
+}
+
+static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd,
+ u64 start,
+ u64 length,
+ u64 iova,
+ int access, struct ib_udata *udata)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_mem *mr;
+
+ mr = rxe_alloc(&rxe->mr_pool);
+ if (!mr) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ rxe_add_index(mr);
+
+ rxe_add_ref(pd);
+
+ err = rxe_mem_init_user(rxe, pd, start, length, iova,
+ access, udata, mr);
+ if (err)
+ goto err3;
+
+ return &mr->ibmr;
+
+err3:
+ rxe_drop_ref(pd);
+ rxe_drop_index(mr);
+ rxe_drop_ref(mr);
+err2:
+ return ERR_PTR(err);
+}
+
+static int rxe_dereg_mr(struct ib_mr *ibmr)
+{
+ struct rxe_mem *mr = to_rmr(ibmr);
+
+ mr->state = RXE_MEM_STATE_ZOMBIE;
+ rxe_drop_ref(mr->pd);
+ rxe_drop_index(mr);
+ rxe_drop_ref(mr);
+ return 0;
+}
+
+static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd,
+ enum ib_mr_type mr_type,
+ u32 max_num_sg)
+{
+ struct rxe_dev *rxe = to_rdev(ibpd->device);
+ struct rxe_pd *pd = to_rpd(ibpd);
+ struct rxe_mem *mr;
+ int err;
+
+ if (mr_type != IB_MR_TYPE_MEM_REG)
+ return ERR_PTR(-EINVAL);
+
+ mr = rxe_alloc(&rxe->mr_pool);
+ if (!mr) {
+ err = -ENOMEM;
+ goto err1;
+ }
+
+ rxe_add_index(mr);
+
+ rxe_add_ref(pd);
+
+ err = rxe_mem_init_fast(rxe, pd, max_num_sg, mr);
+ if (err)
+ goto err2;
+
+ return &mr->ibmr;
+
+err2:
+ rxe_drop_ref(pd);
+ rxe_drop_index(mr);
+ rxe_drop_ref(mr);
+err1:
+ return ERR_PTR(err);
+}
+
+static int rxe_set_page(struct ib_mr *ibmr, u64 addr)
+{
+ struct rxe_mem *mr = to_rmr(ibmr);
+ struct rxe_map *map;
+ struct rxe_phys_buf *buf;
+
+ if (unlikely(mr->nbuf == mr->num_buf))
+ return -ENOMEM;
+
+ map = mr->map[mr->nbuf / RXE_BUF_PER_MAP];
+ buf = &map->buf[mr->nbuf % RXE_BUF_PER_MAP];
+
+ buf->addr = addr;
+ buf->size = ibmr->page_size;
+ mr->nbuf++;
+
+ return 0;
+}
+
+static int rxe_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+ unsigned int *sg_offset)
+{
+ struct rxe_mem *mr = to_rmr(ibmr);
+ int n;
+
+ mr->nbuf = 0;
+
+ n = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, rxe_set_page);
+
+ mr->va = ibmr->iova;
+ mr->iova = ibmr->iova;
+ mr->length = ibmr->length;
+ mr->page_shift = ilog2(ibmr->page_size);
+ mr->page_mask = ibmr->page_size - 1;
+ mr->offset = mr->iova & mr->page_mask;
+
+ return n;
+}
+
+static int rxe_attach_mcast(struct ib_qp *ibqp, union ib_gid *mgid, u16 mlid)
+{
+ int err;
+ struct rxe_dev *rxe = to_rdev(ibqp->device);
+ struct rxe_qp *qp = to_rqp(ibqp);
+ struct rxe_mc_grp *grp;
+
+ /* takes a ref on grp if successful */
+ err = rxe_mcast_get_grp(rxe, mgid, &grp);
+ if (err)
+ return err;
+
+ err = rxe_mcast_add_grp_elem(rxe, qp, grp);
+
+ rxe_drop_ref(grp);
+ return err;
+}
+
+static int rxe_detach_mcast(struct ib_qp *ibqp, union ib_gid *mgid, u16 mlid)
+{
+ struct rxe_dev *rxe = to_rdev(ibqp->device);
+ struct rxe_qp *qp = to_rqp(ibqp);
+
+ return rxe_mcast_drop_grp_elem(rxe, qp, mgid);
+}
+
+static ssize_t rxe_show_parent(struct device *device,
+ struct device_attribute *attr, char *buf)
+{
+ struct rxe_dev *rxe = container_of(device, struct rxe_dev,
+ ib_dev.dev);
+ char *name;
+
+ name = rxe->ifc_ops->parent_name(rxe, 1);
+ return snprintf(buf, 16, "%s\n", name);
+}
+
+static DEVICE_ATTR(parent, S_IRUGO, rxe_show_parent, NULL);
+
+static struct device_attribute *rxe_dev_attributes[] = {
+ &dev_attr_parent,
+};
+
+int rxe_register_device(struct rxe_dev *rxe)
+{
+ int err;
+ int i;
+ struct ib_device *dev = &rxe->ib_dev;
+
+ strlcpy(dev->name, "rxe%d", IB_DEVICE_NAME_MAX);
+ strlcpy(dev->node_desc, "rxe", sizeof(dev->node_desc));
+
+ dev->owner = THIS_MODULE;
+ dev->node_type = RDMA_NODE_IB_CA;
+ dev->phys_port_cnt = 1;
+ dev->num_comp_vectors = RXE_NUM_COMP_VECTORS;
+ dev->dma_device = rxe->ifc_ops->dma_device(rxe);
+ dev->local_dma_lkey = 0;
+ dev->node_guid = rxe->ifc_ops->node_guid(rxe);
+ dev->dma_ops = &rxe_dma_mapping_ops;
+
+ dev->uverbs_abi_ver = RXE_UVERBS_ABI_VERSION;
+ dev->uverbs_cmd_mask = BIT_ULL(IB_USER_VERBS_CMD_GET_CONTEXT)
+ | BIT_ULL(IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)
+ | BIT_ULL(IB_USER_VERBS_CMD_QUERY_DEVICE)
+ | BIT_ULL(IB_USER_VERBS_CMD_QUERY_PORT)
+ | BIT_ULL(IB_USER_VERBS_CMD_ALLOC_PD)
+ | BIT_ULL(IB_USER_VERBS_CMD_DEALLOC_PD)
+ | BIT_ULL(IB_USER_VERBS_CMD_CREATE_SRQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_MODIFY_SRQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_QUERY_SRQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_DESTROY_SRQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_POST_SRQ_RECV)
+ | BIT_ULL(IB_USER_VERBS_CMD_CREATE_QP)
+ | BIT_ULL(IB_USER_VERBS_CMD_MODIFY_QP)
+ | BIT_ULL(IB_USER_VERBS_CMD_QUERY_QP)
+ | BIT_ULL(IB_USER_VERBS_CMD_DESTROY_QP)
+ | BIT_ULL(IB_USER_VERBS_CMD_POST_SEND)
+ | BIT_ULL(IB_USER_VERBS_CMD_POST_RECV)
+ | BIT_ULL(IB_USER_VERBS_CMD_CREATE_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_RESIZE_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_DESTROY_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_POLL_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_PEEK_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ)
+ | BIT_ULL(IB_USER_VERBS_CMD_REG_MR)
+ | BIT_ULL(IB_USER_VERBS_CMD_DEREG_MR)
+ | BIT_ULL(IB_USER_VERBS_CMD_CREATE_AH)
+ | BIT_ULL(IB_USER_VERBS_CMD_MODIFY_AH)
+ | BIT_ULL(IB_USER_VERBS_CMD_QUERY_AH)
+ | BIT_ULL(IB_USER_VERBS_CMD_DESTROY_AH)
+ | BIT_ULL(IB_USER_VERBS_CMD_ATTACH_MCAST)
+ | BIT_ULL(IB_USER_VERBS_CMD_DETACH_MCAST)
+ ;
+
+ dev->query_device = rxe_query_device;
+ dev->modify_device = rxe_modify_device;
+ dev->query_port = rxe_query_port;
+ dev->modify_port = rxe_modify_port;
+ dev->get_link_layer = rxe_get_link_layer;
+ dev->query_gid = rxe_query_gid;
+ dev->get_netdev = rxe_get_netdev;
+ dev->add_gid = rxe_add_gid;
+ dev->del_gid = rxe_del_gid;
+ dev->query_pkey = rxe_query_pkey;
+ dev->alloc_ucontext = rxe_alloc_ucontext;
+ dev->dealloc_ucontext = rxe_dealloc_ucontext;
+ dev->mmap = rxe_mmap;
+ dev->get_port_immutable = rxe_port_immutable;
+ dev->alloc_pd = rxe_alloc_pd;
+ dev->dealloc_pd = rxe_dealloc_pd;
+ dev->create_ah = rxe_create_ah;
+ dev->modify_ah = rxe_modify_ah;
+ dev->query_ah = rxe_query_ah;
+ dev->destroy_ah = rxe_destroy_ah;
+ dev->create_srq = rxe_create_srq;
+ dev->modify_srq = rxe_modify_srq;
+ dev->query_srq = rxe_query_srq;
+ dev->destroy_srq = rxe_destroy_srq;
+ dev->post_srq_recv = rxe_post_srq_recv;
+ dev->create_qp = rxe_create_qp;
+ dev->modify_qp = rxe_modify_qp;
+ dev->query_qp = rxe_query_qp;
+ dev->destroy_qp = rxe_destroy_qp;
+ dev->post_send = rxe_post_send;
+ dev->post_recv = rxe_post_recv;
+ dev->create_cq = rxe_create_cq;
+ dev->destroy_cq = rxe_destroy_cq;
+ dev->resize_cq = rxe_resize_cq;
+ dev->poll_cq = rxe_poll_cq;
+ dev->peek_cq = rxe_peek_cq;
+ dev->req_notify_cq = rxe_req_notify_cq;
+ dev->get_dma_mr = rxe_get_dma_mr;
+ dev->reg_user_mr = rxe_reg_user_mr;
+ dev->dereg_mr = rxe_dereg_mr;
+ dev->alloc_mr = rxe_alloc_mr;
+ dev->map_mr_sg = rxe_map_mr_sg;
+ dev->attach_mcast = rxe_attach_mcast;
+ dev->detach_mcast = rxe_detach_mcast;
+
+ err = ib_register_device(dev, NULL);
+ if (err) {
+ pr_warn("rxe_register_device failed, err = %d\n", err);
+ goto err1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rxe_dev_attributes); ++i) {
+ err = device_create_file(&dev->dev, rxe_dev_attributes[i]);
+ if (err) {
+ pr_warn("device_create_file failed, i = %d, err = %d\n",
+ i, err);
+ goto err2;
+ }
+ }
+
+ return 0;
+
+err2:
+ ib_unregister_device(dev);
+err1:
+ return err;
+}
+
+int rxe_unregister_device(struct rxe_dev *rxe)
+{
+ int i;
+ struct ib_device *dev = &rxe->ib_dev;
+
+ for (i = 0; i < ARRAY_SIZE(rxe_dev_attributes); ++i)
+ device_remove_file(&dev->dev, rxe_dev_attributes[i]);
+
+ ib_unregister_device(dev);
+
+ return 0;
+}
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
new file mode 100644
index 000000000000..cac1d52a08f0
--- /dev/null
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -0,0 +1,480 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RXE_VERBS_H
+#define RXE_VERBS_H
+
+#include <linux/interrupt.h>
+#include <rdma/rdma_user_rxe.h>
+#include "rxe_pool.h"
+#include "rxe_task.h"
+
+static inline int pkey_match(u16 key1, u16 key2)
+{
+ return (((key1 & 0x7fff) != 0) &&
+ ((key1 & 0x7fff) == (key2 & 0x7fff)) &&
+ ((key1 & 0x8000) || (key2 & 0x8000))) ? 1 : 0;
+}
+
+/* Return >0 if psn_a > psn_b
+ * 0 if psn_a == psn_b
+ * <0 if psn_a < psn_b
+ */
+static inline int psn_compare(u32 psn_a, u32 psn_b)
+{
+ s32 diff;
+
+ diff = (psn_a - psn_b) << 8;
+ return diff;
+}
+
+struct rxe_ucontext {
+ struct rxe_pool_entry pelem;
+ struct ib_ucontext ibuc;
+};
+
+struct rxe_pd {
+ struct rxe_pool_entry pelem;
+ struct ib_pd ibpd;
+};
+
+struct rxe_ah {
+ struct rxe_pool_entry pelem;
+ struct ib_ah ibah;
+ struct rxe_pd *pd;
+ struct rxe_av av;
+};
+
+struct rxe_cqe {
+ union {
+ struct ib_wc ibwc;
+ struct ib_uverbs_wc uibwc;
+ };
+};
+
+struct rxe_cq {
+ struct rxe_pool_entry pelem;
+ struct ib_cq ibcq;
+ struct rxe_queue *queue;
+ spinlock_t cq_lock;
+ u8 notify;
+ int is_user;
+ struct tasklet_struct comp_task;
+};
+
+enum wqe_state {
+ wqe_state_posted,
+ wqe_state_processing,
+ wqe_state_pending,
+ wqe_state_done,
+ wqe_state_error,
+};
+
+struct rxe_sq {
+ int max_wr;
+ int max_sge;
+ int max_inline;
+ spinlock_t sq_lock; /* guard queue */
+ struct rxe_queue *queue;
+};
+
+struct rxe_rq {
+ int max_wr;
+ int max_sge;
+ spinlock_t producer_lock; /* guard queue producer */
+ spinlock_t consumer_lock; /* guard queue consumer */
+ struct rxe_queue *queue;
+};
+
+struct rxe_srq {
+ struct rxe_pool_entry pelem;
+ struct ib_srq ibsrq;
+ struct rxe_pd *pd;
+ struct rxe_rq rq;
+ u32 srq_num;
+
+ int limit;
+ int error;
+};
+
+enum rxe_qp_state {
+ QP_STATE_RESET,
+ QP_STATE_INIT,
+ QP_STATE_READY,
+ QP_STATE_DRAIN, /* req only */
+ QP_STATE_DRAINED, /* req only */
+ QP_STATE_ERROR
+};
+
+extern char *rxe_qp_state_name[];
+
+struct rxe_req_info {
+ enum rxe_qp_state state;
+ int wqe_index;
+ u32 psn;
+ int opcode;
+ atomic_t rd_atomic;
+ int wait_fence;
+ int need_rd_atomic;
+ int wait_psn;
+ int need_retry;
+ int noack_pkts;
+ struct rxe_task task;
+};
+
+struct rxe_comp_info {
+ u32 psn;
+ int opcode;
+ int timeout;
+ int timeout_retry;
+ u32 retry_cnt;
+ u32 rnr_retry;
+ struct rxe_task task;
+};
+
+enum rdatm_res_state {
+ rdatm_res_state_next,
+ rdatm_res_state_new,
+ rdatm_res_state_replay,
+};
+
+struct resp_res {
+ int type;
+ u32 first_psn;
+ u32 last_psn;
+ u32 cur_psn;
+ enum rdatm_res_state state;
+
+ union {
+ struct {
+ struct sk_buff *skb;
+ } atomic;
+ struct {
+ struct rxe_mem *mr;
+ u64 va_org;
+ u32 rkey;
+ u32 length;
+ u64 va;
+ u32 resid;
+ } read;
+ };
+};
+
+struct rxe_resp_info {
+ enum rxe_qp_state state;
+ u32 msn;
+ u32 psn;
+ int opcode;
+ int drop_msg;
+ int goto_error;
+ int sent_psn_nak;
+ enum ib_wc_status status;
+ u8 aeth_syndrome;
+
+ /* Receive only */
+ struct rxe_recv_wqe *wqe;
+
+ /* RDMA read / atomic only */
+ u64 va;
+ struct rxe_mem *mr;
+ u32 resid;
+ u32 rkey;
+ u64 atomic_orig;
+
+ /* SRQ only */
+ struct {
+ struct rxe_recv_wqe wqe;
+ struct ib_sge sge[RXE_MAX_SGE];
+ } srq_wqe;
+
+ /* Responder resources. It's a circular list where the oldest
+ * resource is dropped first.
+ */
+ struct resp_res *resources;
+ unsigned int res_head;
+ unsigned int res_tail;
+ struct resp_res *res;
+ struct rxe_task task;
+};
+
+struct rxe_qp {
+ struct rxe_pool_entry pelem;
+ struct ib_qp ibqp;
+ struct ib_qp_attr attr;
+ unsigned int valid;
+ unsigned int mtu;
+ int is_user;
+
+ struct rxe_pd *pd;
+ struct rxe_srq *srq;
+ struct rxe_cq *scq;
+ struct rxe_cq *rcq;
+
+ enum ib_sig_type sq_sig_type;
+
+ struct rxe_sq sq;
+ struct rxe_rq rq;
+
+ struct socket *sk;
+
+ struct rxe_av pri_av;
+ struct rxe_av alt_av;
+
+ /* list of mcast groups qp has joined (for cleanup) */
+ struct list_head grp_list;
+ spinlock_t grp_lock; /* guard grp_list */
+
+ struct sk_buff_head req_pkts;
+ struct sk_buff_head resp_pkts;
+ struct sk_buff_head send_pkts;
+
+ struct rxe_req_info req;
+ struct rxe_comp_info comp;
+ struct rxe_resp_info resp;
+
+ atomic_t ssn;
+ atomic_t skb_out;
+ int need_req_skb;
+
+ /* Timer for retranmitting packet when ACKs have been lost. RC
+ * only. The requester sets it when it is not already
+ * started. The responder resets it whenever an ack is
+ * received.
+ */
+ struct timer_list retrans_timer;
+ u64 qp_timeout_jiffies;
+
+ /* Timer for handling RNR NAKS. */
+ struct timer_list rnr_nak_timer;
+
+ spinlock_t state_lock; /* guard requester and completer */
+};
+
+enum rxe_mem_state {
+ RXE_MEM_STATE_ZOMBIE,
+ RXE_MEM_STATE_INVALID,
+ RXE_MEM_STATE_FREE,
+ RXE_MEM_STATE_VALID,
+};
+
+enum rxe_mem_type {
+ RXE_MEM_TYPE_NONE,
+ RXE_MEM_TYPE_DMA,
+ RXE_MEM_TYPE_MR,
+ RXE_MEM_TYPE_FMR,
+ RXE_MEM_TYPE_MW,
+};
+
+#define RXE_BUF_PER_MAP (PAGE_SIZE / sizeof(struct rxe_phys_buf))
+
+struct rxe_phys_buf {
+ u64 addr;
+ u64 size;
+};
+
+struct rxe_map {
+ struct rxe_phys_buf buf[RXE_BUF_PER_MAP];
+};
+
+struct rxe_mem {
+ struct rxe_pool_entry pelem;
+ union {
+ struct ib_mr ibmr;
+ struct ib_mw ibmw;
+ };
+
+ struct rxe_pd *pd;
+ struct ib_umem *umem;
+
+ u32 lkey;
+ u32 rkey;
+
+ enum rxe_mem_state state;
+ enum rxe_mem_type type;
+ u64 va;
+ u64 iova;
+ size_t length;
+ u32 offset;
+ int access;
+
+ int page_shift;
+ int page_mask;
+ int map_shift;
+ int map_mask;
+
+ u32 num_buf;
+ u32 nbuf;
+
+ u32 max_buf;
+ u32 num_map;
+
+ struct rxe_map **map;
+};
+
+struct rxe_mc_grp {
+ struct rxe_pool_entry pelem;
+ spinlock_t mcg_lock; /* guard group */
+ struct rxe_dev *rxe;
+ struct list_head qp_list;
+ union ib_gid mgid;
+ int num_qp;
+ u32 qkey;
+ u16 pkey;
+};
+
+struct rxe_mc_elem {
+ struct rxe_pool_entry pelem;
+ struct list_head qp_list;
+ struct list_head grp_list;
+ struct rxe_qp *qp;
+ struct rxe_mc_grp *grp;
+};
+
+struct rxe_port {
+ struct ib_port_attr attr;
+ u16 *pkey_tbl;
+ __be64 port_guid;
+ __be64 subnet_prefix;
+ spinlock_t port_lock; /* guard port */
+ unsigned int mtu_cap;
+ /* special QPs */
+ u32 qp_smi_index;
+ u32 qp_gsi_index;
+};
+
+/* callbacks from rdma_rxe to network interface layer */
+struct rxe_ifc_ops {
+ void (*release)(struct rxe_dev *rxe);
+ __be64 (*node_guid)(struct rxe_dev *rxe);
+ __be64 (*port_guid)(struct rxe_dev *rxe);
+ struct device *(*dma_device)(struct rxe_dev *rxe);
+ int (*mcast_add)(struct rxe_dev *rxe, union ib_gid *mgid);
+ int (*mcast_delete)(struct rxe_dev *rxe, union ib_gid *mgid);
+ int (*prepare)(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb, u32 *crc);
+ int (*send)(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
+ struct sk_buff *skb);
+ int (*loopback)(struct sk_buff *skb);
+ struct sk_buff *(*init_packet)(struct rxe_dev *rxe, struct rxe_av *av,
+ int paylen, struct rxe_pkt_info *pkt);
+ char *(*parent_name)(struct rxe_dev *rxe, unsigned int port_num);
+ enum rdma_link_layer (*link_layer)(struct rxe_dev *rxe,
+ unsigned int port_num);
+};
+
+struct rxe_dev {
+ struct ib_device ib_dev;
+ struct ib_device_attr attr;
+ int max_ucontext;
+ int max_inline_data;
+ struct kref ref_cnt;
+ struct mutex usdev_lock;
+
+ struct rxe_ifc_ops *ifc_ops;
+
+ struct net_device *ndev;
+
+ int xmit_errors;
+
+ struct rxe_pool uc_pool;
+ struct rxe_pool pd_pool;
+ struct rxe_pool ah_pool;
+ struct rxe_pool srq_pool;
+ struct rxe_pool qp_pool;
+ struct rxe_pool cq_pool;
+ struct rxe_pool mr_pool;
+ struct rxe_pool mw_pool;
+ struct rxe_pool mc_grp_pool;
+ struct rxe_pool mc_elem_pool;
+
+ spinlock_t pending_lock; /* guard pending_mmaps */
+ struct list_head pending_mmaps;
+
+ spinlock_t mmap_offset_lock; /* guard mmap_offset */
+ int mmap_offset;
+
+ struct rxe_port port;
+ struct list_head list;
+};
+
+static inline struct rxe_dev *to_rdev(struct ib_device *dev)
+{
+ return dev ? container_of(dev, struct rxe_dev, ib_dev) : NULL;
+}
+
+static inline struct rxe_ucontext *to_ruc(struct ib_ucontext *uc)
+{
+ return uc ? container_of(uc, struct rxe_ucontext, ibuc) : NULL;
+}
+
+static inline struct rxe_pd *to_rpd(struct ib_pd *pd)
+{
+ return pd ? container_of(pd, struct rxe_pd, ibpd) : NULL;
+}
+
+static inline struct rxe_ah *to_rah(struct ib_ah *ah)
+{
+ return ah ? container_of(ah, struct rxe_ah, ibah) : NULL;
+}
+
+static inline struct rxe_srq *to_rsrq(struct ib_srq *srq)
+{
+ return srq ? container_of(srq, struct rxe_srq, ibsrq) : NULL;
+}
+
+static inline struct rxe_qp *to_rqp(struct ib_qp *qp)
+{
+ return qp ? container_of(qp, struct rxe_qp, ibqp) : NULL;
+}
+
+static inline struct rxe_cq *to_rcq(struct ib_cq *cq)
+{
+ return cq ? container_of(cq, struct rxe_cq, ibcq) : NULL;
+}
+
+static inline struct rxe_mem *to_rmr(struct ib_mr *mr)
+{
+ return mr ? container_of(mr, struct rxe_mem, ibmr) : NULL;
+}
+
+static inline struct rxe_mem *to_rmw(struct ib_mw *mw)
+{
+ return mw ? container_of(mw, struct rxe_mem, ibmw) : NULL;
+}
+
+int rxe_register_device(struct rxe_dev *rxe);
+int rxe_unregister_device(struct rxe_dev *rxe);
+
+void rxe_mc_cleanup(void *arg);
+
+#endif /* RXE_VERBS_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 1502199c8e56..7b6d40ff1acf 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -62,10 +62,8 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
{
struct ipoib_dev_priv *priv = netdev_priv(netdev);
- snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
- "%d.%d.%d", (int)(priv->ca->attrs.fw_ver >> 32),
- (int)(priv->ca->attrs.fw_ver >> 16) & 0xffff,
- (int)priv->ca->attrs.fw_ver & 0xffff);
+ ib_get_device_fw_str(priv->ca, drvinfo->fw_version,
+ sizeof(drvinfo->fw_version));
strlcpy(drvinfo->bus_info, dev_name(priv->ca->dma_device),
sizeof(drvinfo->bus_info));
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 5f58c41ef787..74bcaa064226 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1967,8 +1967,7 @@ int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
priv->hca_caps = hca->attrs.device_cap_flags;
if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
- priv->dev->hw_features = NETIF_F_SG |
- NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
+ priv->dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
if (priv->hca_caps & IB_DEVICE_UD_TSO)
priv->dev->hw_features |= NETIF_F_TSO;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 1e7cbbaa15bd..c55ecb2c3736 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -135,7 +135,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
.cap = {
.max_send_wr = ipoib_sendq_size,
.max_recv_wr = ipoib_recvq_size,
- .max_send_sge = 1,
+ .max_send_sge = min_t(u32, priv->ca->attrs.max_sge,
+ MAX_SKB_FRAGS + 1),
.max_recv_sge = IPOIB_UD_RX_SG
},
.sq_sig_type = IB_SIGNAL_ALL_WR,
@@ -205,10 +206,6 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
if (priv->hca_caps & IB_DEVICE_MANAGED_FLOW_STEERING)
init_attr.create_flags |= IB_QP_CREATE_NETIF_QP;
- if (dev->features & NETIF_F_SG)
- init_attr.cap.max_send_sge =
- min_t(u32, priv->ca->attrs.max_sge, MAX_SKB_FRAGS + 1);
-
priv->qp = ib_create_qp(priv->pd, &init_attr);
if (IS_ERR(priv->qp)) {
printk(KERN_WARNING "%s: failed to create QP\n", ca->name);
@@ -234,6 +231,9 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
priv->rx_wr.next = NULL;
priv->rx_wr.sg_list = priv->rx_sge;
+ if (init_attr.cap.max_send_sge > 1)
+ dev->features |= NETIF_F_SG;
+
priv->max_send_sge = init_attr.cap.max_send_sge;
return 0;
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index a990c04208c9..ba6be060a476 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -137,8 +137,6 @@ isert_create_qp(struct isert_conn *isert_conn,
attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1;
attr.cap.max_rdma_ctxs = ISCSI_DEF_XMIT_CMDS_MAX;
attr.cap.max_send_sge = device->ib_device->attrs.max_sge;
- isert_conn->max_sge = min(device->ib_device->attrs.max_sge,
- device->ib_device->attrs.max_sge_rd);
attr.cap.max_recv_sge = 1;
attr.sq_sig_type = IB_SIGNAL_REQ_WR;
attr.qp_type = IB_QPT_RC;
diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h
index e512ba941f2f..fc791efe3a10 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.h
+++ b/drivers/infiniband/ulp/isert/ib_isert.h
@@ -138,7 +138,6 @@ struct isert_conn {
u32 responder_resources;
u32 initiator_depth;
bool pi_support;
- u32 max_sge;
struct iser_rx_desc *login_req_buf;
char *login_rsp_buf;
u64 login_req_dma;
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 4a4155640d51..dfa23b075a88 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -1601,6 +1601,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
struct ib_qp_init_attr *qp_init;
struct srpt_port *sport = ch->sport;
struct srpt_device *sdev = sport->sdev;
+ const struct ib_device_attr *attrs = &sdev->device->attrs;
u32 srp_sq_size = sport->port_attrib.srp_sq_size;
int ret;
@@ -1638,7 +1639,7 @@ retry:
*/
qp_init->cap.max_send_wr = srp_sq_size / 2;
qp_init->cap.max_rdma_ctxs = srp_sq_size / 2;
- qp_init->cap.max_send_sge = SRPT_DEF_SG_PER_WQE;
+ qp_init->cap.max_send_sge = min(attrs->max_sge, SRPT_MAX_SG_PER_WQE);
qp_init->port_num = ch->sport->port;
ch->qp = ib_create_qp(sdev->pd, qp_init);
@@ -2261,7 +2262,7 @@ static void srpt_queue_response(struct se_cmd *cmd)
container_of(cmd, struct srpt_send_ioctx, cmd);
struct srpt_rdma_ch *ch = ioctx->ch;
struct srpt_device *sdev = ch->sport->sdev;
- struct ib_send_wr send_wr, *first_wr = NULL, *bad_wr;
+ struct ib_send_wr send_wr, *first_wr = &send_wr, *bad_wr;
struct ib_sge sge;
enum srpt_command_state state;
unsigned long flags;
@@ -2302,11 +2303,8 @@ static void srpt_queue_response(struct se_cmd *cmd)
struct srpt_rw_ctx *ctx = &ioctx->rw_ctxs[i];
first_wr = rdma_rw_ctx_wrs(&ctx->rw, ch->qp,
- ch->sport->port, NULL,
- first_wr ? first_wr : &send_wr);
+ ch->sport->port, NULL, first_wr);
}
- } else {
- first_wr = &send_wr;
}
if (state != SRPT_STATE_MGMT)
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.h b/drivers/infiniband/ulp/srpt/ib_srpt.h
index 389030487da7..581878782854 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.h
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.h
@@ -106,7 +106,11 @@ enum {
SRP_LOGIN_RSP_MULTICHAN_MAINTAINED = 0x2,
SRPT_DEF_SG_TABLESIZE = 128,
- SRPT_DEF_SG_PER_WQE = 16,
+ /*
+ * An experimentally determined value that avoids that QP creation
+ * fails due to "swiotlb buffer is full" on systems using the swiotlb.
+ */
+ SRPT_MAX_SG_PER_WQE = 16,
MIN_SRPT_SQ_SIZE = 16,
DEF_SRPT_SQ_SIZE = 4096,
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index a529a4535457..83af17ad0f1f 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -115,6 +115,10 @@ static bool sticks_to_null;
module_param(sticks_to_null, bool, S_IRUGO);
MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads");
+static bool auto_poweroff = true;
+module_param(auto_poweroff, bool, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(auto_poweroff, "Power off wireless controllers on suspend");
+
static const struct xpad_device {
u16 idVendor;
u16 idProduct;
@@ -1248,6 +1252,36 @@ static void xpad_stop_input(struct usb_xpad *xpad)
usb_kill_urb(xpad->irq_in);
}
+static void xpad360w_poweroff_controller(struct usb_xpad *xpad)
+{
+ unsigned long flags;
+ struct xpad_output_packet *packet =
+ &xpad->out_packets[XPAD_OUT_CMD_IDX];
+
+ spin_lock_irqsave(&xpad->odata_lock, flags);
+
+ packet->data[0] = 0x00;
+ packet->data[1] = 0x00;
+ packet->data[2] = 0x08;
+ packet->data[3] = 0xC0;
+ packet->data[4] = 0x00;
+ packet->data[5] = 0x00;
+ packet->data[6] = 0x00;
+ packet->data[7] = 0x00;
+ packet->data[8] = 0x00;
+ packet->data[9] = 0x00;
+ packet->data[10] = 0x00;
+ packet->data[11] = 0x00;
+ packet->len = 12;
+ packet->pending = true;
+
+ /* Reset the sequence so we send out poweroff now */
+ xpad->last_out_packet = -1;
+ xpad_try_sending_next_out_packet(xpad);
+
+ spin_unlock_irqrestore(&xpad->odata_lock, flags);
+}
+
static int xpad360w_start_input(struct usb_xpad *xpad)
{
int error;
@@ -1590,6 +1624,15 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message)
* or goes away.
*/
xpad360w_stop_input(xpad);
+
+ /*
+ * The wireless adapter is going off now, so the
+ * gamepads are going to become disconnected.
+ * Unless explicitly disabled, power them down
+ * so they don't just sit there flashing.
+ */
+ if (auto_poweroff && xpad->pad_present)
+ xpad360w_poweroff_controller(xpad);
} else {
mutex_lock(&input->mutex);
if (input->users)
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index b01966dc7eb3..4b0878f35471 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -186,7 +186,7 @@ static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
if (ret >= 0)
cros_ec_keyb_process(ckdev, kb_state, ret);
else
- dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
+ dev_err(ckdev->dev, "failed to get keyboard state: %d\n", ret);
return IRQ_HANDLED;
}
@@ -236,7 +236,7 @@ static void cros_ec_keyb_compute_valid_keys(struct cros_ec_keyb *ckdev)
static int cros_ec_keyb_probe(struct platform_device *pdev)
{
struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
- struct device *dev = ec->dev;
+ struct device *dev = &pdev->dev;
struct cros_ec_keyb *ckdev;
struct input_dev *idev;
struct device_node *np;
@@ -246,23 +246,22 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
if (!np)
return -ENODEV;
- ckdev = devm_kzalloc(&pdev->dev, sizeof(*ckdev), GFP_KERNEL);
+ ckdev = devm_kzalloc(dev, sizeof(*ckdev), GFP_KERNEL);
if (!ckdev)
return -ENOMEM;
- err = matrix_keypad_parse_of_params(&pdev->dev, &ckdev->rows,
- &ckdev->cols);
+ err = matrix_keypad_parse_of_params(dev, &ckdev->rows, &ckdev->cols);
if (err)
return err;
- ckdev->valid_keys = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
+ ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
if (!ckdev->valid_keys)
return -ENOMEM;
- ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
+ ckdev->old_kb_state = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
if (!ckdev->old_kb_state)
return -ENOMEM;
- idev = devm_input_allocate_device(&pdev->dev);
+ idev = devm_input_allocate_device(dev);
if (!idev)
return -ENOMEM;
@@ -273,7 +272,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
ckdev->ec = ec;
ckdev->dev = dev;
- dev_set_drvdata(&pdev->dev, ckdev);
+ dev_set_drvdata(dev, ckdev);
idev->name = CROS_EC_DEV_NAME;
idev->phys = ec->phys_name;
@@ -282,7 +281,7 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
idev->id.bustype = BUS_VIRTUAL;
idev->id.version = 1;
idev->id.product = 0;
- idev->dev.parent = &pdev->dev;
+ idev->dev.parent = dev;
idev->open = cros_ec_keyb_open;
idev->close = cros_ec_keyb_close;
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index c7fc8d4fb080..1588aecafff7 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -28,6 +28,11 @@
#define DRV_NAME "rotary-encoder"
+enum rotary_encoder_encoding {
+ ROTENC_GRAY,
+ ROTENC_BINARY,
+};
+
struct rotary_encoder {
struct input_dev *input;
@@ -37,6 +42,7 @@ struct rotary_encoder {
u32 axis;
bool relative_axis;
bool rollover;
+ enum rotary_encoder_encoding encoding;
unsigned int pos;
@@ -57,8 +63,9 @@ static unsigned int rotary_encoder_get_state(struct rotary_encoder *encoder)
for (i = 0; i < encoder->gpios->ndescs; ++i) {
int val = gpiod_get_value_cansleep(encoder->gpios->desc[i]);
+
/* convert from gray encoding to normal */
- if (ret & 1)
+ if (encoder->encoding == ROTENC_GRAY && ret & 1)
val = !val;
ret = ret << 1 | val;
@@ -213,6 +220,20 @@ static int rotary_encoder_probe(struct platform_device *pdev)
encoder->rollover =
device_property_read_bool(dev, "rotary-encoder,rollover");
+ if (!device_property_present(dev, "rotary-encoder,encoding") ||
+ !device_property_match_string(dev, "rotary-encoder,encoding",
+ "gray")) {
+ dev_info(dev, "gray");
+ encoder->encoding = ROTENC_GRAY;
+ } else if (!device_property_match_string(dev, "rotary-encoder,encoding",
+ "binary")) {
+ dev_info(dev, "binary");
+ encoder->encoding = ROTENC_BINARY;
+ } else {
+ dev_err(dev, "unknown encoding setting\n");
+ return -EINVAL;
+ }
+
device_property_read_u32(dev, "linux,axis", &encoder->axis);
encoder->relative_axis =
device_property_read_bool(dev, "rotary-encoder,relative-axis");
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 2f589857a039..d15b33813021 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -4,7 +4,8 @@
* Copyright (c) 2013 ELAN Microelectronics Corp.
*
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * Version: 1.6.0
+ * Author: KT Liao <kt.liao@emc.com.tw>
+ * Version: 1.6.2
*
* Based on cyapa driver:
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -40,7 +41,7 @@
#include "elan_i2c.h"
#define DRIVER_NAME "elan_i2c"
-#define ELAN_DRIVER_VERSION "1.6.1"
+#define ELAN_DRIVER_VERSION "1.6.2"
#define ELAN_VENDOR_ID 0x04f3
#define ETP_MAX_PRESSURE 255
#define ETP_FWIDTH_REDUCE 90
@@ -199,9 +200,41 @@ static int elan_sleep(struct elan_tp_data *data)
return error;
}
+static int elan_query_product(struct elan_tp_data *data)
+{
+ int error;
+
+ error = data->ops->get_product_id(data->client, &data->product_id);
+ if (error)
+ return error;
+
+ error = data->ops->get_sm_version(data->client, &data->ic_type,
+ &data->sm_version);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
+{
+ if (data->ic_type != 0x0E)
+ return false;
+
+ switch (data->product_id) {
+ case 0x05 ... 0x07:
+ case 0x09:
+ case 0x13:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int __elan_initialize(struct elan_tp_data *data)
{
struct i2c_client *client = data->client;
+ bool woken_up = false;
int error;
error = data->ops->initialize(client);
@@ -210,6 +243,27 @@ static int __elan_initialize(struct elan_tp_data *data)
return error;
}
+ error = elan_query_product(data);
+ if (error)
+ return error;
+
+ /*
+ * Some ASUS devices were shipped with firmware that requires
+ * touchpads to be woken up first, before attempting to switch
+ * them into absolute reporting mode.
+ */
+ if (elan_check_ASUS_special_fw(data)) {
+ error = data->ops->sleep_control(client, false);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to wake device up: %d\n", error);
+ return error;
+ }
+
+ msleep(200);
+ woken_up = true;
+ }
+
data->mode |= ETP_ENABLE_ABS;
error = data->ops->set_mode(client, data->mode);
if (error) {
@@ -218,11 +272,13 @@ static int __elan_initialize(struct elan_tp_data *data)
return error;
}
- error = data->ops->sleep_control(client, false);
- if (error) {
- dev_err(&client->dev,
- "failed to wake device up: %d\n", error);
- return error;
+ if (!woken_up) {
+ error = data->ops->sleep_control(client, false);
+ if (error) {
+ dev_err(&client->dev,
+ "failed to wake device up: %d\n", error);
+ return error;
+ }
}
return 0;
@@ -248,10 +304,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
{
int error;
- error = data->ops->get_product_id(data->client, &data->product_id);
- if (error)
- return error;
-
error = data->ops->get_version(data->client, false, &data->fw_version);
if (error)
return error;
@@ -261,11 +313,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
if (error)
return error;
- error = data->ops->get_sm_version(data->client, &data->ic_type,
- &data->sm_version);
- if (error)
- return error;
-
error = data->ops->get_version(data->client, true, &data->iap_version);
if (error)
return error;
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 615d23ec0d8e..08e252a42480 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -222,12 +222,8 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg,
*/
static void elantech_packet_dump(struct psmouse *psmouse)
{
- int i;
-
- psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [");
- for (i = 0; i < psmouse->pktsize; i++)
- printk("%s0x%02x ", i ? ", " : " ", psmouse->packet[i]);
- printk("]\n");
+ psmouse_printk(KERN_DEBUG, psmouse, "PS/2 packet [%*ph]\n",
+ psmouse->pktsize, psmouse->packet);
}
/*
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 253df96be427..a73580654c6b 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -232,10 +232,7 @@ err_put_device:
void rmi_unregister_function(struct rmi_function *fn)
{
device_del(&fn->dev);
-
- if (fn->dev.of_node)
- of_node_put(fn->dev.of_node);
-
+ of_node_put(fn->dev.of_node);
put_device(&fn->dev);
}
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 454195709a82..b4d34086e73f 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1277,6 +1277,7 @@ static int __init i8042_create_kbd_port(void)
serio->start = i8042_start;
serio->stop = i8042_stop;
serio->close = i8042_port_close;
+ serio->ps2_cmd_mutex = &i8042_mutex;
serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
@@ -1373,21 +1374,6 @@ static void i8042_unregister_ports(void)
}
}
-/*
- * Checks whether port belongs to i8042 controller.
- */
-bool i8042_check_port_owner(const struct serio *port)
-{
- int i;
-
- for (i = 0; i < I8042_NUM_PORTS; i++)
- if (i8042_ports[i].serio == port)
- return true;
-
- return false;
-}
-EXPORT_SYMBOL(i8042_check_port_owner);
-
static void i8042_free_irqs(void)
{
if (i8042_aux_irq_registered)
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index 316f2c897101..83e9c663aa67 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte);
void ps2_begin_command(struct ps2dev *ps2dev)
{
- mutex_lock(&ps2dev->cmd_mutex);
+ struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
- if (i8042_check_port_owner(ps2dev->serio))
- i8042_lock_chip();
+ mutex_lock(m);
}
EXPORT_SYMBOL(ps2_begin_command);
void ps2_end_command(struct ps2dev *ps2dev)
{
- if (i8042_check_port_owner(ps2dev->serio))
- i8042_unlock_chip();
+ struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
- mutex_unlock(&ps2dev->cmd_mutex);
+ mutex_unlock(m);
}
EXPORT_SYMBOL(ps2_end_command);
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index ee02dc7422bd..2fb1f430a431 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1059,6 +1059,31 @@ config TOUCHSCREEN_RM_TS
To compile this driver as a module, choose M here: the
module will be called raydium_i2c_ts.
+config TOUCHSCREEN_SILEAD
+ tristate "Silead I2C touchscreen"
+ depends on I2C
+ help
+ Say Y here if you have the Silead touchscreen connected to
+ your system.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called silead.
+
+config TOUCHSCREEN_SIS_I2C
+ tristate "SiS 9200 family I2C touchscreen"
+ depends on I2C
+ select CRC_ITU_T
+ depends on GPIOLIB || COMPILE_TEST
+ help
+ This enables support for SiS 9200 family over I2C based touchscreens.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sis_i2c.
+
config TOUCHSCREEN_ST1232
tristate "Sitronix ST1232 touchscreen controllers"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3315882905f7..b4373d6be402 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -64,6 +64,8 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o
+obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_SUN4I) += sun4i-ts.o
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index ddf694b9fffc..fe4848bd1f4c 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -169,7 +169,7 @@ static ssize_t ili210x_calibrate(struct device *dev,
return count;
}
-static DEVICE_ATTR(calibrate, 0644, NULL, ili210x_calibrate);
+static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate);
static struct attribute *ili210x_attributes[] = {
&dev_attr_calibrate.attr,
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
new file mode 100644
index 000000000000..7379fe153cf9
--- /dev/null
+++ b/drivers/input/touchscreen/silead.c
@@ -0,0 +1,565 @@
+/* -------------------------------------------------------------------------
+ * Copyright (C) 2014-2015, Intel Corporation
+ *
+ * Derived from:
+ * gslX68X.c
+ * Copyright (C) 2010-2015, Shanghai Sileadinc Co.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.
+ * -------------------------------------------------------------------------
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/pm.h>
+#include <linux/irq.h>
+
+#include <asm/unaligned.h>
+
+#define SILEAD_TS_NAME "silead_ts"
+
+#define SILEAD_REG_RESET 0xE0
+#define SILEAD_REG_DATA 0x80
+#define SILEAD_REG_TOUCH_NR 0x80
+#define SILEAD_REG_POWER 0xBC
+#define SILEAD_REG_CLOCK 0xE4
+#define SILEAD_REG_STATUS 0xB0
+#define SILEAD_REG_ID 0xFC
+#define SILEAD_REG_MEM_CHECK 0xB0
+
+#define SILEAD_STATUS_OK 0x5A5A5A5A
+#define SILEAD_TS_DATA_LEN 44
+#define SILEAD_CLOCK 0x04
+
+#define SILEAD_CMD_RESET 0x88
+#define SILEAD_CMD_START 0x00
+
+#define SILEAD_POINT_DATA_LEN 0x04
+#define SILEAD_POINT_Y_OFF 0x00
+#define SILEAD_POINT_Y_MSB_OFF 0x01
+#define SILEAD_POINT_X_OFF 0x02
+#define SILEAD_POINT_X_MSB_OFF 0x03
+#define SILEAD_TOUCH_ID_MASK 0xF0
+
+#define SILEAD_CMD_SLEEP_MIN 10000
+#define SILEAD_CMD_SLEEP_MAX 20000
+#define SILEAD_POWER_SLEEP 20
+#define SILEAD_STARTUP_SLEEP 30
+
+#define SILEAD_MAX_FINGERS 10
+
+enum silead_ts_power {
+ SILEAD_POWER_ON = 1,
+ SILEAD_POWER_OFF = 0
+};
+
+struct silead_ts_data {
+ struct i2c_client *client;
+ struct gpio_desc *gpio_power;
+ struct input_dev *input;
+ char fw_name[64];
+ struct touchscreen_properties prop;
+ u32 max_fingers;
+ u32 chip_id;
+ struct input_mt_pos pos[SILEAD_MAX_FINGERS];
+ int slots[SILEAD_MAX_FINGERS];
+ int id[SILEAD_MAX_FINGERS];
+};
+
+struct silead_fw_data {
+ u32 offset;
+ u32 val;
+};
+
+static int silead_ts_request_input_dev(struct silead_ts_data *data)
+{
+ struct device *dev = &data->client->dev;
+ int error;
+
+ data->input = devm_input_allocate_device(dev);
+ if (!data->input) {
+ dev_err(dev,
+ "Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ input_set_abs_params(data->input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
+ input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
+ touchscreen_parse_properties(data->input, true, &data->prop);
+
+ input_mt_init_slots(data->input, data->max_fingers,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
+ INPUT_MT_TRACK);
+
+ data->input->name = SILEAD_TS_NAME;
+ data->input->phys = "input/ts";
+ data->input->id.bustype = BUS_I2C;
+
+ error = input_register_device(data->input);
+ if (error) {
+ dev_err(dev, "Failed to register input device: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static void silead_ts_set_power(struct i2c_client *client,
+ enum silead_ts_power state)
+{
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+
+ if (data->gpio_power) {
+ gpiod_set_value_cansleep(data->gpio_power, state);
+ msleep(SILEAD_POWER_SLEEP);
+ }
+}
+
+static void silead_ts_read_data(struct i2c_client *client)
+{
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+ struct input_dev *input = data->input;
+ struct device *dev = &client->dev;
+ u8 *bufp, buf[SILEAD_TS_DATA_LEN];
+ int touch_nr, error, i;
+
+ error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
+ SILEAD_TS_DATA_LEN, buf);
+ if (error < 0) {
+ dev_err(dev, "Data read error %d\n", error);
+ return;
+ }
+
+ touch_nr = buf[0];
+ if (touch_nr > data->max_fingers) {
+ dev_warn(dev, "More touches reported then supported %d > %d\n",
+ touch_nr, data->max_fingers);
+ touch_nr = data->max_fingers;
+ }
+
+ bufp = buf + SILEAD_POINT_DATA_LEN;
+ for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) {
+ /* Bits 4-7 are the touch id */
+ data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] &
+ SILEAD_TOUCH_ID_MASK) >> 4;
+ touchscreen_set_mt_pos(&data->pos[i], &data->prop,
+ get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
+ get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
+ }
+
+ input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
+
+ for (i = 0; i < touch_nr; i++) {
+ input_mt_slot(input, data->slots[i]);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+ input_report_abs(input, ABS_MT_POSITION_X, data->pos[i].x);
+ input_report_abs(input, ABS_MT_POSITION_Y, data->pos[i].y);
+
+ dev_dbg(dev, "x=%d y=%d hw_id=%d sw_id=%d\n", data->pos[i].x,
+ data->pos[i].y, data->id[i], data->slots[i]);
+ }
+
+ input_mt_sync_frame(input);
+ input_sync(input);
+}
+
+static int silead_ts_init(struct i2c_client *client)
+{
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+ int error;
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
+ SILEAD_CMD_RESET);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
+ data->max_fingers);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_CLOCK,
+ SILEAD_CLOCK);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
+ SILEAD_CMD_START);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ return 0;
+
+i2c_write_err:
+ dev_err(&client->dev, "Registers clear error %d\n", error);
+ return error;
+}
+
+static int silead_ts_reset(struct i2c_client *client)
+{
+ int error;
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
+ SILEAD_CMD_RESET);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_CLOCK,
+ SILEAD_CLOCK);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_POWER,
+ SILEAD_CMD_START);
+ if (error)
+ goto i2c_write_err;
+ usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
+
+ return 0;
+
+i2c_write_err:
+ dev_err(&client->dev, "Chip reset error %d\n", error);
+ return error;
+}
+
+static int silead_ts_startup(struct i2c_client *client)
+{
+ int error;
+
+ error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET, 0x00);
+ if (error) {
+ dev_err(&client->dev, "Startup error %d\n", error);
+ return error;
+ }
+
+ msleep(SILEAD_STARTUP_SLEEP);
+
+ return 0;
+}
+
+static int silead_ts_load_fw(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+ unsigned int fw_size, i;
+ const struct firmware *fw;
+ struct silead_fw_data *fw_data;
+ int error;
+
+ dev_dbg(dev, "Firmware file name: %s", data->fw_name);
+
+ error = request_firmware(&fw, data->fw_name, dev);
+ if (error) {
+ dev_err(dev, "Firmware request error %d\n", error);
+ return error;
+ }
+
+ fw_size = fw->size / sizeof(*fw_data);
+ fw_data = (struct silead_fw_data *)fw->data;
+
+ for (i = 0; i < fw_size; i++) {
+ error = i2c_smbus_write_i2c_block_data(client,
+ fw_data[i].offset,
+ 4,
+ (u8 *)&fw_data[i].val);
+ if (error) {
+ dev_err(dev, "Firmware load error %d\n", error);
+ break;
+ }
+ }
+
+ release_firmware(fw);
+ return error ?: 0;
+}
+
+static u32 silead_ts_get_status(struct i2c_client *client)
+{
+ int error;
+ __le32 status;
+
+ error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_STATUS,
+ sizeof(status), (u8 *)&status);
+ if (error < 0) {
+ dev_err(&client->dev, "Status read error %d\n", error);
+ return error;
+ }
+
+ return le32_to_cpu(status);
+}
+
+static int silead_ts_get_id(struct i2c_client *client)
+{
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+ __le32 chip_id;
+ int error;
+
+ error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
+ sizeof(chip_id), (u8 *)&chip_id);
+ if (error < 0) {
+ dev_err(&client->dev, "Chip ID read error %d\n", error);
+ return error;
+ }
+
+ data->chip_id = le32_to_cpu(chip_id);
+ dev_info(&client->dev, "Silead chip ID: 0x%8X", data->chip_id);
+
+ return 0;
+}
+
+static int silead_ts_setup(struct i2c_client *client)
+{
+ int error;
+ u32 status;
+
+ silead_ts_set_power(client, SILEAD_POWER_OFF);
+ silead_ts_set_power(client, SILEAD_POWER_ON);
+
+ error = silead_ts_get_id(client);
+ if (error)
+ return error;
+
+ error = silead_ts_init(client);
+ if (error)
+ return error;
+
+ error = silead_ts_reset(client);
+ if (error)
+ return error;
+
+ error = silead_ts_load_fw(client);
+ if (error)
+ return error;
+
+ error = silead_ts_startup(client);
+ if (error)
+ return error;
+
+ status = silead_ts_get_status(client);
+ if (status != SILEAD_STATUS_OK) {
+ dev_err(&client->dev,
+ "Initialization error, status: 0x%X\n", status);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static irqreturn_t silead_ts_threaded_irq_handler(int irq, void *id)
+{
+ struct silead_ts_data *data = id;
+ struct i2c_client *client = data->client;
+
+ silead_ts_read_data(client);
+
+ return IRQ_HANDLED;
+}
+
+static void silead_ts_read_props(struct i2c_client *client)
+{
+ struct silead_ts_data *data = i2c_get_clientdata(client);
+ struct device *dev = &client->dev;
+ const char *str;
+ int error;
+
+ error = device_property_read_u32(dev, "silead,max-fingers",
+ &data->max_fingers);
+ if (error) {
+ dev_dbg(dev, "Max fingers read error %d\n", error);
+ data->max_fingers = 5; /* Most devices handle up-to 5 fingers */
+ }
+
+ error = device_property_read_string(dev, "touchscreen-fw-name", &str);
+ if (!error)
+ snprintf(data->fw_name, sizeof(data->fw_name), "%s", str);
+ else
+ dev_dbg(dev, "Firmware file name read error. Using default.");
+}
+
+#ifdef CONFIG_ACPI
+static int silead_ts_set_default_fw_name(struct silead_ts_data *data,
+ const struct i2c_device_id *id)
+{
+ const struct acpi_device_id *acpi_id;
+ struct device *dev = &data->client->dev;
+ int i;
+
+ if (ACPI_HANDLE(dev)) {
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!acpi_id)
+ return -ENODEV;
+
+ snprintf(data->fw_name, sizeof(data->fw_name), "%s.fw",
+ acpi_id->id);
+
+ for (i = 0; i < strlen(data->fw_name); i++)
+ data->fw_name[i] = tolower(data->fw_name[i]);
+ } else {
+ snprintf(data->fw_name, sizeof(data->fw_name), "%s.fw",
+ id->name);
+ }
+
+ return 0;
+}
+#else
+static int silead_ts_set_default_fw_name(struct silead_ts_data *data,
+ const struct i2c_device_id *id)
+{
+ snprintf(data->fw_name, sizeof(data->fw_name), "%s.fw", id->name);
+ return 0;
+}
+#endif
+
+static int silead_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct silead_ts_data *data;
+ struct device *dev = &client->dev;
+ int error;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK |
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
+ dev_err(dev, "I2C functionality check failed\n");
+ return -ENXIO;
+ }
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->client = client;
+
+ error = silead_ts_set_default_fw_name(data, id);
+ if (error)
+ return error;
+
+ silead_ts_read_props(client);
+
+ /* We must have the IRQ provided by DT or ACPI subsytem */
+ if (client->irq <= 0)
+ return -ENODEV;
+
+ /* Power GPIO pin */
+ data->gpio_power = gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
+ if (IS_ERR(data->gpio_power)) {
+ if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
+ dev_err(dev, "Shutdown GPIO request failed\n");
+ return PTR_ERR(data->gpio_power);
+ }
+
+ error = silead_ts_setup(client);
+ if (error)
+ return error;
+
+ error = silead_ts_request_input_dev(data);
+ if (error)
+ return error;
+
+ error = devm_request_threaded_irq(dev, client->irq,
+ NULL, silead_ts_threaded_irq_handler,
+ IRQF_ONESHOT, client->name, data);
+ if (error) {
+ if (error != -EPROBE_DEFER)
+ dev_err(dev, "IRQ request failed %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused silead_ts_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ silead_ts_set_power(client, SILEAD_POWER_OFF);
+ return 0;
+}
+
+static int __maybe_unused silead_ts_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int error, status;
+
+ silead_ts_set_power(client, SILEAD_POWER_ON);
+
+ error = silead_ts_reset(client);
+ if (error)
+ return error;
+
+ error = silead_ts_startup(client);
+ if (error)
+ return error;
+
+ status = silead_ts_get_status(client);
+ if (status != SILEAD_STATUS_OK) {
+ dev_err(dev, "Resume error, status: 0x%02x\n", status);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(silead_ts_pm, silead_ts_suspend, silead_ts_resume);
+
+static const struct i2c_device_id silead_ts_id[] = {
+ { "gsl1680", 0 },
+ { "gsl1688", 0 },
+ { "gsl3670", 0 },
+ { "gsl3675", 0 },
+ { "gsl3692", 0 },
+ { "mssl1680", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, silead_ts_id);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id silead_ts_acpi_match[] = {
+ { "GSL1680", 0 },
+ { "GSL1688", 0 },
+ { "GSL3670", 0 },
+ { "GSL3675", 0 },
+ { "GSL3692", 0 },
+ { "MSSL1680", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, silead_ts_acpi_match);
+#endif
+
+static struct i2c_driver silead_ts_driver = {
+ .probe = silead_ts_probe,
+ .id_table = silead_ts_id,
+ .driver = {
+ .name = SILEAD_TS_NAME,
+ .acpi_match_table = ACPI_PTR(silead_ts_acpi_match),
+ .pm = &silead_ts_pm,
+ },
+};
+module_i2c_driver(silead_ts_driver);
+
+MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");
+MODULE_DESCRIPTION("Silead I2C touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c
new file mode 100644
index 000000000000..8d93f8c9a403
--- /dev/null
+++ b/drivers/input/touchscreen/sis_i2c.c
@@ -0,0 +1,413 @@
+/*
+ * Touch Screen driver for SiS 9200 family I2C Touch panels
+ *
+ * Copyright (C) 2015 SiS, Inc.
+ * Copyright (C) 2016 Nextfour Group
+ *
+ * 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/crc-itu-t.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/interrupt.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+#define SIS_I2C_NAME "sis_i2c_ts"
+
+/*
+ * The I2C packet format:
+ * le16 byte count
+ * u8 Report ID
+ * <contact data - variable length>
+ * u8 Number of contacts
+ * le16 Scan Time (optional)
+ * le16 CRC
+ *
+ * One touch point information consists of 6+ bytes, the order is:
+ * u8 contact state
+ * u8 finger id
+ * le16 x axis
+ * le16 y axis
+ * u8 contact width (optional)
+ * u8 contact height (optional)
+ * u8 pressure (optional)
+ *
+ * Maximum amount of data transmitted in one shot is 64 bytes, if controller
+ * needs to report more contacts than fit in one packet it will send true
+ * number of contacts in first packet and 0 as number of contacts in second
+ * packet.
+ */
+
+#define SIS_MAX_PACKET_SIZE 64
+
+#define SIS_PKT_LEN_OFFSET 0
+#define SIS_PKT_REPORT_OFFSET 2 /* Report ID/type */
+#define SIS_PKT_CONTACT_OFFSET 3 /* First contact */
+
+#define SIS_SCAN_TIME_LEN 2
+
+/* Supported report types */
+#define SIS_ALL_IN_ONE_PACKAGE 0x10
+#define SIS_PKT_IS_TOUCH(x) (((x) & 0x0f) == 0x01)
+#define SIS_PKT_IS_HIDI2C(x) (((x) & 0x0f) == 0x06)
+
+/* Contact properties within report */
+#define SIS_PKT_HAS_AREA(x) ((x) & BIT(4))
+#define SIS_PKT_HAS_PRESSURE(x) ((x) & BIT(5))
+#define SIS_PKT_HAS_SCANTIME(x) ((x) & BIT(6))
+
+/* Contact size */
+#define SIS_BASE_LEN_PER_CONTACT 6
+#define SIS_AREA_LEN_PER_CONTACT 2
+#define SIS_PRESSURE_LEN_PER_CONTACT 1
+
+/* Offsets within contact data */
+#define SIS_CONTACT_STATUS_OFFSET 0
+#define SIS_CONTACT_ID_OFFSET 1 /* Contact ID */
+#define SIS_CONTACT_X_OFFSET 2
+#define SIS_CONTACT_Y_OFFSET 4
+#define SIS_CONTACT_WIDTH_OFFSET 6
+#define SIS_CONTACT_HEIGHT_OFFSET 7
+#define SIS_CONTACT_PRESSURE_OFFSET(id) (SIS_PKT_HAS_AREA(id) ? 8 : 6)
+
+/* Individual contact state */
+#define SIS_STATUS_UP 0x0
+#define SIS_STATUS_DOWN 0x3
+
+/* Touchscreen parameters */
+#define SIS_MAX_FINGERS 10
+#define SIS_MAX_X 4095
+#define SIS_MAX_Y 4095
+#define SIS_MAX_PRESSURE 255
+
+/* Resolution diagonal */
+#define SIS_AREA_LENGTH_LONGER 5792
+/*((SIS_MAX_X^2) + (SIS_MAX_Y^2))^0.5*/
+#define SIS_AREA_LENGTH_SHORT 5792
+#define SIS_AREA_UNIT (5792 / 32)
+
+struct sis_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+
+ struct gpio_desc *attn_gpio;
+ struct gpio_desc *reset_gpio;
+
+ u8 packet[SIS_MAX_PACKET_SIZE];
+};
+
+static int sis_read_packet(struct i2c_client *client, u8 *buf,
+ unsigned int *num_contacts,
+ unsigned int *contact_size)
+{
+ int count_idx;
+ int ret;
+ u16 len;
+ u16 crc, pkg_crc;
+ u8 report_id;
+
+ ret = i2c_master_recv(client, buf, SIS_MAX_PACKET_SIZE);
+ if (ret <= 0)
+ return -EIO;
+
+ len = get_unaligned_le16(&buf[SIS_PKT_LEN_OFFSET]);
+ if (len > SIS_MAX_PACKET_SIZE) {
+ dev_err(&client->dev,
+ "%s: invalid packet length (%d vs %d)\n",
+ __func__, len, SIS_MAX_PACKET_SIZE);
+ return -E2BIG;
+ }
+
+ if (len < 10)
+ return -EINVAL;
+
+ report_id = buf[SIS_PKT_REPORT_OFFSET];
+ count_idx = len - 1;
+ *contact_size = SIS_BASE_LEN_PER_CONTACT;
+
+ if (report_id != SIS_ALL_IN_ONE_PACKAGE) {
+ if (SIS_PKT_IS_TOUCH(report_id)) {
+ /*
+ * Calculate CRC ignoring packet length
+ * in the beginning and CRC transmitted
+ * at the end of the packet.
+ */
+ crc = crc_itu_t(0, buf + 2, len - 2 - 2);
+ pkg_crc = get_unaligned_le16(&buf[len - 2]);
+
+ if (crc != pkg_crc) {
+ dev_err(&client->dev,
+ "%s: CRC Error (%d vs %d)\n",
+ __func__, crc, pkg_crc);
+ return -EINVAL;
+ }
+
+ count_idx -= 2;
+
+ } else if (!SIS_PKT_IS_HIDI2C(report_id)) {
+ dev_err(&client->dev,
+ "%s: invalid packet ID %#02x\n",
+ __func__, report_id);
+ return -EINVAL;
+ }
+
+ if (SIS_PKT_HAS_SCANTIME(report_id))
+ count_idx -= SIS_SCAN_TIME_LEN;
+
+ if (SIS_PKT_HAS_AREA(report_id))
+ *contact_size += SIS_AREA_LEN_PER_CONTACT;
+ if (SIS_PKT_HAS_PRESSURE(report_id))
+ *contact_size += SIS_PRESSURE_LEN_PER_CONTACT;
+ }
+
+ *num_contacts = buf[count_idx];
+ return 0;
+}
+
+static int sis_ts_report_contact(struct sis_ts_data *ts, const u8 *data, u8 id)
+{
+ struct input_dev *input = ts->input;
+ int slot;
+ u8 status = data[SIS_CONTACT_STATUS_OFFSET];
+ u8 pressure;
+ u8 height, width;
+ u16 x, y;
+
+ if (status != SIS_STATUS_DOWN && status != SIS_STATUS_UP) {
+ dev_err(&ts->client->dev, "Unexpected touch status: %#02x\n",
+ data[SIS_CONTACT_STATUS_OFFSET]);
+ return -EINVAL;
+ }
+
+ slot = input_mt_get_slot_by_key(input, data[SIS_CONTACT_ID_OFFSET]);
+ if (slot < 0)
+ return -ENOENT;
+
+ input_mt_slot(input, slot);
+ input_mt_report_slot_state(input, MT_TOOL_FINGER,
+ status == SIS_STATUS_DOWN);
+
+ if (status == SIS_STATUS_DOWN) {
+ pressure = height = width = 1;
+ if (id != SIS_ALL_IN_ONE_PACKAGE) {
+ if (SIS_PKT_HAS_AREA(id)) {
+ width = data[SIS_CONTACT_WIDTH_OFFSET];
+ height = data[SIS_CONTACT_HEIGHT_OFFSET];
+ }
+
+ if (SIS_PKT_HAS_PRESSURE(id))
+ pressure =
+ data[SIS_CONTACT_PRESSURE_OFFSET(id)];
+ }
+
+ x = get_unaligned_le16(&data[SIS_CONTACT_X_OFFSET]);
+ y = get_unaligned_le16(&data[SIS_CONTACT_Y_OFFSET]);
+
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR,
+ width * SIS_AREA_UNIT);
+ input_report_abs(input, ABS_MT_TOUCH_MINOR,
+ height * SIS_AREA_UNIT);
+ input_report_abs(input, ABS_MT_PRESSURE, pressure);
+ input_report_abs(input, ABS_MT_POSITION_X, x);
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
+ }
+
+ return 0;
+}
+
+static void sis_ts_handle_packet(struct sis_ts_data *ts)
+{
+ const u8 *contact;
+ unsigned int num_to_report = 0;
+ unsigned int num_contacts;
+ unsigned int num_reported;
+ unsigned int contact_size;
+ int error;
+ u8 report_id;
+
+ do {
+ error = sis_read_packet(ts->client, ts->packet,
+ &num_contacts, &contact_size);
+ if (error)
+ break;
+
+ if (num_to_report == 0) {
+ num_to_report = num_contacts;
+ } else if (num_contacts != 0) {
+ dev_err(&ts->client->dev,
+ "%s: nonzero (%d) point count in tail packet\n",
+ __func__, num_contacts);
+ break;
+ }
+
+ report_id = ts->packet[SIS_PKT_REPORT_OFFSET];
+ contact = &ts->packet[SIS_PKT_CONTACT_OFFSET];
+ num_reported = 0;
+
+ while (num_to_report > 0) {
+ error = sis_ts_report_contact(ts, contact, report_id);
+ if (error)
+ break;
+
+ contact += contact_size;
+ num_to_report--;
+ num_reported++;
+
+ if (report_id != SIS_ALL_IN_ONE_PACKAGE &&
+ num_reported >= 5) {
+ /*
+ * The remainder of contacts is sent
+ * in the 2nd packet.
+ */
+ break;
+ }
+ }
+ } while (num_to_report > 0);
+
+ input_mt_sync_frame(ts->input);
+ input_sync(ts->input);
+}
+
+static irqreturn_t sis_ts_irq_handler(int irq, void *dev_id)
+{
+ struct sis_ts_data *ts = dev_id;
+
+ do {
+ sis_ts_handle_packet(ts);
+ } while (ts->attn_gpio && gpiod_get_value_cansleep(ts->attn_gpio));
+
+ return IRQ_HANDLED;
+}
+
+static void sis_ts_reset(struct sis_ts_data *ts)
+{
+ if (ts->reset_gpio) {
+ /* Get out of reset */
+ usleep_range(1000, 2000);
+ gpiod_set_value(ts->reset_gpio, 1);
+ usleep_range(1000, 2000);
+ gpiod_set_value(ts->reset_gpio, 0);
+ msleep(100);
+ }
+}
+
+static int sis_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct sis_ts_data *ts;
+ struct input_dev *input;
+ int error;
+
+ ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+
+ ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
+ "attn", GPIOD_IN);
+ if (IS_ERR(ts->attn_gpio)) {
+ error = PTR_ERR(ts->attn_gpio);
+ if (error != -EPROBE_DEFER)
+ dev_err(&client->dev,
+ "Failed to get attention GPIO: %d\n", error);
+ return error;
+ }
+
+ ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
+ "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ts->reset_gpio)) {
+ error = PTR_ERR(ts->reset_gpio);
+ if (error != -EPROBE_DEFER)
+ dev_err(&client->dev,
+ "Failed to get reset GPIO: %d\n", error);
+ return error;
+ }
+
+ sis_ts_reset(ts);
+
+ ts->input = input = devm_input_allocate_device(&client->dev);
+ if (!input) {
+ dev_err(&client->dev, "Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ input->name = "SiS Touchscreen";
+ input->id.bustype = BUS_I2C;
+
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
+ 0, SIS_AREA_LENGTH_LONGER, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
+ 0, SIS_AREA_LENGTH_SHORT, 0, 0);
+
+ error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to initialize MT slots: %d\n", error);
+ return error;
+ }
+
+ error = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, sis_ts_irq_handler,
+ IRQF_ONESHOT,
+ client->name, ts);
+ if (error) {
+ dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
+ return error;
+ }
+
+ error = input_register_device(ts->input);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to register input device: %d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id sis_ts_dt_ids[] = {
+ { .compatible = "sis,9200-ts" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sis_ts_dt_ids);
+#endif
+
+static const struct i2c_device_id sis_ts_id[] = {
+ { SIS_I2C_NAME, 0 },
+ { "9200-ts", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, sis_ts_id);
+
+static struct i2c_driver sis_ts_driver = {
+ .driver = {
+ .name = SIS_I2C_NAME,
+ .of_match_table = of_match_ptr(sis_ts_dt_ids),
+ },
+ .probe = sis_ts_probe,
+ .id_table = sis_ts_id,
+};
+module_i2c_driver(sis_ts_driver);
+
+MODULE_DESCRIPTION("SiS 9200 Family Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Mika Penttilä <mika.penttila@nextfour.com>");
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 33c177ba93be..96de97a46079 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2375,7 +2375,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom,
static dma_addr_t map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
phys_addr_t paddr = page_to_phys(page) + offset;
struct protection_domain *domain;
@@ -2398,7 +2398,7 @@ static dma_addr_t map_page(struct device *dev, struct page *page,
* The exported unmap_single function for dma_ops.
*/
static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct protection_domain *domain;
struct dma_ops_domain *dma_dom;
@@ -2444,7 +2444,7 @@ static int sg_num_pages(struct device *dev,
*/
static int map_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
int mapped_pages = 0, npages = 0, prot = 0, i;
struct protection_domain *domain;
@@ -2525,7 +2525,7 @@ out_err:
*/
static void unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct protection_domain *domain;
struct dma_ops_domain *dma_dom;
@@ -2548,7 +2548,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,
*/
static void *alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
u64 dma_mask = dev->coherent_dma_mask;
struct protection_domain *domain;
@@ -2604,7 +2604,7 @@ out_free:
*/
static void free_coherent(struct device *dev, size_t size,
void *virt_addr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct protection_domain *domain;
struct dma_ops_domain *dma_dom;
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index ea5a9ebf0f78..00c8a08d56e7 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -68,7 +68,8 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
if (!iovad)
return;
- put_iova_domain(iovad);
+ if (iovad->granule)
+ put_iova_domain(iovad);
kfree(iovad);
domain->iova_cookie = NULL;
}
@@ -151,12 +152,15 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent)
}
}
-static struct iova *__alloc_iova(struct iova_domain *iovad, size_t size,
+static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
dma_addr_t dma_limit)
{
+ struct iova_domain *iovad = domain->iova_cookie;
unsigned long shift = iova_shift(iovad);
unsigned long length = iova_align(iovad, size) >> shift;
+ if (domain->geometry.force_aperture)
+ dma_limit = min(dma_limit, domain->geometry.aperture_end);
/*
* Enforce size-alignment to be safe - there could perhaps be an
* attribute to control this per-device, or at least per-domain...
@@ -286,7 +290,7 @@ void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
* or NULL on failure.
*/
struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
- struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+ unsigned long attrs, int prot, dma_addr_t *handle,
void (*flush_page)(struct device *, const void *, phys_addr_t))
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
@@ -306,7 +310,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
} else {
size = ALIGN(size, min_size);
}
- if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs))
+ if (attrs & DMA_ATTR_ALLOC_SINGLE_PAGES)
alloc_sizes = min_size;
count = PAGE_ALIGN(size) >> PAGE_SHIFT;
@@ -314,7 +318,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
if (!pages)
return NULL;
- iova = __alloc_iova(iovad, size, dev->coherent_dma_mask);
+ iova = __alloc_iova(domain, size, dev->coherent_dma_mask);
if (!iova)
goto out_free_pages;
@@ -386,7 +390,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
phys_addr_t phys = page_to_phys(page) + offset;
size_t iova_off = iova_offset(iovad, phys);
size_t len = iova_align(iovad, size + iova_off);
- struct iova *iova = __alloc_iova(iovad, len, dma_get_mask(dev));
+ struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
if (!iova)
return DMA_ERROR_CODE;
@@ -400,7 +404,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
}
void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
}
@@ -538,7 +542,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
prev = s;
}
- iova = __alloc_iova(iovad, iova_len, dma_get_mask(dev));
+ iova = __alloc_iova(domain, iova_len, dma_get_mask(dev));
if (!iova)
goto out_restore_sg;
@@ -560,7 +564,7 @@ out_restore_sg:
}
void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
/*
* The scatterlist segments are mapped into a single
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index afbaa2c69a59..ebb5bf3ddbd9 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3552,7 +3552,7 @@ error:
static dma_addr_t intel_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return __intel_map_single(dev, page_to_phys(page) + offset, size,
dir, *dev->dma_mask);
@@ -3711,14 +3711,14 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
intel_unmap(dev, dev_addr, size);
}
static void *intel_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct page *page = NULL;
int order;
@@ -3764,7 +3764,7 @@ static void *intel_alloc_coherent(struct device *dev, size_t size,
}
static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
int order;
struct page *page = virt_to_page(vaddr);
@@ -3779,7 +3779,7 @@ static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
unsigned long nrpages = 0;
@@ -3808,7 +3808,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
}
static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
int i;
struct dmar_domain *domain;
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 9ed0a8462ccf..3dab13b4a211 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -55,19 +55,19 @@ struct mtk_iommu_data {
bool enable_4GB;
};
-static int compare_of(struct device *dev, void *data)
+static inline int compare_of(struct device *dev, void *data)
{
return dev->of_node == data;
}
-static int mtk_iommu_bind(struct device *dev)
+static inline int mtk_iommu_bind(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
return component_bind_all(dev, &data->smi_imu);
}
-static void mtk_iommu_unbind(struct device *dev)
+static inline void mtk_iommu_unbind(struct device *dev)
{
struct mtk_iommu_data *data = dev_get_drvdata(dev);
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 3786d0f21972..c5f33c3bd228 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -359,7 +359,7 @@ static void gic_handle_shared_int(bool chained)
pending_reg += gic_reg_step;
intrmask_reg += gic_reg_step;
- if (!config_enabled(CONFIG_64BIT) || mips_cm_is64)
+ if (!IS_ENABLED(CONFIG_64BIT) || mips_cm_is64)
continue;
pending[i] |= (u64)gic_read(pending_reg) << 32;
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 69f16f43f8ab..4b177fe11ebb 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -208,7 +208,7 @@ static void bch_data_insert_start(struct closure *cl)
* Journal writes are marked REQ_PREFLUSH; if the original write was a
* flush, it'll wait on the journal write.
*/
- bio->bi_rw &= ~(REQ_PREFLUSH|REQ_FUA);
+ bio->bi_opf &= ~(REQ_PREFLUSH|REQ_FUA);
do {
unsigned i;
@@ -405,7 +405,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
if (!congested &&
mode == CACHE_MODE_WRITEBACK &&
op_is_write(bio_op(bio)) &&
- (bio->bi_rw & REQ_SYNC))
+ (bio->bi_opf & REQ_SYNC))
goto rescale;
spin_lock(&dc->io_lock);
@@ -668,7 +668,7 @@ static inline struct search *search_alloc(struct bio *bio,
s->iop.write_prio = 0;
s->iop.error = 0;
s->iop.flags = 0;
- s->iop.flush_journal = (bio->bi_rw & (REQ_PREFLUSH|REQ_FUA)) != 0;
+ s->iop.flush_journal = (bio->bi_opf & (REQ_PREFLUSH|REQ_FUA)) != 0;
s->iop.wq = bcache_wq;
return s;
@@ -796,8 +796,8 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
goto out_submit;
}
- if (!(bio->bi_rw & REQ_RAHEAD) &&
- !(bio->bi_rw & REQ_META) &&
+ if (!(bio->bi_opf & REQ_RAHEAD) &&
+ !(bio->bi_opf & REQ_META) &&
s->iop.c->gc_stats.in_use < CUTOFF_CACHE_READA)
reada = min_t(sector_t, dc->readahead >> 9,
bdev_sectors(bio->bi_bdev) - bio_end_sector(bio));
@@ -920,7 +920,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)
bch_writeback_add(dc);
s->iop.bio = bio;
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
/* Also need to send a flush to the backing device */
struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0,
dc->disk.bio_split);
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 88ef6d14cce3..95a4ca6ce6ff 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -347,7 +347,7 @@ static void uuid_io(struct cache_set *c, int op, unsigned long op_flags,
for (i = 0; i < KEY_PTRS(k); i++) {
struct bio *bio = bch_bbio_alloc(c);
- bio->bi_rw = REQ_SYNC|REQ_META|op_flags;
+ bio->bi_opf = REQ_SYNC | REQ_META | op_flags;
bio->bi_iter.bi_size = KEY_SIZE(k) << 9;
bio->bi_end_io = uuid_endio;
diff --git a/drivers/md/bcache/writeback.h b/drivers/md/bcache/writeback.h
index 073a042aed24..301eaf565167 100644
--- a/drivers/md/bcache/writeback.h
+++ b/drivers/md/bcache/writeback.h
@@ -57,7 +57,7 @@ static inline bool should_writeback(struct cached_dev *dc, struct bio *bio,
if (would_skip)
return false;
- return bio->bi_rw & REQ_SYNC ||
+ return bio->bi_opf & REQ_SYNC ||
in_use <= CUTOFF_WRITEBACK;
}
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 718744db62df..59b2c50562e4 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -788,7 +788,7 @@ static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
spin_lock_irqsave(&cache->lock, flags);
if (cache->need_tick_bio &&
- !(bio->bi_rw & (REQ_FUA | REQ_PREFLUSH)) &&
+ !(bio->bi_opf & (REQ_FUA | REQ_PREFLUSH)) &&
bio_op(bio) != REQ_OP_DISCARD) {
pb->tick = true;
cache->need_tick_bio = false;
@@ -830,7 +830,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio)
static int bio_triggers_commit(struct cache *cache, struct bio *bio)
{
- return bio->bi_rw & (REQ_PREFLUSH | REQ_FUA);
+ return bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
}
/*
@@ -1069,7 +1069,7 @@ static void dec_io_migrations(struct cache *cache)
static bool discard_or_flush(struct bio *bio)
{
return bio_op(bio) == REQ_OP_DISCARD ||
- bio->bi_rw & (REQ_PREFLUSH | REQ_FUA);
+ bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
}
static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell)
@@ -1980,7 +1980,7 @@ static void process_deferred_bios(struct cache *cache)
bio = bio_list_pop(&bios);
- if (bio->bi_rw & REQ_PREFLUSH)
+ if (bio->bi_opf & REQ_PREFLUSH)
process_flush_bio(cache, bio);
else if (bio_op(bio) == REQ_OP_DISCARD)
process_discard_bio(cache, &structs, bio);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 8f2e3e2ffd26..4e9784b4e0ac 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1136,7 +1136,7 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone)
clone->bi_private = io;
clone->bi_end_io = crypt_endio;
clone->bi_bdev = cc->dev->bdev;
- bio_set_op_attrs(clone, bio_op(io->base_bio), io->base_bio->bi_rw);
+ bio_set_op_attrs(clone, bio_op(io->base_bio), io->base_bio->bi_opf);
}
static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
@@ -1915,7 +1915,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio)
* - for REQ_PREFLUSH device-mapper core ensures that no IO is in-flight
* - for REQ_OP_DISCARD caller must use flush if IO ordering matters
*/
- if (unlikely(bio->bi_rw & REQ_PREFLUSH ||
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH ||
bio_op(bio) == REQ_OP_DISCARD)) {
bio->bi_bdev = cc->dev->bdev;
if (bio_sectors(bio))
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 2faf49d8f4d7..bf2b2676cb8a 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -1542,7 +1542,7 @@ static int era_map(struct dm_target *ti, struct bio *bio)
/*
* REQ_PREFLUSH bios carry no data, so we're not interested in them.
*/
- if (!(bio->bi_rw & REQ_PREFLUSH) &&
+ if (!(bio->bi_opf & REQ_PREFLUSH) &&
(bio_data_dir(bio) == WRITE) &&
!metadata_current_marked(era->md, block)) {
defer_bio(era, bio);
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 29b99fb6a16a..97e446d54a15 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -16,7 +16,7 @@
#define DM_MSG_PREFIX "flakey"
#define all_corrupt_bio_flags_match(bio, fc) \
- (((bio)->bi_rw & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags)
+ (((bio)->bi_opf & (fc)->corrupt_bio_flags) == (fc)->corrupt_bio_flags)
/*
* Flakey: Used for testing only, simulates intermittent,
@@ -266,9 +266,9 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc)
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=%u bi_sector=%llu cur_bytes=%u)\n",
+ "(rw=%c bi_opf=%u 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,
+ (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_opf,
(unsigned long long)bio->bi_iter.bi_sector, bio_bytes);
}
}
@@ -289,10 +289,16 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
pb->bio_submitted = true;
/*
- * Map reads as normal.
+ * Map reads as normal only if corrupt_bio_byte set.
*/
- if (bio_data_dir(bio) == READ)
- goto map_bio;
+ if (bio_data_dir(bio) == READ) {
+ /* If flags were specified, only corrupt those that match. */
+ if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
+ all_corrupt_bio_flags_match(bio, fc))
+ goto map_bio;
+ else
+ return -EIO;
+ }
/*
* Drop writes?
@@ -330,12 +336,13 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
/*
* Corrupt successful READs while in down state.
- * If flags were specified, only corrupt those that match.
*/
- if (fc->corrupt_bio_byte && !error && pb->bio_submitted &&
- (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
- all_corrupt_bio_flags_match(bio, fc))
- corrupt_bio_data(bio, fc);
+ if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
+ if (fc->corrupt_bio_byte)
+ corrupt_bio_data(bio, fc);
+ else
+ return -EIO;
+ }
return error;
}
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index daa03e41654a..0bf1a12e35fe 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -505,9 +505,9 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
* New collapsed (a)synchronous interface.
*
* If the IO is asynchronous (i.e. it has notify.fn), you must either unplug
- * the queue with blk_unplug() some time later or set REQ_SYNC in io_req->bi_rw.
- * If you fail to do one of these, the IO will be submitted to the disk after
- * q->unplug_delay, which defaults to 3ms in blk-settings.c.
+ * the queue with blk_unplug() some time later or set REQ_SYNC in
+ * io_req->bi_opf. If you fail to do one of these, the IO will be submitted to
+ * the disk after q->unplug_delay, which defaults to 3ms in blk-settings.c.
*/
int dm_io(struct dm_io_request *io_req, unsigned num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits)
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index b5dbf7a0515e..4ab68033f9d1 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -555,8 +555,8 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio)
struct bio_vec bv;
size_t alloc_size;
int i = 0;
- bool flush_bio = (bio->bi_rw & REQ_PREFLUSH);
- bool fua_bio = (bio->bi_rw & REQ_FUA);
+ bool flush_bio = (bio->bi_opf & REQ_PREFLUSH);
+ bool fua_bio = (bio->bi_opf & REQ_FUA);
bool discard_bio = (bio_op(bio) == REQ_OP_DISCARD);
pb->block = NULL;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 7eac080fcb18..ac734e5bbe48 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -507,13 +507,27 @@ static bool __must_push_back(struct multipath *m)
static bool must_push_back_rq(struct multipath *m)
{
- return (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
- __must_push_back(m));
+ bool r;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ r = (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags) ||
+ __must_push_back(m));
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
}
static bool must_push_back_bio(struct multipath *m)
{
- return __must_push_back(m);
+ bool r;
+ unsigned long flags;
+
+ spin_lock_irqsave(&m->lock, flags);
+ r = __must_push_back(m);
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ return r;
}
/*
@@ -647,7 +661,7 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
bio->bi_error = 0;
bio->bi_bdev = pgpath->path.dev->bdev;
- bio->bi_rw |= REQ_FAILFAST_TRANSPORT;
+ bio->bi_opf |= REQ_FAILFAST_TRANSPORT;
if (pgpath->pg->ps.type->start_io)
pgpath->pg->ps.type->start_io(&pgpath->pg->ps,
@@ -1680,12 +1694,14 @@ static void multipath_postsuspend(struct dm_target *ti)
static void multipath_resume(struct dm_target *ti)
{
struct multipath *m = ti->private;
+ unsigned long flags;
+ spin_lock_irqsave(&m->lock, flags);
if (test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &m->flags))
set_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
else
clear_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags);
- smp_mb__after_atomic();
+ spin_unlock_irqrestore(&m->lock, flags);
}
/*
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 84983549b5e1..1b9795d75ef8 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1270,7 +1270,7 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as,
}
rs->md.sync_speed_min = (int)value;
} else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE))) {
- if (test_and_set_bit(__CTR_FLAG_MIN_RECOVERY_RATE, &rs->ctr_flags)) {
+ if (test_and_set_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags)) {
rs->ti->error = "Only one max_recovery_rate argument pair allowed";
return -EINVAL;
}
@@ -1960,6 +1960,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
sb->data_offset = cpu_to_le64(rdev->data_offset);
sb->new_data_offset = cpu_to_le64(rdev->new_data_offset);
sb->sectors = cpu_to_le64(rdev->sectors);
+ sb->incompat_features = cpu_to_le32(0);
/* Zero out the rest of the payload after the size of the superblock */
memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
@@ -3577,7 +3578,6 @@ static int raid_preresume(struct dm_target *ti)
/* Be prepared for mddev_resume() in raid_resume() */
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
if (mddev->recovery_cp && mddev->recovery_cp < MaxSector) {
- set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
mddev->resync_min = mddev->recovery_cp;
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index dac55b254a09..bdf1606f67bc 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -657,7 +657,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
struct mirror *m;
struct dm_io_request io_req = {
.bi_op = REQ_OP_WRITE,
- .bi_op_flags = bio->bi_rw & WRITE_FLUSH_FUA,
+ .bi_op_flags = bio->bi_opf & WRITE_FLUSH_FUA,
.mem.type = DM_IO_BIO,
.mem.ptr.bio = bio,
.notify.fn = write_callback,
@@ -704,7 +704,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
bio_list_init(&requeue);
while ((bio = bio_list_pop(writes))) {
- if ((bio->bi_rw & REQ_PREFLUSH) ||
+ if ((bio->bi_opf & REQ_PREFLUSH) ||
(bio_op(bio) == REQ_OP_DISCARD)) {
bio_list_add(&sync, bio);
continue;
@@ -1217,7 +1217,7 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
* If region is not in-sync queue the bio.
*/
if (!r || (r == -EWOULDBLOCK)) {
- if (bio->bi_rw & REQ_RAHEAD)
+ if (bio->bi_opf & REQ_RAHEAD)
return -EWOULDBLOCK;
queue_bio(ms, bio, rw);
@@ -1253,7 +1253,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
* We need to dec pending if this was a write.
*/
if (rw == WRITE) {
- if (!(bio->bi_rw & REQ_PREFLUSH) &&
+ if (!(bio->bi_opf & REQ_PREFLUSH) &&
bio_op(bio) != REQ_OP_DISCARD)
dm_rh_dec(ms->rh, bio_record->write_region);
return error;
@@ -1262,7 +1262,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
if (error == -EOPNOTSUPP)
goto out;
- if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD))
+ if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
goto out;
if (unlikely(error)) {
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index b11813431f31..85c32b22a420 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -398,7 +398,7 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
region_t region = dm_rh_bio_to_region(rh, bio);
int recovering = 0;
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
rh->flush_failure = 1;
return;
}
@@ -526,7 +526,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
struct bio *bio;
for (bio = bios->head; bio; bio = bio->bi_next) {
- if (bio->bi_rw & REQ_PREFLUSH || bio_op(bio) == REQ_OP_DISCARD)
+ if (bio->bi_opf & REQ_PREFLUSH || bio_op(bio) == REQ_OP_DISCARD)
continue;
rh_inc(rh, dm_rh_bio_to_region(rh, bio));
}
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index 7a9661868496..1ca7463e8bb2 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -78,6 +78,7 @@ void dm_start_queue(struct request_queue *q)
if (!q->mq_ops)
dm_old_start_queue(q);
else {
+ queue_flag_clear_unlocked(QUEUE_FLAG_STOPPED, q);
blk_mq_start_stopped_hw_queues(q, true);
blk_mq_kick_requeue_list(q);
}
@@ -101,8 +102,14 @@ void dm_stop_queue(struct request_queue *q)
{
if (!q->mq_ops)
dm_old_stop_queue(q);
- else
+ else {
+ spin_lock_irq(q->queue_lock);
+ queue_flag_set(QUEUE_FLAG_STOPPED, q);
+ spin_unlock_irq(q->queue_lock);
+
+ blk_mq_cancel_requeue_work(q);
blk_mq_stop_hw_queues(q);
+ }
}
static struct dm_rq_target_io *alloc_old_rq_tio(struct mapped_device *md,
@@ -864,6 +871,17 @@ static int dm_mq_queue_rq(struct blk_mq_hw_ctx *hctx,
dm_put_live_table(md, srcu_idx);
}
+ /*
+ * On suspend dm_stop_queue() handles stopping the blk-mq
+ * request_queue BUT: even though the hw_queues are marked
+ * BLK_MQ_S_STOPPED at that point there is still a race that
+ * is allowing block/blk-mq.c to call ->queue_rq against a
+ * hctx that it really shouldn't. The following check guards
+ * against this rarity (albeit _not_ race-free).
+ */
+ if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
+ return BLK_MQ_RQ_QUEUE_BUSY;
+
if (ti->type->busy && ti->type->busy(ti))
return BLK_MQ_RQ_QUEUE_BUSY;
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ce2a910709f7..c65feeada864 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -1680,7 +1680,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio)
init_tracked_chunk(bio);
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
bio->bi_bdev = s->cow->bdev;
return DM_MAPIO_REMAPPED;
}
@@ -1800,7 +1800,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio)
init_tracked_chunk(bio);
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
if (!dm_bio_get_target_bio_nr(bio))
bio->bi_bdev = s->origin->bdev;
else
@@ -2286,7 +2286,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio)
bio->bi_bdev = o->dev->bdev;
- if (unlikely(bio->bi_rw & REQ_PREFLUSH))
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH))
return DM_MAPIO_REMAPPED;
if (bio_data_dir(bio) != WRITE)
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 83f1d4667195..28193a57bf47 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -286,7 +286,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio)
uint32_t stripe;
unsigned target_bio_nr;
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
target_bio_nr = dm_bio_get_target_bio_nr(bio);
BUG_ON(target_bio_nr >= sc->stripes);
bio->bi_bdev = sc->stripe[target_bio_nr].dev->bdev;
@@ -383,7 +383,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio, int error)
if (!error)
return 0; /* I/O complete */
- if ((error == -EWOULDBLOCK) && (bio->bi_rw & REQ_RAHEAD))
+ if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
return error;
if (error == -EOPNOTSUPP)
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 197ea2003400..d1c05c12a9db 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -699,7 +699,7 @@ static void remap_to_origin(struct thin_c *tc, struct bio *bio)
static int bio_triggers_commit(struct thin_c *tc, struct bio *bio)
{
- return (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) &&
+ return (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA)) &&
dm_thin_changed_this_transaction(tc->td);
}
@@ -870,7 +870,7 @@ static void __inc_remap_and_issue_cell(void *context,
struct bio *bio;
while ((bio = bio_list_pop(&cell->bios))) {
- if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) ||
+ if (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA) ||
bio_op(bio) == REQ_OP_DISCARD)
bio_list_add(&info->defer_bios, bio);
else {
@@ -1717,7 +1717,7 @@ static void __remap_and_issue_shared_cell(void *context,
while ((bio = bio_list_pop(&cell->bios))) {
if ((bio_data_dir(bio) == WRITE) ||
- (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) ||
+ (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA) ||
bio_op(bio) == REQ_OP_DISCARD))
bio_list_add(&info->defer_bios, bio);
else {
@@ -2635,7 +2635,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio)
return DM_MAPIO_SUBMITTED;
}
- if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) ||
+ if (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA) ||
bio_op(bio) == REQ_OP_DISCARD) {
thin_defer_bio_with_throttle(tc, bio);
return DM_MAPIO_SUBMITTED;
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index 618b8752dcf1..b616f11d8473 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -37,7 +37,7 @@ static int zero_map(struct dm_target *ti, struct bio *bio)
{
switch (bio_op(bio)) {
case REQ_OP_READ:
- if (bio->bi_rw & REQ_RAHEAD) {
+ if (bio->bi_opf & REQ_RAHEAD) {
/* readahead of null bytes only wastes buffer cache */
return -EIO;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 25d1d97154a8..fa9b1cb4438a 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -798,12 +798,12 @@ static void dec_pending(struct dm_io *io, int error)
if (io_error == DM_ENDIO_REQUEUE)
return;
- if ((bio->bi_rw & REQ_PREFLUSH) && bio->bi_iter.bi_size) {
+ if ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size) {
/*
* Preflush done for flush with data, reissue
* without REQ_PREFLUSH.
*/
- bio->bi_rw &= ~REQ_PREFLUSH;
+ bio->bi_opf &= ~REQ_PREFLUSH;
queue_io(md, bio);
} else {
/* done with normal IO or empty flush */
@@ -964,7 +964,7 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors)
{
struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
unsigned bi_size = bio->bi_iter.bi_size >> SECTOR_SHIFT;
- BUG_ON(bio->bi_rw & REQ_PREFLUSH);
+ BUG_ON(bio->bi_opf & REQ_PREFLUSH);
BUG_ON(bi_size > *tio->len_ptr);
BUG_ON(n_sectors > bi_size);
*tio->len_ptr -= bi_size - n_sectors;
@@ -1252,7 +1252,7 @@ static void __split_and_process_bio(struct mapped_device *md,
start_io_acct(ci.io);
- if (bio->bi_rw & REQ_PREFLUSH) {
+ if (bio->bi_opf & REQ_PREFLUSH) {
ci.bio = &ci.md->flush_bio;
ci.sector_count = 0;
error = __send_empty_flush(&ci);
@@ -1290,7 +1290,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
if (unlikely(test_bit(DMF_BLOCK_IO_FOR_SUSPEND, &md->flags))) {
dm_put_live_table(md, srcu_idx);
- if (!(bio->bi_rw & REQ_RAHEAD))
+ if (!(bio->bi_opf & REQ_RAHEAD))
queue_io(md, bio);
else
bio_io_error(bio);
@@ -2082,7 +2082,8 @@ static void unlock_fs(struct mapped_device *md)
* Caller must hold md->suspend_lock
*/
static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
- unsigned suspend_flags, int interruptible)
+ unsigned suspend_flags, int interruptible,
+ int dmf_suspended_flag)
{
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
@@ -2149,6 +2150,8 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
* to finish.
*/
r = dm_wait_for_completion(md, interruptible);
+ if (!r)
+ set_bit(dmf_suspended_flag, &md->flags);
if (noflush)
clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
@@ -2210,12 +2213,10 @@ retry:
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
- r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE);
+ r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
if (r)
goto out_unlock;
- set_bit(DMF_SUSPENDED, &md->flags);
-
dm_table_postsuspend_targets(map);
out_unlock:
@@ -2309,9 +2310,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
* would require changing .presuspend to return an error -- avoid this
* until there is a need for more elaborate variants of internal suspend.
*/
- (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE);
-
- set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+ (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
+ DMF_SUSPENDED_INTERNALLY);
dm_table_postsuspend_targets(map);
}
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 70ff888d25d0..86f5d435901d 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -221,7 +221,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
struct bio *split;
sector_t start_sector, end_sector, data_offset;
- if (unlikely(bio->bi_rw & REQ_PREFLUSH)) {
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
md_flush_request(mddev, bio);
return;
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 2c3ab6f5e6be..d646f6e444f0 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -285,7 +285,7 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
*/
sectors = bio_sectors(bio);
/* bio could be mergeable after passing to underlayer */
- bio->bi_rw &= ~REQ_NOMERGE;
+ bio->bi_opf &= ~REQ_NOMERGE;
mddev->pers->make_request(mddev, bio);
cpu = part_stat_lock();
@@ -414,7 +414,7 @@ static void md_submit_flush_data(struct work_struct *ws)
/* an empty barrier - all done */
bio_endio(bio);
else {
- bio->bi_rw &= ~REQ_PREFLUSH;
+ bio->bi_opf &= ~REQ_PREFLUSH;
mddev->pers->make_request(mddev, bio);
}
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 4974682842ae..673efbd6fc47 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -91,7 +91,7 @@ static void multipath_end_request(struct bio *bio)
if (!bio->bi_error)
multipath_end_bh_io(mp_bh, 0);
- else if (!(bio->bi_rw & REQ_RAHEAD)) {
+ else if (!(bio->bi_opf & REQ_RAHEAD)) {
/*
* oops, IO error:
*/
@@ -112,7 +112,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
struct multipath_bh * mp_bh;
struct multipath_info *multipath;
- if (unlikely(bio->bi_rw & REQ_PREFLUSH)) {
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
md_flush_request(mddev, bio);
return;
}
@@ -135,7 +135,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio)
mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
mp_bh->bio.bi_bdev = multipath->rdev->bdev;
- mp_bh->bio.bi_rw |= REQ_FAILFAST_TRANSPORT;
+ mp_bh->bio.bi_opf |= REQ_FAILFAST_TRANSPORT;
mp_bh->bio.bi_end_io = multipath_end_request;
mp_bh->bio.bi_private = mp_bh;
generic_make_request(&mp_bh->bio);
@@ -360,7 +360,7 @@ static void multipathd(struct md_thread *thread)
bio->bi_iter.bi_sector +=
conf->multipaths[mp_bh->path].rdev->data_offset;
bio->bi_bdev = conf->multipaths[mp_bh->path].rdev->bdev;
- bio->bi_rw |= REQ_FAILFAST_TRANSPORT;
+ bio->bi_opf |= REQ_FAILFAST_TRANSPORT;
bio->bi_end_io = multipath_end_request;
bio->bi_private = mp_bh;
generic_make_request(bio);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index c3d439083212..258986a2699d 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -458,7 +458,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
struct md_rdev *tmp_dev;
struct bio *split;
- if (unlikely(bio->bi_rw & REQ_PREFLUSH)) {
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
md_flush_request(mddev, bio);
return;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 46168ef2e279..21dc00eb1989 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1043,8 +1043,8 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio)
unsigned long flags;
const int op = bio_op(bio);
const int rw = bio_data_dir(bio);
- const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
- const unsigned long do_flush_fua = (bio->bi_rw &
+ const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+ const unsigned long do_flush_fua = (bio->bi_opf &
(REQ_PREFLUSH | REQ_FUA));
struct md_rdev *blocked_rdev;
struct blk_plug_cb *cb;
@@ -2318,7 +2318,7 @@ read_more:
raid_end_bio_io(r1_bio);
} else {
const unsigned long do_sync
- = r1_bio->master_bio->bi_rw & REQ_SYNC;
+ = r1_bio->master_bio->bi_opf & REQ_SYNC;
if (bio) {
r1_bio->bios[r1_bio->read_disk] =
mddev->ro ? IO_BLOCKED : NULL;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index ed29fc899f06..0e4efcd10795 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1054,8 +1054,8 @@ static void __make_request(struct mddev *mddev, struct bio *bio)
int i;
const int op = bio_op(bio);
const int rw = bio_data_dir(bio);
- const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
- const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
+ const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+ const unsigned long do_fua = (bio->bi_opf & REQ_FUA);
unsigned long flags;
struct md_rdev *blocked_rdev;
struct blk_plug_cb *cb;
@@ -1440,7 +1440,7 @@ static void raid10_make_request(struct mddev *mddev, struct bio *bio)
struct bio *split;
- if (unlikely(bio->bi_rw & REQ_PREFLUSH)) {
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
md_flush_request(mddev, bio);
return;
}
@@ -2533,7 +2533,7 @@ read_more:
return;
}
- do_sync = (r10_bio->master_bio->bi_rw & REQ_SYNC);
+ do_sync = (r10_bio->master_bio->bi_opf & REQ_SYNC);
slot = r10_bio->read_slot;
printk_ratelimited(
KERN_ERR
diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
index 5504ce2bac06..51f76ddbe265 100644
--- a/drivers/md/raid5-cache.c
+++ b/drivers/md/raid5-cache.c
@@ -536,7 +536,7 @@ int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio)
bio_endio(bio);
return 0;
}
- bio->bi_rw &= ~REQ_PREFLUSH;
+ bio->bi_opf &= ~REQ_PREFLUSH;
return -EAGAIN;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index d189e894b921..8912407a4dd0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -806,7 +806,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh
dd_idx = 0;
while (dd_idx == sh->pd_idx || dd_idx == sh->qd_idx)
dd_idx++;
- if (head->dev[dd_idx].towrite->bi_rw != sh->dev[dd_idx].towrite->bi_rw ||
+ if (head->dev[dd_idx].towrite->bi_opf != sh->dev[dd_idx].towrite->bi_opf ||
bio_op(head->dev[dd_idx].towrite) != bio_op(sh->dev[dd_idx].towrite))
goto unlock_out;
@@ -1003,7 +1003,7 @@ again:
pr_debug("%s: for %llu schedule op %d on disc %d\n",
__func__, (unsigned long long)sh->sector,
- bi->bi_rw, i);
+ bi->bi_opf, i);
atomic_inc(&sh->count);
if (sh != head_sh)
atomic_inc(&head_sh->count);
@@ -1014,7 +1014,7 @@ again:
bi->bi_iter.bi_sector = (sh->sector
+ rdev->data_offset);
if (test_bit(R5_ReadNoMerge, &head_sh->dev[i].flags))
- bi->bi_rw |= REQ_NOMERGE;
+ bi->bi_opf |= REQ_NOMERGE;
if (test_bit(R5_SkipCopy, &sh->dev[i].flags))
WARN_ON(test_bit(R5_UPTODATE, &sh->dev[i].flags));
@@ -1055,7 +1055,7 @@ again:
pr_debug("%s: for %llu schedule op %d on "
"replacement disc %d\n",
__func__, (unsigned long long)sh->sector,
- rbi->bi_rw, i);
+ rbi->bi_opf, i);
atomic_inc(&sh->count);
if (sh != head_sh)
atomic_inc(&head_sh->count);
@@ -1088,7 +1088,7 @@ again:
if (op_is_write(op))
set_bit(STRIPE_DEGRADED, &sh->state);
pr_debug("skip op %d on disc %d for sector %llu\n",
- bi->bi_rw, i, (unsigned long long)sh->sector);
+ bi->bi_opf, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state);
}
@@ -1619,9 +1619,9 @@ again:
while (wbi && wbi->bi_iter.bi_sector <
dev->sector + STRIPE_SECTORS) {
- if (wbi->bi_rw & REQ_FUA)
+ if (wbi->bi_opf & REQ_FUA)
set_bit(R5_WantFUA, &dev->flags);
- if (wbi->bi_rw & REQ_SYNC)
+ if (wbi->bi_opf & REQ_SYNC)
set_bit(R5_SyncIO, &dev->flags);
if (bio_op(wbi) == REQ_OP_DISCARD)
set_bit(R5_Discard, &dev->flags);
@@ -5154,7 +5154,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi)
DEFINE_WAIT(w);
bool do_prepare;
- if (unlikely(bi->bi_rw & REQ_PREFLUSH)) {
+ if (unlikely(bi->bi_opf & REQ_PREFLUSH)) {
int ret = r5l_handle_flush_request(conf->log, bi);
if (ret == 0)
@@ -5237,7 +5237,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi)
(unsigned long long)logical_sector);
sh = raid5_get_active_stripe(conf, new_sector, previous,
- (bi->bi_rw & REQ_RAHEAD), 0);
+ (bi->bi_opf & REQ_RAHEAD), 0);
if (sh) {
if (unlikely(previous)) {
/* expansion might have moved on while waiting for a
@@ -5305,7 +5305,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi)
set_bit(STRIPE_HANDLE, &sh->state);
clear_bit(STRIPE_DELAYED, &sh->state);
if ((!sh->batch_head || sh == sh->batch_head) &&
- (bi->bi_rw & REQ_SYNC) &&
+ (bi->bi_opf & REQ_SYNC) &&
!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
atomic_inc(&conf->preread_active_stripes);
release_stripe_plug(mddev, sh);
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index 09c39346167f..ffe88bc6b813 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -3378,20 +3378,28 @@ static int cxd2841er_tune_tc(struct dvb_frontend *fe,
ret = cxd2841er_get_carrier_offset_i(
priv, p->bandwidth_hz,
&carrier_offset);
+ if (ret)
+ return ret;
break;
case SYS_DVBT:
ret = cxd2841er_get_carrier_offset_t(
priv, p->bandwidth_hz,
&carrier_offset);
+ if (ret)
+ return ret;
break;
case SYS_DVBT2:
ret = cxd2841er_get_carrier_offset_t2(
priv, p->bandwidth_hz,
&carrier_offset);
+ if (ret)
+ return ret;
break;
case SYS_DVBC_ANNEX_A:
ret = cxd2841er_get_carrier_offset_c(
priv, &carrier_offset);
+ if (ret)
+ return ret;
break;
default:
dev_dbg(&priv->i2c->dev,
@@ -3399,8 +3407,6 @@ static int cxd2841er_tune_tc(struct dvb_frontend *fe,
__func__, priv->system);
return -EINVAL;
}
- if (ret)
- return ret;
dev_dbg(&priv->i2c->dev, "%s(): carrier offset %d\n",
__func__, carrier_offset);
p->frequency += carrier_offset;
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index b77b0a4dbf68..95cbc857f36e 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -100,7 +100,7 @@
#define ADV7180_REG_IDENT 0x0011
#define ADV7180_ID_7180 0x18
-#define ADV7180_REG_ICONF1 0x0040
+#define ADV7180_REG_ICONF1 0x2040
#define ADV7180_ICONF1_ACTIVE_LOW 0x01
#define ADV7180_ICONF1_PSYNC_ONLY 0x10
#define ADV7180_ICONF1_ACTIVE_TO_CLR 0xC0
@@ -113,15 +113,15 @@
#define ADV7180_IRQ1_LOCK 0x01
#define ADV7180_IRQ1_UNLOCK 0x02
-#define ADV7180_REG_ISR1 0x0042
-#define ADV7180_REG_ICR1 0x0043
-#define ADV7180_REG_IMR1 0x0044
-#define ADV7180_REG_IMR2 0x0048
+#define ADV7180_REG_ISR1 0x2042
+#define ADV7180_REG_ICR1 0x2043
+#define ADV7180_REG_IMR1 0x2044
+#define ADV7180_REG_IMR2 0x2048
#define ADV7180_IRQ3_AD_CHANGE 0x08
-#define ADV7180_REG_ISR3 0x004A
-#define ADV7180_REG_ICR3 0x004B
-#define ADV7180_REG_IMR3 0x004C
-#define ADV7180_REG_IMR4 0x50
+#define ADV7180_REG_ISR3 0x204A
+#define ADV7180_REG_ICR3 0x204B
+#define ADV7180_REG_IMR3 0x204C
+#define ADV7180_REG_IMR4 0x2050
#define ADV7180_REG_NTSC_V_BIT_END 0x00E6
#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND 0x4F
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 6d7cad54a65d..53030d631653 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -1041,6 +1041,8 @@ static int adv7511_s_dv_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
struct adv7511_state *state = get_adv7511_state(sd);
+ struct v4l2_bt_timings *bt = &timings->bt;
+ u32 fps;
v4l2_dbg(1, debug, sd, "%s:\n", __func__);
@@ -1052,15 +1054,29 @@ static int adv7511_s_dv_timings(struct v4l2_subdev *sd,
if the format is one of the CEA or DMT timings. */
v4l2_find_dv_timings_cap(timings, &adv7511_timings_cap, 0, NULL, NULL);
- timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
-
/* save timings */
state->dv_timings = *timings;
/* set h/vsync polarities */
adv7511_wr_and_or(sd, 0x17, 0x9f,
- ((timings->bt.polarities & V4L2_DV_VSYNC_POS_POL) ? 0 : 0x40) |
- ((timings->bt.polarities & V4L2_DV_HSYNC_POS_POL) ? 0 : 0x20));
+ ((bt->polarities & V4L2_DV_VSYNC_POS_POL) ? 0 : 0x40) |
+ ((bt->polarities & V4L2_DV_HSYNC_POS_POL) ? 0 : 0x20));
+
+ fps = (u32)bt->pixelclock / (V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt));
+ switch (fps) {
+ case 24:
+ adv7511_wr_and_or(sd, 0xfb, 0xf9, 1 << 1);
+ break;
+ case 25:
+ adv7511_wr_and_or(sd, 0xfb, 0xf9, 2 << 1);
+ break;
+ case 30:
+ adv7511_wr_and_or(sd, 0xfb, 0xf9, 3 << 1);
+ break;
+ default:
+ adv7511_wr_and_or(sd, 0xfb, 0xf9, 0);
+ break;
+ }
/* update quantization range based on new dv_timings */
adv7511_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
index e277b7c23516..c7806ecda2dd 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -246,7 +246,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
struct video_device *vfd_enc;
struct resource *res;
int i, j, ret;
- DEFINE_DMA_ATTRS(attrs);
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -378,9 +377,6 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_enc_reg;
}
- /* Avoid the iommu eat big hunks */
- dma_set_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, &attrs);
-
mtk_v4l2_debug(0, "encoder registered as /dev/video%d",
vfd_enc->num);
diff --git a/drivers/media/platform/sti/bdisp/bdisp-hw.c b/drivers/media/platform/sti/bdisp/bdisp-hw.c
index 3df66d11c795..b7892f3efd98 100644
--- a/drivers/media/platform/sti/bdisp/bdisp-hw.c
+++ b/drivers/media/platform/sti/bdisp/bdisp-hw.c
@@ -430,14 +430,11 @@ int bdisp_hw_get_and_clear_irq(struct bdisp_dev *bdisp)
*/
void bdisp_hw_free_nodes(struct bdisp_ctx *ctx)
{
- if (ctx && ctx->node[0]) {
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ if (ctx && ctx->node[0])
dma_free_attrs(ctx->bdisp_dev->dev,
sizeof(struct bdisp_node) * MAX_NB_NODE,
- ctx->node[0], ctx->node_paddr[0], &attrs);
- }
+ ctx->node[0], ctx->node_paddr[0],
+ DMA_ATTR_WRITE_COMBINE);
}
/**
@@ -455,12 +452,10 @@ int bdisp_hw_alloc_nodes(struct bdisp_ctx *ctx)
unsigned int i, node_size = sizeof(struct bdisp_node);
void *base;
dma_addr_t paddr;
- DEFINE_DMA_ATTRS(attrs);
/* Allocate all the nodes within a single memory page */
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
base = dma_alloc_attrs(dev, node_size * MAX_NB_NODE, &paddr,
- GFP_KERNEL | GFP_DMA, &attrs);
+ GFP_KERNEL | GFP_DMA, DMA_ATTR_WRITE_COMBINE);
if (!base) {
dev_err(dev, "%s no mem\n", __func__);
return -ENOMEM;
@@ -493,13 +488,9 @@ void bdisp_hw_free_filters(struct device *dev)
{
int size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
- if (bdisp_h_filter[0].virt) {
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ if (bdisp_h_filter[0].virt)
dma_free_attrs(dev, size, bdisp_h_filter[0].virt,
- bdisp_h_filter[0].paddr, &attrs);
- }
+ bdisp_h_filter[0].paddr, DMA_ATTR_WRITE_COMBINE);
}
/**
@@ -516,12 +507,11 @@ int bdisp_hw_alloc_filters(struct device *dev)
unsigned int i, size;
void *base;
dma_addr_t paddr;
- DEFINE_DMA_ATTRS(attrs);
/* Allocate all the filters within a single memory page */
size = (BDISP_HF_NB * NB_H_FILTER) + (BDISP_VF_NB * NB_V_FILTER);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL | GFP_DMA, &attrs);
+ base = dma_alloc_attrs(dev, size, &paddr, GFP_KERNEL | GFP_DMA,
+ DMA_ATTR_WRITE_COMBINE);
if (!base)
return -ENOMEM;
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 6b17015048ae..cd0ff4a66fdc 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -171,6 +171,9 @@ struct vim2m_ctx {
int mode;
enum v4l2_colorspace colorspace;
+ enum v4l2_ycbcr_encoding ycbcr_enc;
+ enum v4l2_xfer_func xfer_func;
+ enum v4l2_quantization quant;
/* Source and destination queue data */
struct vim2m_q_data q_data[2];
@@ -493,6 +496,9 @@ static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
f->fmt.pix.bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
f->fmt.pix.sizeimage = q_data->sizeimage;
f->fmt.pix.colorspace = ctx->colorspace;
+ f->fmt.pix.xfer_func = ctx->xfer_func;
+ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
+ f->fmt.pix.quantization = ctx->quant;
return 0;
}
@@ -549,6 +555,9 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
return -EINVAL;
}
f->fmt.pix.colorspace = ctx->colorspace;
+ f->fmt.pix.xfer_func = ctx->xfer_func;
+ f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
+ f->fmt.pix.quantization = ctx->quant;
return vidioc_try_fmt(f, fmt);
}
@@ -630,8 +639,12 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
return ret;
ret = vidioc_s_fmt(file2ctx(file), f);
- if (!ret)
+ if (!ret) {
ctx->colorspace = f->fmt.pix.colorspace;
+ ctx->xfer_func = f->fmt.pix.xfer_func;
+ ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
+ ctx->quant = f->fmt.pix.quantization;
+ }
return ret;
}
diff --git a/drivers/media/platform/vivid/vivid-cec.c b/drivers/media/platform/vivid/vivid-cec.c
index 66aa7292076b..f9f878b8e0a7 100644
--- a/drivers/media/platform/vivid/vivid-cec.c
+++ b/drivers/media/platform/vivid/vivid-cec.c
@@ -169,7 +169,6 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
struct vivid_dev *dev = adap->priv;
struct cec_msg reply;
u8 dest = cec_msg_destination(msg);
- u16 pa;
u8 disp_ctl;
char osd[14];
@@ -178,15 +177,6 @@ static int vivid_received(struct cec_adapter *adap, struct cec_msg *msg)
cec_msg_init(&reply, dest, cec_msg_initiator(msg));
switch (cec_msg_opcode(msg)) {
- case CEC_MSG_SET_STREAM_PATH:
- if (cec_is_sink(adap))
- return -ENOMSG;
- cec_ops_set_stream_path(msg, &pa);
- if (pa != adap->phys_addr)
- return -ENOMSG;
- cec_msg_active_source(&reply, adap->phys_addr);
- cec_transmit_msg(adap, &reply, false);
- break;
case CEC_MSG_SET_OSD_STRING:
if (!cec_is_sink(adap))
return -ENOMSG;
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 863f658a3fa1..59fa204b15f3 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -27,7 +27,7 @@ struct vb2_dc_buf {
unsigned long size;
void *cookie;
dma_addr_t dma_addr;
- struct dma_attrs attrs;
+ unsigned long attrs;
enum dma_data_direction dma_dir;
struct sg_table *dma_sgt;
struct frame_vector *vec;
@@ -130,12 +130,12 @@ static void vb2_dc_put(void *buf_priv)
kfree(buf->sgt_base);
}
dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr,
- &buf->attrs);
+ buf->attrs);
put_device(buf->dev);
kfree(buf);
}
-static void *vb2_dc_alloc(struct device *dev, const struct dma_attrs *attrs,
+static void *vb2_dc_alloc(struct device *dev, unsigned long attrs,
unsigned long size, enum dma_data_direction dma_dir,
gfp_t gfp_flags)
{
@@ -146,16 +146,16 @@ static void *vb2_dc_alloc(struct device *dev, const struct dma_attrs *attrs,
return ERR_PTR(-ENOMEM);
if (attrs)
- buf->attrs = *attrs;
+ buf->attrs = attrs;
buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr,
- GFP_KERNEL | gfp_flags, &buf->attrs);
+ GFP_KERNEL | gfp_flags, buf->attrs);
if (!buf->cookie) {
dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
kfree(buf);
return ERR_PTR(-ENOMEM);
}
- if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->attrs))
+ if ((buf->attrs & DMA_ATTR_NO_KERNEL_MAPPING) == 0)
buf->vaddr = buf->cookie;
/* Prevent the device from being released while the buffer is used */
@@ -189,7 +189,7 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
vma->vm_pgoff = 0;
ret = dma_mmap_attrs(buf->dev, vma, buf->cookie,
- buf->dma_addr, buf->size, &buf->attrs);
+ buf->dma_addr, buf->size, buf->attrs);
if (ret) {
pr_err("Remapping memory failed, error: %d\n", ret);
@@ -372,7 +372,7 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf)
}
ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr,
- buf->size, &buf->attrs);
+ buf->size, buf->attrs);
if (ret < 0) {
dev_err(buf->dev, "failed to get scatterlist from DMA API\n");
kfree(sgt);
@@ -421,15 +421,12 @@ static void vb2_dc_put_userptr(void *buf_priv)
struct page **pages;
if (sgt) {
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
/*
* No need to sync to CPU, it's already synced to the CPU
* since the finish() memop will have been called before this.
*/
dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
pages = frame_vector_pages(buf->vec);
/* sgt should exist only if vector contains pages... */
BUG_ON(IS_ERR(pages));
@@ -484,9 +481,6 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
struct sg_table *sgt;
unsigned long contig_size;
unsigned long dma_align = dma_get_cache_alignment();
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
/* Only cache aligned DMA transfers are reliable */
if (!IS_ALIGNED(vaddr | size, dma_align)) {
@@ -548,7 +542,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
* prepare() memop is called.
*/
sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
if (sgt->nents <= 0) {
pr_err("failed to map scatterlist\n");
ret = -EIO;
@@ -572,7 +566,7 @@ out:
fail_map_sg:
dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
fail_sgt_init:
sg_free_table(sgt);
@@ -749,7 +743,7 @@ EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
int vb2_dma_contig_set_max_seg_size(struct device *dev, unsigned int size)
{
if (!dev->dma_parms) {
- dev->dma_parms = kzalloc(sizeof(dev->dma_parms), GFP_KERNEL);
+ dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
if (!dev->dma_parms)
return -ENOMEM;
}
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index a39db8a6db7a..bd82d709ee82 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -95,7 +95,7 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
return 0;
}
-static void *vb2_dma_sg_alloc(struct device *dev, const struct dma_attrs *dma_attrs,
+static void *vb2_dma_sg_alloc(struct device *dev, unsigned long dma_attrs,
unsigned long size, enum dma_data_direction dma_dir,
gfp_t gfp_flags)
{
@@ -103,9 +103,6 @@ static void *vb2_dma_sg_alloc(struct device *dev, const struct dma_attrs *dma_at
struct sg_table *sgt;
int ret;
int num_pages;
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
if (WARN_ON(dev == NULL))
return NULL;
@@ -144,7 +141,7 @@ static void *vb2_dma_sg_alloc(struct device *dev, const struct dma_attrs *dma_at
* prepare() memop is called.
*/
sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
if (!sgt->nents)
goto fail_map;
@@ -179,13 +176,10 @@ static void vb2_dma_sg_put(void *buf_priv)
int i = buf->num_pages;
if (atomic_dec_and_test(&buf->refcount)) {
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
buf->num_pages);
dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
if (buf->vaddr)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
@@ -228,10 +222,8 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr,
{
struct vb2_dma_sg_buf *buf;
struct sg_table *sgt;
- DEFINE_DMA_ATTRS(attrs);
struct frame_vector *vec;
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
return NULL;
@@ -262,7 +254,7 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr,
* prepare() memop is called.
*/
sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ buf->dma_dir, DMA_ATTR_SKIP_CPU_SYNC);
if (!sgt->nents)
goto userptr_fail_map;
@@ -286,14 +278,11 @@ static void vb2_dma_sg_put_userptr(void *buf_priv)
struct vb2_dma_sg_buf *buf = buf_priv;
struct sg_table *sgt = &buf->sg_table;
int i = buf->num_pages;
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
__func__, buf->num_pages);
dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir,
- &attrs);
+ DMA_ATTR_SKIP_CPU_SYNC);
if (buf->vaddr)
vm_unmap_ram(buf->vaddr, buf->num_pages);
sg_free_table(buf->dma_sgt);
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 7e8a07ed8d82..c2820a6e164d 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -33,7 +33,7 @@ struct vb2_vmalloc_buf {
static void vb2_vmalloc_put(void *buf_priv);
-static void *vb2_vmalloc_alloc(struct device *dev, const struct dma_attrs *attrs,
+static void *vb2_vmalloc_alloc(struct device *dev, unsigned long attrs,
unsigned long size, enum dma_data_direction dma_dir,
gfp_t gfp_flags)
{
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 4387ccb79e64..7410c6d9a34d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -69,5 +69,6 @@ OBJCOPYFLAGS :=
OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \
--set-section-flags .text=alloc,readonly \
--rename-section .text=.rodata
-$(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o
+targets += lkdtm_rodata.o lkdtm_rodata_objcopy.o
+$(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE
$(call if_changed,objcopy)
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c
index bdee9a01ef35..c466ee2b0c97 100644
--- a/drivers/misc/cxl/context.c
+++ b/drivers/misc/cxl/context.c
@@ -90,8 +90,7 @@ int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
*/
mutex_lock(&afu->contexts_lock);
idr_preload(GFP_KERNEL);
- i = idr_alloc(&ctx->afu->contexts_idr, ctx,
- ctx->afu->adapter->native->sl_ops->min_pe,
+ i = idr_alloc(&ctx->afu->contexts_idr, ctx, ctx->afu->adapter->min_pe,
ctx->afu->num_procs, GFP_NOWAIT);
idr_preload_end();
mutex_unlock(&afu->contexts_lock);
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index de090533f18c..344a0ff8f8c7 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -561,7 +561,6 @@ struct cxl_service_layer_ops {
u64 (*timebase_read)(struct cxl *adapter);
int capi_mode;
bool needs_reset_before_disable;
- int min_pe;
};
struct cxl_native {
@@ -603,6 +602,7 @@ struct cxl {
struct bin_attribute cxl_attr;
int adapter_num;
int user_irqs;
+ int min_pe;
u64 ps_size;
u16 psl_rev;
u16 base_image;
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 3bcdaee11ba1..e606fdc4bc9c 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -924,7 +924,7 @@ static irqreturn_t native_irq_multiplexed(int irq, void *data)
return fail_psl_irq(afu, &irq_info);
}
-void native_irq_wait(struct cxl_context *ctx)
+static void native_irq_wait(struct cxl_context *ctx)
{
u64 dsisr;
int timeout = 1000;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index d152e2de8c93..6f0c4ac4b649 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -379,7 +379,7 @@ static int calc_capp_routing(struct pci_dev *dev, u64 *chipid, u64 *capp_unit_id
static int init_implementation_adapter_psl_regs(struct cxl *adapter, struct pci_dev *dev)
{
- u64 psl_dsnctl;
+ u64 psl_dsnctl, psl_fircntl;
u64 chipid;
u64 capp_unit_id;
int rc;
@@ -398,8 +398,11 @@ static int init_implementation_adapter_psl_regs(struct cxl *adapter, struct pci_
cxl_p1_write(adapter, CXL_PSL_RESLCKTO, 0x20000000200ULL);
/* snoop write mask */
cxl_p1_write(adapter, CXL_PSL_SNWRALLOC, 0x00000000FFFFFFFFULL);
- /* set fir_accum */
- cxl_p1_write(adapter, CXL_PSL_FIR_CNTL, 0x0800000000000000ULL);
+ /* set fir_cntl to recommended value for production env */
+ psl_fircntl = (0x2ULL << (63-3)); /* ce_report */
+ psl_fircntl |= (0x1ULL << (63-6)); /* FIR_report */
+ psl_fircntl |= 0x1ULL; /* ce_thresh */
+ cxl_p1_write(adapter, CXL_PSL_FIR_CNTL, psl_fircntl);
/* for debugging with trace arrays */
cxl_p1_write(adapter, CXL_PSL_TRACE, 0x0000FF7C00000000ULL);
@@ -1521,14 +1524,15 @@ static const struct cxl_service_layer_ops xsl_ops = {
.write_timebase_ctrl = write_timebase_ctrl_xsl,
.timebase_read = timebase_read_xsl,
.capi_mode = OPAL_PHB_CAPI_MODE_DMA,
- .min_pe = 1, /* Workaround for Mellanox CX4 HW bug */
};
static void set_sl_ops(struct cxl *adapter, struct pci_dev *dev)
{
if (dev->vendor == PCI_VENDOR_ID_MELLANOX && dev->device == 0x1013) {
+ /* Mellanox CX-4 */
dev_info(&adapter->dev, "Device uses an XSL\n");
adapter->native->sl_ops = &xsl_ops;
+ adapter->min_pe = 1; /* Workaround for CX-4 hardware bug */
} else {
dev_info(&adapter->dev, "Device uses a PSL\n");
adapter->native->sl_ops = &psl_ops;
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c
index dee8def1c193..7ada5f1b7bb6 100644
--- a/drivers/misc/cxl/vphb.c
+++ b/drivers/misc/cxl/vphb.c
@@ -221,7 +221,7 @@ int cxl_pci_vphb_add(struct cxl_afu *afu)
/* Setup the PHB using arch provided callback */
phb->ops = &cxl_pcie_pci_ops;
phb->cfg_addr = NULL;
- phb->cfg_data = 0;
+ phb->cfg_data = NULL;
phb->private_data = afu;
phb->controller_ops = cxl_pci_controller_ops;
diff --git a/drivers/misc/lkdtm_usercopy.c b/drivers/misc/lkdtm_usercopy.c
index 5a3fd76eec27..5525a204db93 100644
--- a/drivers/misc/lkdtm_usercopy.c
+++ b/drivers/misc/lkdtm_usercopy.c
@@ -49,7 +49,7 @@ static noinline void do_usercopy_stack(bool to_user, bool bad_frame)
/* This is a pointer to outside our current stack frame. */
if (bad_frame) {
- bad_stack = do_usercopy_stack_callee((uintptr_t)bad_stack);
+ bad_stack = do_usercopy_stack_callee((uintptr_t)&bad_stack);
} else {
/* Put start address just inside stack. */
bad_stack = task_stack_page(current) + THREAD_SIZE;
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index 89e5917e1c33..6fd9d367dea7 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -146,3 +146,7 @@ config VOP
More information about the Intel MIC family as well as the Linux
OS and tools for MIC to use with this driver are available from
<http://software.intel.com/en-us/mic-developer>.
+
+if VOP
+source "drivers/vhost/Kconfig.vringh"
+endif
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index e047efd83f57..9599d732aff3 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -38,7 +38,7 @@ static inline struct mic_device *vpdev_to_mdev(struct device *dev)
static dma_addr_t
_mic_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
void *va = phys_to_virt(page_to_phys(page)) + offset;
struct mic_device *mdev = vpdev_to_mdev(dev);
@@ -48,7 +48,7 @@ _mic_dma_map_page(struct device *dev, struct page *page,
static void _mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct mic_device *mdev = vpdev_to_mdev(dev);
@@ -144,7 +144,7 @@ static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
static void *__mic_dma_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
struct mic_device *mdev = scdev_to_mdev(scdev);
@@ -164,7 +164,7 @@ static void *__mic_dma_alloc(struct device *dev, size_t size,
}
static void __mic_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
struct mic_device *mdev = scdev_to_mdev(scdev);
@@ -176,7 +176,7 @@ static void __mic_dma_free(struct device *dev, size_t size, void *vaddr,
static dma_addr_t
__mic_dma_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *va = phys_to_virt(page_to_phys(page)) + offset;
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
@@ -188,7 +188,7 @@ __mic_dma_map_page(struct device *dev, struct page *page, unsigned long offset,
static void
__mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
struct mic_device *mdev = scdev_to_mdev(scdev);
@@ -198,7 +198,7 @@ __mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
static int __mic_dma_map_sg(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
struct mic_device *mdev = scdev_to_mdev(scdev);
@@ -229,7 +229,7 @@ err:
static void __mic_dma_unmap_sg(struct device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scif_hw_dev *scdev = dev_get_drvdata(dev);
struct mic_device *mdev = scdev_to_mdev(scdev);
@@ -327,7 +327,7 @@ static inline struct mic_device *mbdev_to_mdev(struct mbus_device *mbdev)
static dma_addr_t
mic_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *va = phys_to_virt(page_to_phys(page)) + offset;
struct mic_device *mdev = dev_get_drvdata(dev->parent);
@@ -338,7 +338,7 @@ mic_dma_map_page(struct device *dev, struct page *page,
static void
mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct mic_device *mdev = dev_get_drvdata(dev->parent);
mic_unmap_single(mdev, dma_addr, size);
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index 845dd27d9f41..377947580203 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -122,7 +122,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
for (offset = 0; offset <= master->size - blocksize;
offset += blocksize) {
/* Nothing more in higher memory on BCM47XX (MIPS) */
- if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000)
+ if (IS_ENABLED(CONFIG_BCM47XX) && offset >= 0x2000000)
break;
if (curr_part >= BCM47XXPART_MAX_PARTS) {
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index c1aaf0336cf2..903becd31410 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -175,6 +175,40 @@ static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec)
}
/**
+ * add_fastmap - add a Fastmap related physical eraseblock.
+ * @ai: attaching information
+ * @pnum: physical eraseblock number the VID header came from
+ * @vid_hdr: the volume identifier header
+ * @ec: erase counter of the physical eraseblock
+ *
+ * This function allocates a 'struct ubi_ainf_peb' object for a Fastamp
+ * physical eraseblock @pnum and adds it to the 'fastmap' list.
+ * Such blocks can be Fastmap super and data blocks from both the most
+ * recent Fastmap we're attaching from or from old Fastmaps which will
+ * be erased.
+ */
+static int add_fastmap(struct ubi_attach_info *ai, int pnum,
+ struct ubi_vid_hdr *vid_hdr, int ec)
+{
+ struct ubi_ainf_peb *aeb;
+
+ aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
+ if (!aeb)
+ return -ENOMEM;
+
+ aeb->pnum = pnum;
+ aeb->vol_id = be32_to_cpu(vidh->vol_id);
+ aeb->sqnum = be64_to_cpu(vidh->sqnum);
+ aeb->ec = ec;
+ list_add(&aeb->u.list, &ai->fastmap);
+
+ dbg_bld("add to fastmap list: PEB %d, vol_id %d, sqnum: %llu", pnum,
+ aeb->vol_id, aeb->sqnum);
+
+ return 0;
+}
+
+/**
* validate_vid_hdr - check volume identifier header.
* @ubi: UBI device description object
* @vid_hdr: the volume identifier header to check
@@ -803,13 +837,26 @@ out_unlock:
return err;
}
+static bool vol_ignored(int vol_id)
+{
+ switch (vol_id) {
+ case UBI_LAYOUT_VOLUME_ID:
+ return true;
+ }
+
+#ifdef CONFIG_MTD_UBI_FASTMAP
+ return ubi_is_fm_vol(vol_id);
+#else
+ return false;
+#endif
+}
+
/**
* scan_peb - scan and process UBI headers of a PEB.
* @ubi: UBI device description object
* @ai: attaching information
* @pnum: the physical eraseblock number
- * @vid: The volume ID of the found volume will be stored in this pointer
- * @sqnum: The sqnum of the found volume will be stored in this pointer
+ * @fast: true if we're scanning for a Fastmap
*
* This function reads UBI headers of PEB @pnum, checks them, and adds
* information about this PEB to the corresponding list or RB-tree in the
@@ -817,9 +864,9 @@ out_unlock:
* successfully handled and a negative error code in case of failure.
*/
static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
- int pnum, int *vid, unsigned long long *sqnum)
+ int pnum, bool fast)
{
- long long uninitialized_var(ec);
+ long long ec;
int err, bitflips = 0, vol_id = -1, ec_err = 0;
dbg_bld("scan PEB %d", pnum);
@@ -935,6 +982,20 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
*/
ai->maybe_bad_peb_count += 1;
case UBI_IO_BAD_HDR:
+ /*
+ * If we're facing a bad VID header we have to drop *all*
+ * Fastmap data structures we find. The most recent Fastmap
+ * could be bad and therefore there is a chance that we attach
+ * from an old one. On a fine MTD stack a PEB must not render
+ * bad all of a sudden, but the reality is different.
+ * So, let's be paranoid and help finding the root cause by
+ * falling back to scanning mode instead of attaching with a
+ * bad EBA table and cause data corruption which is hard to
+ * analyze.
+ */
+ if (fast)
+ ai->force_full_scan = 1;
+
if (ec_err)
/*
* Both headers are corrupted. There is a possibility
@@ -991,21 +1052,15 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
}
vol_id = be32_to_cpu(vidh->vol_id);
- if (vid)
- *vid = vol_id;
- if (sqnum)
- *sqnum = be64_to_cpu(vidh->sqnum);
- if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) {
+ if (vol_id > UBI_MAX_VOLUMES && !vol_ignored(vol_id)) {
int lnum = be32_to_cpu(vidh->lnum);
/* Unsupported internal volume */
switch (vidh->compat) {
case UBI_COMPAT_DELETE:
- if (vol_id != UBI_FM_SB_VOLUME_ID
- && vol_id != UBI_FM_DATA_VOLUME_ID) {
- ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it",
- vol_id, lnum);
- }
+ ubi_msg(ubi, "\"delete\" compatible internal volume %d:%d found, will remove it",
+ vol_id, lnum);
+
err = add_to_list(ai, pnum, vol_id, lnum,
ec, 1, &ai->erase);
if (err)
@@ -1037,7 +1092,12 @@ static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
if (ec_err)
ubi_warn(ubi, "valid VID header but corrupted EC header at PEB %d",
pnum);
- err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
+
+ if (ubi_is_fm_vol(vol_id))
+ err = add_fastmap(ai, pnum, vidh, ec);
+ else
+ err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips);
+
if (err)
return err;
@@ -1186,6 +1246,10 @@ static void destroy_ai(struct ubi_attach_info *ai)
list_del(&aeb->u.list);
kmem_cache_free(ai->aeb_slab_cache, aeb);
}
+ list_for_each_entry_safe(aeb, aeb_tmp, &ai->fastmap, u.list) {
+ list_del(&aeb->u.list);
+ kmem_cache_free(ai->aeb_slab_cache, aeb);
+ }
/* Destroy the volume RB-tree */
rb = ai->volumes.rb_node;
@@ -1245,7 +1309,7 @@ static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
cond_resched();
dbg_gen("process PEB %d", pnum);
- err = scan_peb(ubi, ai, pnum, NULL, NULL);
+ err = scan_peb(ubi, ai, pnum, false);
if (err < 0)
goto out_vidh;
}
@@ -1311,6 +1375,7 @@ static struct ubi_attach_info *alloc_ai(void)
INIT_LIST_HEAD(&ai->free);
INIT_LIST_HEAD(&ai->erase);
INIT_LIST_HEAD(&ai->alien);
+ INIT_LIST_HEAD(&ai->fastmap);
ai->volumes = RB_ROOT;
ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
sizeof(struct ubi_ainf_peb),
@@ -1326,7 +1391,7 @@ static struct ubi_attach_info *alloc_ai(void)
#ifdef CONFIG_MTD_UBI_FASTMAP
/**
- * scan_fastmap - try to find a fastmap and attach from it.
+ * scan_fast - try to find a fastmap and attach from it.
* @ubi: UBI device description object
* @ai: attach info object
*
@@ -1337,52 +1402,58 @@ static struct ubi_attach_info *alloc_ai(void)
*/
static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
{
- int err, pnum, fm_anchor = -1;
- unsigned long long max_sqnum = 0;
+ int err, pnum;
+ struct ubi_attach_info *scan_ai;
err = -ENOMEM;
+ scan_ai = alloc_ai();
+ if (!scan_ai)
+ goto out;
+
ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ech)
- goto out;
+ goto out_ai;
vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh)
goto out_ech;
for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) {
- int vol_id = -1;
- unsigned long long sqnum = -1;
cond_resched();
dbg_gen("process PEB %d", pnum);
- err = scan_peb(ubi, *ai, pnum, &vol_id, &sqnum);
+ err = scan_peb(ubi, scan_ai, pnum, true);
if (err < 0)
goto out_vidh;
-
- if (vol_id == UBI_FM_SB_VOLUME_ID && sqnum > max_sqnum) {
- max_sqnum = sqnum;
- fm_anchor = pnum;
- }
}
ubi_free_vid_hdr(ubi, vidh);
kfree(ech);
- if (fm_anchor < 0)
- return UBI_NO_FASTMAP;
+ if (scan_ai->force_full_scan)
+ err = UBI_NO_FASTMAP;
+ else
+ err = ubi_scan_fastmap(ubi, *ai, scan_ai);
- destroy_ai(*ai);
- *ai = alloc_ai();
- if (!*ai)
- return -ENOMEM;
+ if (err) {
+ /*
+ * Didn't attach via fastmap, do a full scan but reuse what
+ * we've aready scanned.
+ */
+ destroy_ai(*ai);
+ *ai = scan_ai;
+ } else
+ destroy_ai(scan_ai);
- return ubi_scan_fastmap(ubi, *ai, fm_anchor);
+ return err;
out_vidh:
ubi_free_vid_hdr(ubi, vidh);
out_ech:
kfree(ech);
+out_ai:
+ destroy_ai(scan_ai);
out:
return err;
}
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index ef3618299494..0680516bb472 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -874,7 +874,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && mtd->index == ubi->mtd->index) {
- ubi_err(ubi, "mtd%d is already attached to ubi%d",
+ pr_err("ubi: mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
}
@@ -889,7 +889,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
* no sense to attach emulated MTD devices, so we prohibit this.
*/
if (mtd->type == MTD_UBIVOLUME) {
- ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI",
+ pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI",
mtd->index);
return -EINVAL;
}
@@ -900,7 +900,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
if (!ubi_devices[ubi_num])
break;
if (ubi_num == UBI_MAX_DEVICES) {
- ubi_err(ubi, "only %d UBI devices may be created",
+ pr_err("ubi: only %d UBI devices may be created",
UBI_MAX_DEVICES);
return -ENFILE;
}
@@ -910,7 +910,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
/* Make sure ubi_num is not busy */
if (ubi_devices[ubi_num]) {
- ubi_err(ubi, "already exists");
+ pr_err("ubi: ubi%i already exists", ubi_num);
return -EEXIST;
}
}
@@ -992,6 +992,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
goto out_detach;
}
+ /* Make device "available" before it becomes accessible via sysfs */
+ ubi_devices[ubi_num] = ubi;
+
err = uif_init(ubi, &ref);
if (err)
goto out_detach;
@@ -1036,7 +1039,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
wake_up_process(ubi->bgt_thread);
spin_unlock(&ubi->wl_lock);
- ubi_devices[ubi_num] = ubi;
ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
return ubi_num;
@@ -1047,6 +1049,7 @@ out_uif:
ubi_assert(ref);
uif_close(ubi);
out_detach:
+ ubi_devices[ubi_num] = NULL;
ubi_wl_close(ubi);
ubi_free_internal_volumes(ubi);
vfree(ubi->vtbl);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 990898b9dc72..48eb55f344eb 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -15,20 +15,22 @@
*/
#include <linux/crc32.h>
+#include <linux/bitmap.h>
#include "ubi.h"
/**
* init_seen - allocate memory for used for debugging.
* @ubi: UBI device description object
*/
-static inline int *init_seen(struct ubi_device *ubi)
+static inline unsigned long *init_seen(struct ubi_device *ubi)
{
- int *ret;
+ unsigned long *ret;
if (!ubi_dbg_chk_fastmap(ubi))
return NULL;
- ret = kcalloc(ubi->peb_count, sizeof(int), GFP_KERNEL);
+ ret = kcalloc(BITS_TO_LONGS(ubi->peb_count), sizeof(unsigned long),
+ GFP_KERNEL);
if (!ret)
return ERR_PTR(-ENOMEM);
@@ -39,7 +41,7 @@ static inline int *init_seen(struct ubi_device *ubi)
* free_seen - free the seen logic integer array.
* @seen: integer array of @ubi->peb_count size
*/
-static inline void free_seen(int *seen)
+static inline void free_seen(unsigned long *seen)
{
kfree(seen);
}
@@ -50,12 +52,12 @@ static inline void free_seen(int *seen)
* @pnum: The PEB to be makred as seen
* @seen: integer array of @ubi->peb_count size
*/
-static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
+static inline void set_seen(struct ubi_device *ubi, int pnum, unsigned long *seen)
{
if (!ubi_dbg_chk_fastmap(ubi) || !seen)
return;
- seen[pnum] = 1;
+ set_bit(pnum, seen);
}
/**
@@ -63,7 +65,7 @@ static inline void set_seen(struct ubi_device *ubi, int pnum, int *seen)
* @ubi: UBI device description object
* @seen: integer array of @ubi->peb_count size
*/
-static int self_check_seen(struct ubi_device *ubi, int *seen)
+static int self_check_seen(struct ubi_device *ubi, unsigned long *seen)
{
int pnum, ret = 0;
@@ -71,7 +73,7 @@ static int self_check_seen(struct ubi_device *ubi, int *seen)
return 0;
for (pnum = 0; pnum < ubi->peb_count; pnum++) {
- if (!seen[pnum] && ubi->lookuptbl[pnum]) {
+ if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
ret = -EINVAL;
}
@@ -578,7 +580,7 @@ static int count_fastmap_pebs(struct ubi_attach_info *ai)
list_for_each_entry(aeb, &ai->free, u.list)
n++;
- ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
+ ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb)
ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
n++;
@@ -850,27 +852,57 @@ fail:
}
/**
+ * find_fm_anchor - find the most recent Fastmap superblock (anchor)
+ * @ai: UBI attach info to be filled
+ */
+static int find_fm_anchor(struct ubi_attach_info *ai)
+{
+ int ret = -1;
+ struct ubi_ainf_peb *aeb;
+ unsigned long long max_sqnum = 0;
+
+ list_for_each_entry(aeb, &ai->fastmap, u.list) {
+ if (aeb->vol_id == UBI_FM_SB_VOLUME_ID && aeb->sqnum > max_sqnum) {
+ max_sqnum = aeb->sqnum;
+ ret = aeb->pnum;
+ }
+ }
+
+ return ret;
+}
+
+/**
* ubi_scan_fastmap - scan the fastmap.
* @ubi: UBI device object
* @ai: UBI attach info to be filled
- * @fm_anchor: The fastmap starts at this PEB
+ * @scan_ai: UBI attach info from the first 64 PEBs,
+ * used to find the most recent Fastmap data structure
*
* Returns 0 on success, UBI_NO_FASTMAP if no fastmap was found,
* UBI_BAD_FASTMAP if one was found but is not usable.
* < 0 indicates an internal error.
*/
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
- int fm_anchor)
+ struct ubi_attach_info *scan_ai)
{
struct ubi_fm_sb *fmsb, *fmsb2;
struct ubi_vid_hdr *vh;
struct ubi_ec_hdr *ech;
struct ubi_fastmap_layout *fm;
- int i, used_blocks, pnum, ret = 0;
+ struct ubi_ainf_peb *tmp_aeb, *aeb;
+ int i, used_blocks, pnum, fm_anchor, ret = 0;
size_t fm_size;
__be32 crc, tmp_crc;
unsigned long long sqnum = 0;
+ fm_anchor = find_fm_anchor(scan_ai);
+ if (fm_anchor < 0)
+ return UBI_NO_FASTMAP;
+
+ /* Move all (possible) fastmap blocks into our new attach structure. */
+ list_for_each_entry_safe(aeb, tmp_aeb, &scan_ai->fastmap, u.list)
+ list_move_tail(&aeb->u.list, &ai->fastmap);
+
down_write(&ubi->fm_protect);
memset(ubi->fm_buf, 0, ubi->fm_size);
@@ -945,6 +977,13 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
goto free_hdr;
}
+ if (i == 0 && pnum != fm_anchor) {
+ ubi_err(ubi, "Fastmap anchor PEB mismatch: PEB: %i vs. %i",
+ pnum, fm_anchor);
+ ret = UBI_BAD_FASTMAP;
+ goto free_hdr;
+ }
+
ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
if (ret && ret != UBI_IO_BITFLIPS) {
ubi_err(ubi, "unable to read fastmap block# %i EC (PEB: %i)",
@@ -1102,7 +1141,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct rb_node *tmp_rb;
int ret, i, j, free_peb_count, used_peb_count, vol_count;
int scrub_peb_count, erase_peb_count;
- int *seen_pebs = NULL;
+ unsigned long *seen_pebs = NULL;
fm_raw = ubi->fm_buf;
memset(ubi->fm_buf, 0, ubi->fm_size);
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c
index cb7c075f2144..1cb287ec32ad 100644
--- a/drivers/mtd/ubi/gluebi.c
+++ b/drivers/mtd/ubi/gluebi.c
@@ -99,9 +99,6 @@ static int gluebi_get_device(struct mtd_info *mtd)
struct gluebi_device *gluebi;
int ubi_mode = UBI_READONLY;
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
if (mtd->flags & MTD_WRITEABLE)
ubi_mode = UBI_READWRITE;
@@ -129,7 +126,6 @@ static int gluebi_get_device(struct mtd_info *mtd)
ubi_mode);
if (IS_ERR(gluebi->desc)) {
mutex_unlock(&devices_mutex);
- module_put(THIS_MODULE);
return PTR_ERR(gluebi->desc);
}
gluebi->refcnt += 1;
@@ -153,7 +149,6 @@ static void gluebi_put_device(struct mtd_info *mtd)
gluebi->refcnt -= 1;
if (gluebi->refcnt == 0)
ubi_close_volume(gluebi->desc);
- module_put(THIS_MODULE);
mutex_unlock(&devices_mutex);
}
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 10cf3b549959..ff8cafe1e5cd 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -1019,7 +1019,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
p = (char *)vid_hdr - ubi->vid_hdr_shift;
read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
- ubi->vid_hdr_alsize);
+ ubi->vid_hdr_shift + UBI_VID_HDR_SIZE);
if (read_err && read_err != UBI_IO_BITFLIPS && !mtd_is_eccerr(read_err))
return read_err;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 61d4e99755a4..b616a115c9d3 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -703,6 +703,8 @@ struct ubi_ainf_volume {
* @erase: list of physical eraseblocks which have to be erased
* @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
* those belonging to "preserve"-compatible internal volumes)
+ * @fastmap: list of physical eraseblocks which relate to fastmap (e.g.,
+ * eraseblocks of the current and not yet erased old fastmap blocks)
* @corr_peb_count: count of PEBs in the @corr list
* @empty_peb_count: count of PEBs which are presumably empty (contain only
* 0xFF bytes)
@@ -713,6 +715,8 @@ struct ubi_ainf_volume {
* @vols_found: number of volumes found
* @highest_vol_id: highest volume ID
* @is_empty: flag indicating whether the MTD device is empty or not
+ * @force_full_scan: flag indicating whether we need to do a full scan and drop
+ all existing Fastmap data structures
* @min_ec: lowest erase counter value
* @max_ec: highest erase counter value
* @max_sqnum: highest sequence number value
@@ -731,6 +735,7 @@ struct ubi_attach_info {
struct list_head free;
struct list_head erase;
struct list_head alien;
+ struct list_head fastmap;
int corr_peb_count;
int empty_peb_count;
int alien_peb_count;
@@ -739,6 +744,7 @@ struct ubi_attach_info {
int vols_found;
int highest_vol_id;
int is_empty;
+ int force_full_scan;
int min_ec;
int max_ec;
unsigned long long max_sqnum;
@@ -911,7 +917,7 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb,
size_t ubi_calc_fm_size(struct ubi_device *ubi);
int ubi_update_fastmap(struct ubi_device *ubi);
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
- int fm_anchor);
+ struct ubi_attach_info *scan_ai);
#else
static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
#endif
@@ -1105,4 +1111,42 @@ static inline int idx2vol_id(const struct ubi_device *ubi, int idx)
return idx;
}
+/**
+ * ubi_is_fm_vol - check whether a volume ID is a Fastmap volume.
+ * @vol_id: volume ID
+ */
+static inline bool ubi_is_fm_vol(int vol_id)
+{
+ switch (vol_id) {
+ case UBI_FM_SB_VOLUME_ID:
+ case UBI_FM_DATA_VOLUME_ID:
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * ubi_find_fm_block - check whether a PEB is part of the current Fastmap.
+ * @ubi: UBI device description object
+ * @pnum: physical eraseblock to look for
+ *
+ * This function returns a wear leveling object if @pnum relates to the current
+ * fastmap, @NULL otherwise.
+ */
+static inline struct ubi_wl_entry *ubi_find_fm_block(const struct ubi_device *ubi,
+ int pnum)
+{
+ int i;
+
+ if (ubi->fm) {
+ for (i = 0; i < ubi->fm->used_blocks; i++) {
+ if (ubi->fm->e[i]->pnum == pnum)
+ return ubi->fm->e[i];
+ }
+ }
+
+ return NULL;
+}
+
#endif /* !__UBI_UBI_H__ */
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 10059dfdc1b6..0138f526474a 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -488,13 +488,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
spin_unlock(&ubi->volumes_lock);
}
- /* Change volume table record */
- vtbl_rec = ubi->vtbl[vol_id];
- vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
- err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
- if (err)
- goto out_acc;
-
if (pebs < 0) {
for (i = 0; i < -pebs; i++) {
err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);
@@ -512,6 +505,24 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
spin_unlock(&ubi->volumes_lock);
}
+ /*
+ * When we shrink a volume we have to flush all pending (erase) work.
+ * Otherwise it can happen that upon next attach UBI finds a LEB with
+ * lnum > highest_lnum and refuses to attach.
+ */
+ if (pebs < 0) {
+ err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
+ if (err)
+ goto out_acc;
+ }
+
+ /* Change volume table record */
+ vtbl_rec = ubi->vtbl[vol_id];
+ vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
+ err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
+ if (err)
+ goto out_acc;
+
vol->reserved_pebs = reserved_pebs;
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
vol->used_ebs = reserved_pebs;
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 959c7b12e0b1..f4533266d7b2 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1598,19 +1598,44 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
}
}
- dbg_wl("found %i PEBs", found_pebs);
+ list_for_each_entry(aeb, &ai->fastmap, u.list) {
+ cond_resched();
+
+ e = ubi_find_fm_block(ubi, aeb->pnum);
- if (ubi->fm) {
- ubi_assert(ubi->good_peb_count ==
- found_pebs + ubi->fm->used_blocks);
+ if (e) {
+ ubi_assert(!ubi->lookuptbl[e->pnum]);
+ ubi->lookuptbl[e->pnum] = e;
+ } else {
+ /*
+ * Usually old Fastmap PEBs are scheduled for erasure
+ * and we don't have to care about them but if we face
+ * an power cut before scheduling them we need to
+ * take care of them here.
+ */
+ if (ubi->lookuptbl[aeb->pnum])
+ continue;
+
+ e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
+ if (!e)
+ goto out_free;
- for (i = 0; i < ubi->fm->used_blocks; i++) {
- e = ubi->fm->e[i];
+ e->pnum = aeb->pnum;
+ e->ec = aeb->ec;
+ ubi_assert(!ubi->lookuptbl[e->pnum]);
ubi->lookuptbl[e->pnum] = e;
+ if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) {
+ wl_entry_destroy(ubi, e);
+ goto out_free;
+ }
}
+
+ found_pebs++;
}
- else
- ubi_assert(ubi->good_peb_count == found_pebs);
+
+ dbg_wl("found %i PEBs", found_pebs);
+
+ ubi_assert(ubi->good_peb_count == found_pebs);
reserved_pebs = WL_RESERVED_PEBS;
ubi_fastmap_init(ubi, &reserved_pebs);
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig
index 547098086773..f81df91a9ce1 100644
--- a/drivers/net/caif/Kconfig
+++ b/drivers/net/caif/Kconfig
@@ -52,5 +52,5 @@ config CAIF_VIRTIO
The caif driver for CAIF over Virtio.
if CAIF_VIRTIO
-source "drivers/vhost/Kconfig"
+source "drivers/vhost/Kconfig.vringh"
endif
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index 4705e2dea423..e0ebe1378cb2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -104,6 +104,8 @@ enum {
enum CPL_error {
CPL_ERR_NONE = 0,
+ CPL_ERR_TCAM_PARITY = 1,
+ CPL_ERR_TCAM_MISS = 2,
CPL_ERR_TCAM_FULL = 3,
CPL_ERR_BAD_LENGTH = 15,
CPL_ERR_BAD_ROUTE = 18,
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index f4497cf4d06d..d728704d0c7b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -721,6 +721,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
#define QUERY_DEV_CAP_ETH_BACKPL_OFFSET 0x9c
+#define QUERY_DEV_CAP_DIAG_RPRT_PER_PORT 0x9c
#define QUERY_DEV_CAP_FW_REASSIGN_MAC 0x9d
#define QUERY_DEV_CAP_VXLAN 0x9e
#define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0
@@ -935,6 +936,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP;
if (field32 & (1 << 7))
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT;
+ MLX4_GET(field32, outbox, QUERY_DEV_CAP_DIAG_RPRT_PER_PORT);
+ if (field32 & (1 << 17))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT;
MLX4_GET(field, outbox, QUERY_DEV_CAP_FW_REASSIGN_MAC);
if (field & 1<<6)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_REASSIGN_MAC_EN;
@@ -2457,6 +2461,42 @@ int mlx4_NOP(struct mlx4_dev *dev)
MLX4_CMD_NATIVE);
}
+int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
+ const u32 offset[],
+ u32 value[], size_t array_len, u8 port)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ u32 *outbox;
+ size_t i;
+ int ret;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ return PTR_ERR(mailbox);
+
+ outbox = mailbox->buf;
+
+ ret = mlx4_cmd_box(dev, 0, mailbox->dma, port, op_modifier,
+ MLX4_CMD_DIAG_RPRT, MLX4_CMD_TIME_CLASS_A,
+ MLX4_CMD_NATIVE);
+ if (ret)
+ goto out;
+
+ for (i = 0; i < array_len; i++) {
+ if (offset[i] > MLX4_MAILBOX_SIZE) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ MLX4_GET(value[i], outbox, offset[i]);
+ }
+
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return ret;
+}
+EXPORT_SYMBOL(mlx4_query_diag_counters);
+
int mlx4_get_phys_port_id(struct mlx4_dev *dev)
{
u8 port;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/srq.c b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
index 04bc522605a0..c07f4d01b70e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/srq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/srq.c
@@ -63,12 +63,12 @@ void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type)
complete(&srq->free);
}
-static int get_pas_size(void *srqc)
+static int get_pas_size(struct mlx5_srq_attr *in)
{
- u32 log_page_size = MLX5_GET(srqc, srqc, log_page_size) + 12;
- u32 log_srq_size = MLX5_GET(srqc, srqc, log_srq_size);
- u32 log_rq_stride = MLX5_GET(srqc, srqc, log_rq_stride);
- u32 page_offset = MLX5_GET(srqc, srqc, page_offset);
+ u32 log_page_size = in->log_page_size + 12;
+ u32 log_srq_size = in->log_size;
+ u32 log_rq_stride = in->wqe_shift;
+ u32 page_offset = in->page_offset;
u32 po_quanta = 1 << (log_page_size - 6);
u32 rq_sz = 1 << (log_srq_size + 4 + log_rq_stride);
u32 page_size = 1 << log_page_size;
@@ -78,57 +78,58 @@ static int get_pas_size(void *srqc)
return rq_num_pas * sizeof(u64);
}
-static void rmpc_srqc_reformat(void *srqc, void *rmpc, bool srqc_to_rmpc)
+static void set_wq(void *wq, struct mlx5_srq_attr *in)
{
- void *wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
-
- if (srqc_to_rmpc) {
- switch (MLX5_GET(srqc, srqc, state)) {
- case MLX5_SRQC_STATE_GOOD:
- MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY);
- break;
- case MLX5_SRQC_STATE_ERROR:
- MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_ERR);
- break;
- default:
- pr_warn("%s: %d: Unknown srq state = 0x%x\n", __func__,
- __LINE__, MLX5_GET(srqc, srqc, state));
- MLX5_SET(rmpc, rmpc, state, MLX5_GET(srqc, srqc, state));
- }
-
- MLX5_SET(wq, wq, wq_signature, MLX5_GET(srqc, srqc, wq_signature));
- MLX5_SET(wq, wq, log_wq_pg_sz, MLX5_GET(srqc, srqc, log_page_size));
- MLX5_SET(wq, wq, log_wq_stride, MLX5_GET(srqc, srqc, log_rq_stride) + 4);
- MLX5_SET(wq, wq, log_wq_sz, MLX5_GET(srqc, srqc, log_srq_size));
- MLX5_SET(wq, wq, page_offset, MLX5_GET(srqc, srqc, page_offset));
- MLX5_SET(wq, wq, lwm, MLX5_GET(srqc, srqc, lwm));
- MLX5_SET(wq, wq, pd, MLX5_GET(srqc, srqc, pd));
- MLX5_SET64(wq, wq, dbr_addr, MLX5_GET64(srqc, srqc, dbr_addr));
- } else {
- switch (MLX5_GET(rmpc, rmpc, state)) {
- case MLX5_RMPC_STATE_RDY:
- MLX5_SET(srqc, srqc, state, MLX5_SRQC_STATE_GOOD);
- break;
- case MLX5_RMPC_STATE_ERR:
- MLX5_SET(srqc, srqc, state, MLX5_SRQC_STATE_ERROR);
- break;
- default:
- pr_warn("%s: %d: Unknown rmp state = 0x%x\n",
- __func__, __LINE__,
- MLX5_GET(rmpc, rmpc, state));
- MLX5_SET(srqc, srqc, state,
- MLX5_GET(rmpc, rmpc, state));
- }
-
- MLX5_SET(srqc, srqc, wq_signature, MLX5_GET(wq, wq, wq_signature));
- MLX5_SET(srqc, srqc, log_page_size, MLX5_GET(wq, wq, log_wq_pg_sz));
- MLX5_SET(srqc, srqc, log_rq_stride, MLX5_GET(wq, wq, log_wq_stride) - 4);
- MLX5_SET(srqc, srqc, log_srq_size, MLX5_GET(wq, wq, log_wq_sz));
- MLX5_SET(srqc, srqc, page_offset, MLX5_GET(wq, wq, page_offset));
- MLX5_SET(srqc, srqc, lwm, MLX5_GET(wq, wq, lwm));
- MLX5_SET(srqc, srqc, pd, MLX5_GET(wq, wq, pd));
- MLX5_SET64(srqc, srqc, dbr_addr, MLX5_GET64(wq, wq, dbr_addr));
- }
+ MLX5_SET(wq, wq, wq_signature, !!(in->flags
+ & MLX5_SRQ_FLAG_WQ_SIG));
+ MLX5_SET(wq, wq, log_wq_pg_sz, in->log_page_size);
+ MLX5_SET(wq, wq, log_wq_stride, in->wqe_shift + 4);
+ MLX5_SET(wq, wq, log_wq_sz, in->log_size);
+ MLX5_SET(wq, wq, page_offset, in->page_offset);
+ MLX5_SET(wq, wq, lwm, in->lwm);
+ MLX5_SET(wq, wq, pd, in->pd);
+ MLX5_SET64(wq, wq, dbr_addr, in->db_record);
+}
+
+static void set_srqc(void *srqc, struct mlx5_srq_attr *in)
+{
+ MLX5_SET(srqc, srqc, wq_signature, !!(in->flags
+ & MLX5_SRQ_FLAG_WQ_SIG));
+ MLX5_SET(srqc, srqc, log_page_size, in->log_page_size);
+ MLX5_SET(srqc, srqc, log_rq_stride, in->wqe_shift);
+ MLX5_SET(srqc, srqc, log_srq_size, in->log_size);
+ MLX5_SET(srqc, srqc, page_offset, in->page_offset);
+ MLX5_SET(srqc, srqc, lwm, in->lwm);
+ MLX5_SET(srqc, srqc, pd, in->pd);
+ MLX5_SET64(srqc, srqc, dbr_addr, in->db_record);
+ MLX5_SET(srqc, srqc, xrcd, in->xrcd);
+ MLX5_SET(srqc, srqc, cqn, in->cqn);
+}
+
+static void get_wq(void *wq, struct mlx5_srq_attr *in)
+{
+ if (MLX5_GET(wq, wq, wq_signature))
+ in->flags &= MLX5_SRQ_FLAG_WQ_SIG;
+ in->log_page_size = MLX5_GET(wq, wq, log_wq_pg_sz);
+ in->wqe_shift = MLX5_GET(wq, wq, log_wq_stride) - 4;
+ in->log_size = MLX5_GET(wq, wq, log_wq_sz);
+ in->page_offset = MLX5_GET(wq, wq, page_offset);
+ in->lwm = MLX5_GET(wq, wq, lwm);
+ in->pd = MLX5_GET(wq, wq, pd);
+ in->db_record = MLX5_GET64(wq, wq, dbr_addr);
+}
+
+static void get_srqc(void *srqc, struct mlx5_srq_attr *in)
+{
+ if (MLX5_GET(srqc, srqc, wq_signature))
+ in->flags &= MLX5_SRQ_FLAG_WQ_SIG;
+ in->log_page_size = MLX5_GET(srqc, srqc, log_page_size);
+ in->wqe_shift = MLX5_GET(srqc, srqc, log_rq_stride);
+ in->log_size = MLX5_GET(srqc, srqc, log_srq_size);
+ in->page_offset = MLX5_GET(srqc, srqc, page_offset);
+ in->lwm = MLX5_GET(srqc, srqc, lwm);
+ in->pd = MLX5_GET(srqc, srqc, pd);
+ in->db_record = MLX5_GET64(srqc, srqc, dbr_addr);
}
struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn)
@@ -149,19 +150,36 @@ struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn)
EXPORT_SYMBOL(mlx5_core_get_srq);
static int create_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in, int inlen)
+ struct mlx5_srq_attr *in)
{
- struct mlx5_create_srq_mbox_out out;
+ u32 create_out[MLX5_ST_SZ_DW(create_srq_out)] = {0};
+ void *create_in;
+ void *srqc;
+ void *pas;
+ int pas_size;
+ int inlen;
int err;
- memset(&out, 0, sizeof(out));
+ pas_size = get_pas_size(in);
+ inlen = MLX5_ST_SZ_BYTES(create_srq_in) + pas_size;
+ create_in = mlx5_vzalloc(inlen);
+ if (!create_in)
+ return -ENOMEM;
+
+ srqc = MLX5_ADDR_OF(create_srq_in, create_in, srq_context_entry);
+ pas = MLX5_ADDR_OF(create_srq_in, create_in, pas);
- in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_SRQ);
+ set_srqc(srqc, in);
+ memcpy(pas, in->pas, pas_size);
- err = mlx5_cmd_exec_check_status(dev, (u32 *)in, inlen, (u32 *)(&out),
- sizeof(out));
+ MLX5_SET(create_srq_in, create_in, opcode,
+ MLX5_CMD_OP_CREATE_SRQ);
- srq->srqn = be32_to_cpu(out.srqn) & 0xffffff;
+ err = mlx5_cmd_exec_check_status(dev, create_in, inlen, create_out,
+ sizeof(create_out));
+ kvfree(create_in);
+ if (!err)
+ srq->srqn = MLX5_GET(create_srq_out, create_out, srqn);
return err;
}
@@ -169,67 +187,75 @@ static int create_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
static int destroy_srq_cmd(struct mlx5_core_dev *dev,
struct mlx5_core_srq *srq)
{
- struct mlx5_destroy_srq_mbox_in in;
- struct mlx5_destroy_srq_mbox_out out;
+ u32 srq_in[MLX5_ST_SZ_DW(destroy_srq_in)] = {0};
+ u32 srq_out[MLX5_ST_SZ_DW(destroy_srq_out)] = {0};
- memset(&in, 0, sizeof(in));
- memset(&out, 0, sizeof(out));
- in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ);
- in.srqn = cpu_to_be32(srq->srqn);
+ MLX5_SET(destroy_srq_in, srq_in, opcode,
+ MLX5_CMD_OP_DESTROY_SRQ);
+ MLX5_SET(destroy_srq_in, srq_in, srqn, srq->srqn);
- return mlx5_cmd_exec_check_status(dev, (u32 *)(&in), sizeof(in),
- (u32 *)(&out), sizeof(out));
+ return mlx5_cmd_exec_check_status(dev, srq_in, sizeof(srq_in),
+ srq_out, sizeof(srq_out));
}
static int arm_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
u16 lwm, int is_srq)
{
- struct mlx5_arm_srq_mbox_in in;
- struct mlx5_arm_srq_mbox_out out;
-
- memset(&in, 0, sizeof(in));
- memset(&out, 0, sizeof(out));
+ /* arm_srq structs missing using identical xrc ones */
+ u32 srq_in[MLX5_ST_SZ_DW(arm_xrc_srq_in)] = {0};
+ u32 srq_out[MLX5_ST_SZ_DW(arm_xrc_srq_out)] = {0};
- in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ARM_RQ);
- in.hdr.opmod = cpu_to_be16(!!is_srq);
- in.srqn = cpu_to_be32(srq->srqn);
- in.lwm = cpu_to_be16(lwm);
+ MLX5_SET(arm_xrc_srq_in, srq_in, opcode, MLX5_CMD_OP_ARM_XRC_SRQ);
+ MLX5_SET(arm_xrc_srq_in, srq_in, xrc_srqn, srq->srqn);
+ MLX5_SET(arm_xrc_srq_in, srq_in, lwm, lwm);
- return mlx5_cmd_exec_check_status(dev, (u32 *)(&in),
- sizeof(in), (u32 *)(&out),
- sizeof(out));
+ return mlx5_cmd_exec_check_status(dev, srq_in, sizeof(srq_in),
+ srq_out, sizeof(srq_out));
}
static int query_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_query_srq_mbox_out *out)
+ struct mlx5_srq_attr *out)
{
- struct mlx5_query_srq_mbox_in in;
+ u32 srq_in[MLX5_ST_SZ_DW(query_srq_in)] = {0};
+ u32 *srq_out;
+ void *srqc;
+ int err;
- memset(&in, 0, sizeof(in));
+ srq_out = mlx5_vzalloc(MLX5_ST_SZ_BYTES(query_srq_out));
+ if (!srq_out)
+ return -ENOMEM;
- in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SRQ);
- in.srqn = cpu_to_be32(srq->srqn);
+ MLX5_SET(query_srq_in, srq_in, opcode,
+ MLX5_CMD_OP_QUERY_SRQ);
+ MLX5_SET(query_srq_in, srq_in, srqn, srq->srqn);
+ err = mlx5_cmd_exec_check_status(dev, srq_in, sizeof(srq_in),
+ srq_out,
+ MLX5_ST_SZ_BYTES(query_srq_out));
+ if (err)
+ goto out;
- return mlx5_cmd_exec_check_status(dev, (u32 *)(&in), sizeof(in),
- (u32 *)out, sizeof(*out));
+ srqc = MLX5_ADDR_OF(query_srq_out, srq_out, srq_context_entry);
+ get_srqc(srqc, out);
+ if (MLX5_GET(srqc, srqc, state) != MLX5_SRQC_STATE_GOOD)
+ out->flags |= MLX5_SRQ_FLAG_ERR;
+out:
+ kvfree(srq_out);
+ return err;
}
static int create_xrc_srq_cmd(struct mlx5_core_dev *dev,
struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in,
- int srq_inlen)
+ struct mlx5_srq_attr *in)
{
u32 create_out[MLX5_ST_SZ_DW(create_xrc_srq_out)];
void *create_in;
- void *srqc;
void *xrc_srqc;
void *pas;
int pas_size;
int inlen;
int err;
- srqc = MLX5_ADDR_OF(create_srq_in, in, srq_context_entry);
- pas_size = get_pas_size(srqc);
+ pas_size = get_pas_size(in);
inlen = MLX5_ST_SZ_BYTES(create_xrc_srq_in) + pas_size;
create_in = mlx5_vzalloc(inlen);
if (!create_in)
@@ -239,7 +265,8 @@ static int create_xrc_srq_cmd(struct mlx5_core_dev *dev,
xrc_srq_context_entry);
pas = MLX5_ADDR_OF(create_xrc_srq_in, create_in, pas);
- memcpy(xrc_srqc, srqc, MLX5_ST_SZ_BYTES(srqc));
+ set_srqc(xrc_srqc, in);
+ MLX5_SET(xrc_srqc, xrc_srqc, user_index, in->user_index);
memcpy(pas, in->pas, pas_size);
MLX5_SET(create_xrc_srq_in, create_in, opcode,
MLX5_CMD_OP_CREATE_XRC_SRQ);
@@ -293,11 +320,10 @@ static int arm_xrc_srq_cmd(struct mlx5_core_dev *dev,
static int query_xrc_srq_cmd(struct mlx5_core_dev *dev,
struct mlx5_core_srq *srq,
- struct mlx5_query_srq_mbox_out *out)
+ struct mlx5_srq_attr *out)
{
u32 xrcsrq_in[MLX5_ST_SZ_DW(query_xrc_srq_in)];
u32 *xrcsrq_out;
- void *srqc;
void *xrc_srqc;
int err;
@@ -317,8 +343,9 @@ static int query_xrc_srq_cmd(struct mlx5_core_dev *dev,
xrc_srqc = MLX5_ADDR_OF(query_xrc_srq_out, xrcsrq_out,
xrc_srq_context_entry);
- srqc = MLX5_ADDR_OF(query_srq_out, out, srq_context_entry);
- memcpy(srqc, xrc_srqc, MLX5_ST_SZ_BYTES(srqc));
+ get_srqc(xrc_srqc, out);
+ if (MLX5_GET(xrc_srqc, xrc_srqc, state) != MLX5_XRC_SRQC_STATE_GOOD)
+ out->flags |= MLX5_SRQ_FLAG_ERR;
out:
kvfree(xrcsrq_out);
@@ -326,26 +353,27 @@ out:
}
static int create_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in, int srq_inlen)
+ struct mlx5_srq_attr *in)
{
void *create_in;
void *rmpc;
- void *srqc;
+ void *wq;
int pas_size;
int inlen;
int err;
- srqc = MLX5_ADDR_OF(create_srq_in, in, srq_context_entry);
- pas_size = get_pas_size(srqc);
+ pas_size = get_pas_size(in);
inlen = MLX5_ST_SZ_BYTES(create_rmp_in) + pas_size;
create_in = mlx5_vzalloc(inlen);
if (!create_in)
return -ENOMEM;
rmpc = MLX5_ADDR_OF(create_rmp_in, create_in, ctx);
+ wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
+ MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY);
+ set_wq(wq, in);
memcpy(MLX5_ADDR_OF(rmpc, rmpc, wq.pas), in->pas, pas_size);
- rmpc_srqc_reformat(srqc, rmpc, true);
err = mlx5_core_create_rmp(dev, create_in, inlen, &srq->srqn);
@@ -390,11 +418,10 @@ static int arm_rmp_cmd(struct mlx5_core_dev *dev,
}
static int query_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_query_srq_mbox_out *out)
+ struct mlx5_srq_attr *out)
{
u32 *rmp_out;
void *rmpc;
- void *srqc;
int err;
rmp_out = mlx5_vzalloc(MLX5_ST_SZ_BYTES(query_rmp_out));
@@ -405,9 +432,10 @@ static int query_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
if (err)
goto out;
- srqc = MLX5_ADDR_OF(query_srq_out, out, srq_context_entry);
rmpc = MLX5_ADDR_OF(query_rmp_out, rmp_out, rmp_context);
- rmpc_srqc_reformat(srqc, rmpc, false);
+ get_wq(MLX5_ADDR_OF(rmpc, rmpc, wq), out);
+ if (MLX5_GET(rmpc, rmpc, state) != MLX5_RMPC_STATE_RDY)
+ out->flags |= MLX5_SRQ_FLAG_ERR;
out:
kvfree(rmp_out);
@@ -416,15 +444,14 @@ out:
static int create_srq_split(struct mlx5_core_dev *dev,
struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in,
- int inlen, int is_xrc)
+ struct mlx5_srq_attr *in)
{
if (!dev->issi)
- return create_srq_cmd(dev, srq, in, inlen);
+ return create_srq_cmd(dev, srq, in);
else if (srq->common.res == MLX5_RES_XSRQ)
- return create_xrc_srq_cmd(dev, srq, in, inlen);
+ return create_xrc_srq_cmd(dev, srq, in);
else
- return create_rmp_cmd(dev, srq, in, inlen);
+ return create_rmp_cmd(dev, srq, in);
}
static int destroy_srq_split(struct mlx5_core_dev *dev,
@@ -439,15 +466,17 @@ static int destroy_srq_split(struct mlx5_core_dev *dev,
}
int mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in, int inlen,
- int is_xrc)
+ struct mlx5_srq_attr *in)
{
int err;
struct mlx5_srq_table *table = &dev->priv.srq_table;
- srq->common.res = is_xrc ? MLX5_RES_XSRQ : MLX5_RES_SRQ;
+ if (in->type == IB_SRQT_XRC)
+ srq->common.res = MLX5_RES_XSRQ;
+ else
+ srq->common.res = MLX5_RES_SRQ;
- err = create_srq_split(dev, srq, in, inlen, is_xrc);
+ err = create_srq_split(dev, srq, in);
if (err)
return err;
@@ -502,7 +531,7 @@ int mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq)
EXPORT_SYMBOL(mlx5_core_destroy_srq);
int mlx5_core_query_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_query_srq_mbox_out *out)
+ struct mlx5_srq_attr *out)
{
if (!dev->issi)
return query_srq_cmd(dev, srq, out);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
index 03a5093ffeb7..28274a6fbafe 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
@@ -85,6 +85,7 @@ int mlx5_core_create_rq(struct mlx5_core_dev *dev, u32 *in, int inlen, u32 *rqn)
return err;
}
+EXPORT_SYMBOL(mlx5_core_create_rq);
int mlx5_core_modify_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *in, int inlen)
{
@@ -110,6 +111,7 @@ void mlx5_core_destroy_rq(struct mlx5_core_dev *dev, u32 rqn)
mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
}
+EXPORT_SYMBOL(mlx5_core_destroy_rq);
int mlx5_core_query_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *out)
{
@@ -430,6 +432,7 @@ int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen,
return err;
}
+EXPORT_SYMBOL(mlx5_core_create_rqt);
int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in,
int inlen)
@@ -455,3 +458,4 @@ void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn)
mlx5_cmd_exec_check_status(dev, in, sizeof(in), out, sizeof(out));
}
+EXPORT_SYMBOL(mlx5_core_destroy_rqt);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 355e1ae665f9..8f0fd41dfd4b 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -139,11 +139,11 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
ar->id.subsystem_vendor, ar->id.subsystem_device);
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
- config_enabled(CONFIG_ATH10K_DEBUG),
- config_enabled(CONFIG_ATH10K_DEBUGFS),
- config_enabled(CONFIG_ATH10K_TRACING),
- config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
- config_enabled(CONFIG_NL80211_TESTMODE));
+ IS_ENABLED(CONFIG_ATH10K_DEBUG),
+ IS_ENABLED(CONFIG_ATH10K_DEBUGFS),
+ IS_ENABLED(CONFIG_ATH10K_TRACING),
+ IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED),
+ IS_ENABLED(CONFIG_NL80211_TESTMODE));
firmware = ar->normal_mode_fw.fw_file.firmware;
if (firmware)
@@ -2424,7 +2424,7 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_simulate_radar);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fb8e38df9446..0bbd0a00edcc 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3039,7 +3039,7 @@ static void ath10k_regd_update(struct ath10k *ar)
regpair = ar->ath_common.regulatory.regpair;
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
nl_dfs_reg = ar->dfs_detector->region;
wmi_dfs_reg = ath10k_mac_get_dfs_region(nl_dfs_reg);
} else {
@@ -3068,7 +3068,7 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
request->dfs_region);
result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector,
@@ -7955,7 +7955,7 @@ int ath10k_mac_register(struct ath10k *ar)
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
ar->hw->netdev_features = NETIF_F_HW_CSUM;
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
/* Init ath dfs pattern detector */
ar->ath_common.debug_mask = ATH_DBG_DFS;
ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common,
@@ -8003,7 +8003,7 @@ err_unregister:
ieee80211_unregister_hw(ar->hw);
err_dfs_detector_exit:
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
ar->dfs_detector->exit(ar->dfs_detector);
err_free:
@@ -8018,7 +8018,7 @@ void ath10k_mac_unregister(struct ath10k *ar)
{
ieee80211_unregister_hw(ar->hw);
- if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+ if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
ar->dfs_detector->exit(ar->dfs_detector);
kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 169cd2e783eb..d2462886b75c 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3704,7 +3704,7 @@ void ath10k_wmi_event_dfs(struct ath10k *ar,
phyerr->tsf_timestamp, tsf, buf_len);
/* Skip event if DFS disabled */
- if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED))
+ if (!IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED))
return;
ATH10K_DFS_STAT_INC(ar, pulses_total);
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 4ad6284fc37d..72e2ec67768d 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3881,7 +3881,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
BIT(NL80211_IFTYPE_P2P_CLIENT);
}
- if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
+ if (IS_ENABLED(CONFIG_ATH6KL_REGDOMAIN) &&
test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities)) {
wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
ar->wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index a8762711ad74..e2512d5bc0e1 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -731,7 +731,7 @@ void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
struct ath_hw *ah = spec_priv->ah;
u32 rxfilter;
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return;
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
@@ -806,7 +806,7 @@ static ssize_t write_file_spec_scan_ctl(struct file *file,
char buf[32];
ssize_t len;
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return -EOPNOTSUPP;
len = min(count, sizeof(buf) - 1);
@@ -1072,7 +1072,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = {
void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
{
- if (config_enabled(CONFIG_ATH9K_DEBUGFS)) {
+ if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS)) {
relay_close(spec_priv->rfs_chan_spec_scan);
spec_priv->rfs_chan_spec_scan = NULL;
}
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index edc74fca60aa..cfa3fe82ade3 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -843,7 +843,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
NL80211_FEATURE_P2P_GO_CTWIN;
- if (!config_enabled(CONFIG_ATH9K_TX99)) {
+ if (!IS_ENABLED(CONFIG_ATH9K_TX99)) {
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 7594650f214f..a394622c9022 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1250,7 +1250,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
- if (config_enabled(CONFIG_ATH9K_TX99)) {
+ if (IS_ENABLED(CONFIG_ATH9K_TX99)) {
if (sc->cur_chan->nvifs >= 1) {
mutex_unlock(&sc->mutex);
return -EOPNOTSUPP;
@@ -1300,7 +1300,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
- if (config_enabled(CONFIG_ATH9K_TX99)) {
+ if (IS_ENABLED(CONFIG_ATH9K_TX99)) {
mutex_unlock(&sc->mutex);
return -EOPNOTSUPP;
}
@@ -1360,7 +1360,7 @@ static void ath9k_enable_ps(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return;
sc->ps_enabled = true;
@@ -1379,7 +1379,7 @@ static void ath9k_disable_ps(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return;
sc->ps_enabled = false;
@@ -1953,7 +1953,7 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
struct ieee80211_channel *chan;
int pos;
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return -EOPNOTSUPP;
spin_lock_bh(&common->cc_lock);
@@ -2003,7 +2003,7 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return;
mutex_lock(&sc->mutex);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 32160fca876a..669734252664 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -377,7 +377,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u32 rfilt;
- if (config_enabled(CONFIG_ATH9K_TX99))
+ if (IS_ENABLED(CONFIG_ATH9K_TX99))
return 0;
rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 2303ef96299d..2f8136d50f78 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -352,7 +352,7 @@ dfs_pattern_detector_init(struct ath_common *common,
{
struct dfs_pattern_detector *dpd;
- if (!config_enabled(CONFIG_CFG80211_CERTIFICATION_ONUS))
+ if (!IS_ENABLED(CONFIG_CFG80211_CERTIFICATION_ONUS))
return NULL;
dpd = kmalloc(sizeof(*dpd), GFP_KERNEL);
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 7e15ed9ed31f..f8506037736f 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -116,7 +116,7 @@ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
static bool dynamic_country_user_possible(struct ath_regulatory *reg)
{
- if (config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+ if (IS_ENABLED(CONFIG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
return true;
switch (reg->country_code) {
@@ -188,7 +188,7 @@ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg)
{
- if (!config_enabled(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS))
+ if (!IS_ENABLED(CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS))
return false;
if (!dynamic_country_user_possible(reg))
return false;
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_intel.c
index 40d04ef5da9e..0d5c29ae51de 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.c
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.c
@@ -551,13 +551,15 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *offp)
{
struct intel_ntb_dev *ndev;
+ struct pci_dev *pdev;
void __iomem *mmio;
char *buf;
size_t buf_size;
ssize_t ret, off;
- union { u64 v64; u32 v32; u16 v16; } u;
+ union { u64 v64; u32 v32; u16 v16; u8 v8; } u;
ndev = filp->private_data;
+ pdev = ndev_pdev(ndev);
mmio = ndev->self_mmio;
buf_size = min(count, 0x800ul);
@@ -632,6 +634,41 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
"Doorbell Bell -\t\t%#llx\n", u.v64);
off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Window Size:\n");
+
+ pci_read_config_byte(pdev, XEON_PBAR23SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "PBAR23SZ %hhu\n", u.v8);
+ if (!ndev->bar4_split) {
+ pci_read_config_byte(pdev, XEON_PBAR45SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "PBAR45SZ %hhu\n", u.v8);
+ } else {
+ pci_read_config_byte(pdev, XEON_PBAR4SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "PBAR4SZ %hhu\n", u.v8);
+ pci_read_config_byte(pdev, XEON_PBAR5SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "PBAR5SZ %hhu\n", u.v8);
+ }
+
+ pci_read_config_byte(pdev, XEON_SBAR23SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "SBAR23SZ %hhu\n", u.v8);
+ if (!ndev->bar4_split) {
+ pci_read_config_byte(pdev, XEON_SBAR45SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "SBAR45SZ %hhu\n", u.v8);
+ } else {
+ pci_read_config_byte(pdev, XEON_SBAR4SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "SBAR4SZ %hhu\n", u.v8);
+ pci_read_config_byte(pdev, XEON_SBAR5SZ_OFFSET, &u.v8);
+ off += scnprintf(buf + off, buf_size - off,
+ "SBAR5SZ %hhu\n", u.v8);
+ }
+
+ off += scnprintf(buf + off, buf_size - off,
"\nNTB Incoming XLAT:\n");
u.v64 = ioread64(mmio + bar2_off(ndev->xlat_reg->bar2_xlat, 2));
@@ -669,7 +706,7 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
"LMT45 -\t\t\t%#018llx\n", u.v64);
}
- if (pdev_is_xeon(ndev->ntb.pdev)) {
+ if (pdev_is_xeon(pdev)) {
if (ntb_topo_is_b2b(ndev->ntb.topo)) {
off += scnprintf(buf + off, buf_size - off,
"\nNTB Outgoing B2B XLAT:\n");
@@ -750,22 +787,22 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
off += scnprintf(buf + off, buf_size - off,
"\nXEON NTB Hardware Errors:\n");
- if (!pci_read_config_word(ndev->ntb.pdev,
+ if (!pci_read_config_word(pdev,
XEON_DEVSTS_OFFSET, &u.v16))
off += scnprintf(buf + off, buf_size - off,
"DEVSTS -\t\t%#06x\n", u.v16);
- if (!pci_read_config_word(ndev->ntb.pdev,
+ if (!pci_read_config_word(pdev,
XEON_LINK_STATUS_OFFSET, &u.v16))
off += scnprintf(buf + off, buf_size - off,
"LNKSTS -\t\t%#06x\n", u.v16);
- if (!pci_read_config_dword(ndev->ntb.pdev,
+ if (!pci_read_config_dword(pdev,
XEON_UNCERRSTS_OFFSET, &u.v32))
off += scnprintf(buf + off, buf_size - off,
"UNCERRSTS -\t\t%#06x\n", u.v32);
- if (!pci_read_config_dword(ndev->ntb.pdev,
+ if (!pci_read_config_dword(pdev,
XEON_CORERRSTS_OFFSET, &u.v32))
off += scnprintf(buf + off, buf_size - off,
"CORERRSTS -\t\t%#06x\n", u.v32);
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 2ef9d9130864..d5c5894f252e 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -153,6 +153,7 @@ struct ntb_transport_qp {
unsigned int rx_index;
unsigned int rx_max_entry;
unsigned int rx_max_frame;
+ unsigned int rx_alloc_entry;
dma_cookie_t last_cookie;
struct tasklet_struct rxc_db_work;
@@ -480,7 +481,9 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, size_t count,
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"rx_index - \t%u\n", qp->rx_index);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
- "rx_max_entry - \t%u\n\n", qp->rx_max_entry);
+ "rx_max_entry - \t%u\n", qp->rx_max_entry);
+ out_offset += snprintf(buf + out_offset, out_count - out_offset,
+ "rx_alloc_entry - \t%u\n\n", qp->rx_alloc_entry);
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"tx_bytes - \t%llu\n", qp->tx_bytes);
@@ -597,9 +600,12 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
{
struct ntb_transport_qp *qp = &nt->qp_vec[qp_num];
struct ntb_transport_mw *mw;
+ struct ntb_dev *ndev = nt->ndev;
+ struct ntb_queue_entry *entry;
unsigned int rx_size, num_qps_mw;
unsigned int mw_num, mw_count, qp_count;
unsigned int i;
+ int node;
mw_count = nt->mw_count;
qp_count = nt->qp_count;
@@ -626,6 +632,23 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
qp->rx_max_entry = rx_size / qp->rx_max_frame;
qp->rx_index = 0;
+ /*
+ * Checking to see if we have more entries than the default.
+ * We should add additional entries if that is the case so we
+ * can be in sync with the transport frames.
+ */
+ node = dev_to_node(&ndev->dev);
+ for (i = qp->rx_alloc_entry; i < qp->rx_max_entry; i++) {
+ entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
+ if (!entry)
+ return -ENOMEM;
+
+ entry->qp = qp;
+ ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry,
+ &qp->rx_free_q);
+ qp->rx_alloc_entry++;
+ }
+
qp->remote_rx_info->entry = qp->rx_max_entry - 1;
/* setup the hdr offsets with 0's */
@@ -1037,6 +1060,13 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
int node;
int rc, i;
+ mw_count = ntb_mw_count(ndev);
+ if (ntb_spad_count(ndev) < (NUM_MWS + 1 + mw_count * 2)) {
+ dev_err(&ndev->dev, "Not enough scratch pad registers for %s",
+ NTB_TRANSPORT_NAME);
+ return -EIO;
+ }
+
if (ntb_db_is_unsafe(ndev))
dev_dbg(&ndev->dev,
"doorbell is unsafe, proceed anyway...\n");
@@ -1052,8 +1082,6 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
nt->ndev = ndev;
- mw_count = ntb_mw_count(ndev);
-
nt->mw_count = mw_count;
nt->mw_vec = kzalloc_node(mw_count * sizeof(*nt->mw_vec),
@@ -1722,8 +1750,9 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry,
&qp->rx_free_q);
}
+ qp->rx_alloc_entry = NTB_QP_DEF_NUM_ENTRIES;
- for (i = 0; i < NTB_QP_DEF_NUM_ENTRIES; i++) {
+ for (i = 0; i < qp->tx_max_entry; i++) {
entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
if (!entry)
goto err2;
@@ -1744,6 +1773,7 @@ err2:
while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
kfree(entry);
err1:
+ qp->rx_alloc_entry = 0;
while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q)))
kfree(entry);
if (qp->tx_dma_chan)
diff --git a/drivers/ntb/test/ntb_perf.c b/drivers/ntb/test/ntb_perf.c
index 8dfce9c9aad0..6a50f20bf1cd 100644
--- a/drivers/ntb/test/ntb_perf.c
+++ b/drivers/ntb/test/ntb_perf.c
@@ -58,6 +58,7 @@
#include <linux/delay.h>
#include <linux/sizes.h>
#include <linux/ntb.h>
+#include <linux/mutex.h>
#define DRIVER_NAME "ntb_perf"
#define DRIVER_DESCRIPTION "PCIe NTB Performance Measurement Tool"
@@ -83,6 +84,10 @@ MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
static struct dentry *perf_debugfs_dir;
+static unsigned long max_mw_size;
+module_param(max_mw_size, ulong, 0644);
+MODULE_PARM_DESC(max_mw_size, "Limit size of large memory windows");
+
static unsigned int seg_order = 19; /* 512K */
module_param(seg_order, uint, 0644);
MODULE_PARM_DESC(seg_order, "size order [n^2] of buffer segment for testing");
@@ -117,6 +122,10 @@ struct pthr_ctx {
int dma_prep_err;
int src_idx;
void *srcs[MAX_SRCS];
+ wait_queue_head_t *wq;
+ int status;
+ u64 copied;
+ u64 diff_us;
};
struct perf_ctx {
@@ -124,23 +133,23 @@ struct perf_ctx {
spinlock_t db_lock;
struct perf_mw mw;
bool link_is_up;
- struct work_struct link_cleanup;
struct delayed_work link_work;
+ wait_queue_head_t link_wq;
struct dentry *debugfs_node_dir;
struct dentry *debugfs_run;
struct dentry *debugfs_threads;
u8 perf_threads;
- bool run;
+ /* mutex ensures only one set of threads run at once */
+ struct mutex run_mutex;
struct pthr_ctx pthr_ctx[MAX_THREADS];
atomic_t tsync;
+ atomic_t tdone;
};
enum {
VERSION = 0,
MW_SZ_HIGH,
MW_SZ_LOW,
- SPAD_MSG,
- SPAD_ACK,
MAX_SPAD
};
@@ -148,10 +157,16 @@ static void perf_link_event(void *ctx)
{
struct perf_ctx *perf = ctx;
- if (ntb_link_is_up(perf->ntb, NULL, NULL) == 1)
+ if (ntb_link_is_up(perf->ntb, NULL, NULL) == 1) {
schedule_delayed_work(&perf->link_work, 2*HZ);
- else
- schedule_work(&perf->link_cleanup);
+ } else {
+ dev_dbg(&perf->ntb->pdev->dev, "link down\n");
+
+ if (!perf->link_is_up)
+ cancel_delayed_work_sync(&perf->link_work);
+
+ perf->link_is_up = false;
+ }
}
static void perf_db_event(void *ctx, int vec)
@@ -271,6 +286,7 @@ static int perf_move_data(struct pthr_ctx *pctx, char __iomem *dst, char *src,
char __iomem *tmp = dst;
u64 perf, diff_us;
ktime_t kstart, kstop, kdiff;
+ unsigned long last_sleep = jiffies;
chunks = div64_u64(win_size, buf_size);
total_chunks = div64_u64(total, buf_size);
@@ -286,30 +302,40 @@ static int perf_move_data(struct pthr_ctx *pctx, char __iomem *dst, char *src,
} else
tmp += buf_size;
- /* Probably should schedule every 4GB to prevent soft hang. */
- if (((copied % SZ_4G) == 0) && !use_dma) {
+ /* Probably should schedule every 5s to prevent soft hang. */
+ if (unlikely((jiffies - last_sleep) > 5 * HZ)) {
+ last_sleep = jiffies;
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
}
+
+ if (unlikely(kthread_should_stop()))
+ break;
}
if (use_dma) {
- pr_info("%s: All DMA descriptors submitted\n", current->comm);
- while (atomic_read(&pctx->dma_sync) != 0)
+ pr_debug("%s: All DMA descriptors submitted\n", current->comm);
+ while (atomic_read(&pctx->dma_sync) != 0) {
+ if (kthread_should_stop())
+ break;
msleep(20);
+ }
}
kstop = ktime_get();
kdiff = ktime_sub(kstop, kstart);
diff_us = ktime_to_us(kdiff);
- pr_info("%s: copied %llu bytes\n", current->comm, copied);
+ pr_debug("%s: copied %llu bytes\n", current->comm, copied);
- pr_info("%s: lasted %llu usecs\n", current->comm, diff_us);
+ pr_debug("%s: lasted %llu usecs\n", current->comm, diff_us);
perf = div64_u64(copied, diff_us);
- pr_info("%s: MBytes/s: %llu\n", current->comm, perf);
+ pr_debug("%s: MBytes/s: %llu\n", current->comm, perf);
+
+ pctx->copied = copied;
+ pctx->diff_us = diff_us;
return 0;
}
@@ -331,7 +357,7 @@ static int ntb_perf_thread(void *data)
int rc, node, i;
struct dma_chan *dma_chan = NULL;
- pr_info("kthread %s starting...\n", current->comm);
+ pr_debug("kthread %s starting...\n", current->comm);
node = dev_to_node(&pdev->dev);
@@ -389,7 +415,10 @@ static int ntb_perf_thread(void *data)
pctx->srcs[i] = NULL;
}
- return 0;
+ atomic_inc(&perf->tdone);
+ wake_up(pctx->wq);
+ rc = 0;
+ goto done;
err:
for (i = 0; i < MAX_SRCS; i++) {
@@ -402,6 +431,16 @@ err:
pctx->dma_chan = NULL;
}
+done:
+ /* Wait until we are told to stop */
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (kthread_should_stop())
+ break;
+ schedule();
+ }
+ __set_current_state(TASK_RUNNING);
+
return rc;
}
@@ -472,6 +511,10 @@ static void perf_link_work(struct work_struct *work)
dev_dbg(&perf->ntb->pdev->dev, "%s called\n", __func__);
size = perf->mw.phys_size;
+
+ if (max_mw_size && size > max_mw_size)
+ size = max_mw_size;
+
ntb_peer_spad_write(ndev, MW_SZ_HIGH, upper_32_bits(size));
ntb_peer_spad_write(ndev, MW_SZ_LOW, lower_32_bits(size));
ntb_peer_spad_write(ndev, VERSION, PERF_VERSION);
@@ -496,6 +539,7 @@ static void perf_link_work(struct work_struct *work)
goto out1;
perf->link_is_up = true;
+ wake_up(&perf->link_wq);
return;
@@ -508,18 +552,6 @@ out:
msecs_to_jiffies(PERF_LINK_DOWN_TIMEOUT));
}
-static void perf_link_cleanup(struct work_struct *work)
-{
- struct perf_ctx *perf = container_of(work,
- struct perf_ctx,
- link_cleanup);
-
- dev_dbg(&perf->ntb->pdev->dev, "%s called\n", __func__);
-
- if (!perf->link_is_up)
- cancel_delayed_work_sync(&perf->link_work);
-}
-
static int perf_setup_mw(struct ntb_dev *ntb, struct perf_ctx *perf)
{
struct perf_mw *mw;
@@ -544,16 +576,44 @@ static ssize_t debugfs_run_read(struct file *filp, char __user *ubuf,
{
struct perf_ctx *perf = filp->private_data;
char *buf;
- ssize_t ret, out_offset;
+ ssize_t ret, out_off = 0;
+ struct pthr_ctx *pctx;
+ int i;
+ u64 rate;
if (!perf)
return 0;
- buf = kmalloc(64, GFP_KERNEL);
+ buf = kmalloc(1024, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- out_offset = snprintf(buf, 64, "%d\n", perf->run);
- ret = simple_read_from_buffer(ubuf, count, offp, buf, out_offset);
+
+ if (mutex_is_locked(&perf->run_mutex)) {
+ out_off = snprintf(buf, 64, "running\n");
+ goto read_from_buf;
+ }
+
+ for (i = 0; i < MAX_THREADS; i++) {
+ pctx = &perf->pthr_ctx[i];
+
+ if (pctx->status == -ENODATA)
+ break;
+
+ if (pctx->status) {
+ out_off += snprintf(buf + out_off, 1024 - out_off,
+ "%d: error %d\n", i,
+ pctx->status);
+ continue;
+ }
+
+ rate = div64_u64(pctx->copied, pctx->diff_us);
+ out_off += snprintf(buf + out_off, 1024 - out_off,
+ "%d: copied %llu bytes in %llu usecs, %llu MBytes/s\n",
+ i, pctx->copied, pctx->diff_us, rate);
+ }
+
+read_from_buf:
+ ret = simple_read_from_buffer(ubuf, count, offp, buf, out_off);
kfree(buf);
return ret;
@@ -564,80 +624,90 @@ static void threads_cleanup(struct perf_ctx *perf)
struct pthr_ctx *pctx;
int i;
- perf->run = false;
for (i = 0; i < MAX_THREADS; i++) {
pctx = &perf->pthr_ctx[i];
if (pctx->thread) {
- kthread_stop(pctx->thread);
+ pctx->status = kthread_stop(pctx->thread);
pctx->thread = NULL;
}
}
}
+static void perf_clear_thread_status(struct perf_ctx *perf)
+{
+ int i;
+
+ for (i = 0; i < MAX_THREADS; i++)
+ perf->pthr_ctx[i].status = -ENODATA;
+}
+
static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf,
size_t count, loff_t *offp)
{
struct perf_ctx *perf = filp->private_data;
int node, i;
+ DECLARE_WAIT_QUEUE_HEAD(wq);
- if (!perf->link_is_up)
- return 0;
+ if (wait_event_interruptible(perf->link_wq, perf->link_is_up))
+ return -ENOLINK;
if (perf->perf_threads == 0)
- return 0;
+ return -EINVAL;
- if (atomic_read(&perf->tsync) == 0)
- perf->run = false;
+ if (!mutex_trylock(&perf->run_mutex))
+ return -EBUSY;
- if (perf->run)
- threads_cleanup(perf);
- else {
- perf->run = true;
+ perf_clear_thread_status(perf);
- if (perf->perf_threads > MAX_THREADS) {
- perf->perf_threads = MAX_THREADS;
- pr_info("Reset total threads to: %u\n", MAX_THREADS);
- }
+ if (perf->perf_threads > MAX_THREADS) {
+ perf->perf_threads = MAX_THREADS;
+ pr_info("Reset total threads to: %u\n", MAX_THREADS);
+ }
- /* no greater than 1M */
- if (seg_order > MAX_SEG_ORDER) {
- seg_order = MAX_SEG_ORDER;
- pr_info("Fix seg_order to %u\n", seg_order);
- }
+ /* no greater than 1M */
+ if (seg_order > MAX_SEG_ORDER) {
+ seg_order = MAX_SEG_ORDER;
+ pr_info("Fix seg_order to %u\n", seg_order);
+ }
- if (run_order < seg_order) {
- run_order = seg_order;
- pr_info("Fix run_order to %u\n", run_order);
- }
+ if (run_order < seg_order) {
+ run_order = seg_order;
+ pr_info("Fix run_order to %u\n", run_order);
+ }
- node = dev_to_node(&perf->ntb->pdev->dev);
- /* launch kernel thread */
- for (i = 0; i < perf->perf_threads; i++) {
- struct pthr_ctx *pctx;
-
- pctx = &perf->pthr_ctx[i];
- atomic_set(&pctx->dma_sync, 0);
- pctx->perf = perf;
- pctx->thread =
- kthread_create_on_node(ntb_perf_thread,
- (void *)pctx,
- node, "ntb_perf %d", i);
- if (IS_ERR(pctx->thread)) {
- pctx->thread = NULL;
- goto err;
- } else
- wake_up_process(pctx->thread);
-
- if (perf->run == false)
- return -ENXIO;
- }
+ node = dev_to_node(&perf->ntb->pdev->dev);
+ atomic_set(&perf->tdone, 0);
+ /* launch kernel thread */
+ for (i = 0; i < perf->perf_threads; i++) {
+ struct pthr_ctx *pctx;
+
+ pctx = &perf->pthr_ctx[i];
+ atomic_set(&pctx->dma_sync, 0);
+ pctx->perf = perf;
+ pctx->wq = &wq;
+ pctx->thread =
+ kthread_create_on_node(ntb_perf_thread,
+ (void *)pctx,
+ node, "ntb_perf %d", i);
+ if (IS_ERR(pctx->thread)) {
+ pctx->thread = NULL;
+ goto err;
+ } else {
+ wake_up_process(pctx->thread);
+ }
}
+ wait_event_interruptible(wq,
+ atomic_read(&perf->tdone) == perf->perf_threads);
+
+ threads_cleanup(perf);
+ mutex_unlock(&perf->run_mutex);
return count;
err:
threads_cleanup(perf);
+ mutex_unlock(&perf->run_mutex);
return -ENXIO;
}
@@ -688,6 +758,12 @@ static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
int node;
int rc = 0;
+ if (ntb_spad_count(ntb) < MAX_SPAD) {
+ dev_err(&ntb->dev, "Not enough scratch pad registers for %s",
+ DRIVER_NAME);
+ return -EIO;
+ }
+
node = dev_to_node(&pdev->dev);
perf = kzalloc_node(sizeof(*perf), GFP_KERNEL, node);
@@ -699,11 +775,11 @@ static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
perf->ntb = ntb;
perf->perf_threads = 1;
atomic_set(&perf->tsync, 0);
- perf->run = false;
+ mutex_init(&perf->run_mutex);
spin_lock_init(&perf->db_lock);
perf_setup_mw(ntb, perf);
+ init_waitqueue_head(&perf->link_wq);
INIT_DELAYED_WORK(&perf->link_work, perf_link_work);
- INIT_WORK(&perf->link_cleanup, perf_link_cleanup);
rc = ntb_set_ctx(ntb, perf, &perf_ops);
if (rc)
@@ -717,11 +793,12 @@ static int perf_probe(struct ntb_client *client, struct ntb_dev *ntb)
if (rc)
goto err_ctx;
+ perf_clear_thread_status(perf);
+
return 0;
err_ctx:
cancel_delayed_work_sync(&perf->link_work);
- cancel_work_sync(&perf->link_cleanup);
kfree(perf);
err_perf:
return rc;
@@ -734,8 +811,9 @@ static void perf_remove(struct ntb_client *client, struct ntb_dev *ntb)
dev_dbg(&perf->ntb->dev, "%s called\n", __func__);
+ mutex_lock(&perf->run_mutex);
+
cancel_delayed_work_sync(&perf->link_work);
- cancel_work_sync(&perf->link_cleanup);
ntb_clear_ctx(ntb);
ntb_link_disable(ntb);
diff --git a/drivers/ntb/test/ntb_pingpong.c b/drivers/ntb/test/ntb_pingpong.c
index fe1600566981..7d311799fca1 100644
--- a/drivers/ntb/test/ntb_pingpong.c
+++ b/drivers/ntb/test/ntb_pingpong.c
@@ -61,6 +61,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/debugfs.h>
#include <linux/ntb.h>
@@ -96,8 +97,13 @@ struct pp_ctx {
spinlock_t db_lock;
struct timer_list db_timer;
unsigned long db_delay;
+ struct dentry *debugfs_node_dir;
+ struct dentry *debugfs_count;
+ atomic_t count;
};
+static struct dentry *pp_debugfs_dir;
+
static void pp_ping(unsigned long ctx)
{
struct pp_ctx *pp = (void *)ctx;
@@ -171,10 +177,32 @@ static void pp_db_event(void *ctx, int vec)
dev_dbg(&pp->ntb->dev,
"Pong vec %d bits %#llx\n",
vec, db_bits);
+ atomic_inc(&pp->count);
}
spin_unlock_irqrestore(&pp->db_lock, irqflags);
}
+static int pp_debugfs_setup(struct pp_ctx *pp)
+{
+ struct pci_dev *pdev = pp->ntb->pdev;
+
+ if (!pp_debugfs_dir)
+ return -ENODEV;
+
+ pp->debugfs_node_dir = debugfs_create_dir(pci_name(pdev),
+ pp_debugfs_dir);
+ if (!pp->debugfs_node_dir)
+ return -ENODEV;
+
+ pp->debugfs_count = debugfs_create_atomic_t("count", S_IRUSR | S_IWUSR,
+ pp->debugfs_node_dir,
+ &pp->count);
+ if (!pp->debugfs_count)
+ return -ENODEV;
+
+ return 0;
+}
+
static const struct ntb_ctx_ops pp_ops = {
.link_event = pp_link_event,
.db_event = pp_db_event,
@@ -210,6 +238,7 @@ static int pp_probe(struct ntb_client *client,
pp->ntb = ntb;
pp->db_bits = 0;
+ atomic_set(&pp->count, 0);
spin_lock_init(&pp->db_lock);
setup_timer(&pp->db_timer, pp_ping, (unsigned long)pp);
pp->db_delay = msecs_to_jiffies(delay_ms);
@@ -218,6 +247,10 @@ static int pp_probe(struct ntb_client *client,
if (rc)
goto err_ctx;
+ rc = pp_debugfs_setup(pp);
+ if (rc)
+ goto err_ctx;
+
ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
ntb_link_event(ntb);
@@ -234,6 +267,8 @@ static void pp_remove(struct ntb_client *client,
{
struct pp_ctx *pp = ntb->ctx;
+ debugfs_remove_recursive(pp->debugfs_node_dir);
+
ntb_clear_ctx(ntb);
del_timer_sync(&pp->db_timer);
ntb_link_disable(ntb);
@@ -247,4 +282,29 @@ static struct ntb_client pp_client = {
.remove = pp_remove,
},
};
-module_ntb_client(pp_client);
+
+static int __init pp_init(void)
+{
+ int rc;
+
+ if (debugfs_initialized())
+ pp_debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+
+ rc = ntb_register_client(&pp_client);
+ if (rc)
+ goto err_client;
+
+ return 0;
+
+err_client:
+ debugfs_remove_recursive(pp_debugfs_dir);
+ return rc;
+}
+module_init(pp_init);
+
+static void __exit pp_exit(void)
+{
+ ntb_unregister_client(&pp_client);
+ debugfs_remove_recursive(pp_debugfs_dir);
+}
+module_exit(pp_exit);
diff --git a/drivers/ntb/test/ntb_tool.c b/drivers/ntb/test/ntb_tool.c
index 6f5dc6ca673d..61bf2ef87e0e 100644
--- a/drivers/ntb/test/ntb_tool.c
+++ b/drivers/ntb/test/ntb_tool.c
@@ -59,6 +59,12 @@
*
* Eg: check if clearing the doorbell mask generates an interrupt.
*
+ * # Check the link status
+ * root@self# cat $DBG_DIR/link
+ *
+ * # Block until the link is up
+ * root@self# echo Y > $DBG_DIR/link_event
+ *
* # Set the doorbell mask
* root@self# echo 's 1' > $DBG_DIR/mask
*
@@ -79,6 +85,13 @@
* root@self# cat $DBG_DIR/spad
*
* Observe that spad 0 and 1 have the values set by the peer.
+ *
+ * # Check the memory window translation info
+ * cat $DBG_DIR/peer_trans0
+ *
+ * # Setup a 16k memory window buffer
+ * echo 16384 > $DBG_DIR/peer_trans0
+ *
*/
#include <linux/init.h>
@@ -89,6 +102,7 @@
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <linux/ntb.h>
@@ -105,11 +119,27 @@ MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
+#define MAX_MWS 16
+
static struct dentry *tool_dbgfs;
+struct tool_mw {
+ int idx;
+ struct tool_ctx *tc;
+ resource_size_t win_size;
+ resource_size_t size;
+ u8 __iomem *local;
+ u8 *peer;
+ dma_addr_t peer_dma;
+ struct dentry *peer_dbg_file;
+};
+
struct tool_ctx {
struct ntb_dev *ntb;
struct dentry *dbgfs;
+ wait_queue_head_t link_wq;
+ int mw_count;
+ struct tool_mw mws[MAX_MWS];
};
#define SPAD_FNAME_SIZE 0x10
@@ -135,6 +165,8 @@ static void tool_link_event(void *ctx)
dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n",
up ? "up" : "down", speed, width);
+
+ wake_up(&tc->link_wq);
}
static void tool_db_event(void *ctx, int vec)
@@ -239,7 +271,14 @@ static ssize_t tool_spadfn_read(struct tool_ctx *tc, char __user *ubuf,
if (!spad_read_fn)
return -EINVAL;
- buf_size = min_t(size_t, size, 0x100);
+ spad_count = ntb_spad_count(tc->ntb);
+
+ /*
+ * We multiply the number of spads by 15 to get the buffer size
+ * this is from 3 for the %d, 10 for the largest hex value
+ * (0x00000000) and 2 for the tab and line feed.
+ */
+ buf_size = min_t(size_t, size, spad_count * 15);
buf = kmalloc(buf_size, GFP_KERNEL);
if (!buf)
@@ -247,7 +286,6 @@ static ssize_t tool_spadfn_read(struct tool_ctx *tc, char __user *ubuf,
pos = 0;
- spad_count = ntb_spad_count(tc->ntb);
for (i = 0; i < spad_count; ++i) {
pos += scnprintf(buf + pos, buf_size - pos, "%d\t%#x\n",
i, spad_read_fn(tc->ntb, i));
@@ -268,7 +306,7 @@ static ssize_t tool_spadfn_write(struct tool_ctx *tc,
{
int spad_idx;
u32 spad_val;
- char *buf;
+ char *buf, *buf_ptr;
int pos, n;
ssize_t rc;
@@ -288,14 +326,15 @@ static ssize_t tool_spadfn_write(struct tool_ctx *tc,
}
buf[size] = 0;
-
- n = sscanf(buf, "%d %i%n", &spad_idx, &spad_val, &pos);
+ buf_ptr = buf;
+ n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
while (n == 2) {
+ buf_ptr += pos;
rc = spad_write_fn(tc->ntb, spad_idx, spad_val);
if (rc)
break;
- n = sscanf(buf + pos, "%d %i%n", &spad_idx, &spad_val, &pos);
+ n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
}
if (n < 0)
@@ -442,8 +481,384 @@ static TOOL_FOPS_RDWR(tool_peer_spad_fops,
tool_peer_spad_read,
tool_peer_spad_write);
+static ssize_t tool_link_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ char buf[3];
+
+ buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N';
+ buf[1] = '\n';
+ buf[2] = '\0';
+
+ return simple_read_from_buffer(ubuf, size, offp, buf, 2);
+}
+
+static ssize_t tool_link_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ char buf[32];
+ size_t buf_size;
+ bool val;
+ int rc;
+
+ buf_size = min(size, (sizeof(buf) - 1));
+ if (copy_from_user(buf, ubuf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+
+ rc = strtobool(buf, &val);
+ if (rc)
+ return rc;
+
+ if (val)
+ rc = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
+ else
+ rc = ntb_link_disable(tc->ntb);
+
+ if (rc)
+ return rc;
+
+ return size;
+}
+
+static TOOL_FOPS_RDWR(tool_link_fops,
+ tool_link_read,
+ tool_link_write);
+
+static ssize_t tool_link_event_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_ctx *tc = filep->private_data;
+ char buf[32];
+ size_t buf_size;
+ bool val;
+ int rc;
+
+ buf_size = min(size, (sizeof(buf) - 1));
+ if (copy_from_user(buf, ubuf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+
+ rc = strtobool(buf, &val);
+ if (rc)
+ return rc;
+
+ if (wait_event_interruptible(tc->link_wq,
+ ntb_link_is_up(tc->ntb, NULL, NULL) == val))
+ return -ERESTART;
+
+ return size;
+}
+
+static TOOL_FOPS_RDWR(tool_link_event_fops,
+ NULL,
+ tool_link_event_write);
+
+static ssize_t tool_mw_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+ ssize_t rc;
+ loff_t pos = *offp;
+ void *buf;
+
+ if (mw->local == NULL)
+ return -EIO;
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= mw->win_size || !size)
+ return 0;
+ if (size > mw->win_size - pos)
+ size = mw->win_size - pos;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy_fromio(buf, mw->local + pos, size);
+ rc = copy_to_user(ubuf, buf, size);
+ if (rc == size) {
+ rc = -EFAULT;
+ goto err_free;
+ }
+
+ size -= rc;
+ *offp = pos + size;
+ rc = size;
+
+err_free:
+ kfree(buf);
+
+ return rc;
+}
+
+static ssize_t tool_mw_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+ ssize_t rc;
+ loff_t pos = *offp;
+ void *buf;
+
+ if (pos < 0)
+ return -EINVAL;
+ if (pos >= mw->win_size || !size)
+ return 0;
+ if (size > mw->win_size - pos)
+ size = mw->win_size - pos;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ rc = copy_from_user(buf, ubuf, size);
+ if (rc == size) {
+ rc = -EFAULT;
+ goto err_free;
+ }
+
+ size -= rc;
+ *offp = pos + size;
+ rc = size;
+
+ memcpy_toio(mw->local + pos, buf, size);
+
+err_free:
+ kfree(buf);
+
+ return rc;
+}
+
+static TOOL_FOPS_RDWR(tool_mw_fops,
+ tool_mw_read,
+ tool_mw_write);
+
+static ssize_t tool_peer_mw_read(struct file *filep, char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+
+ if (!mw->peer)
+ return -ENXIO;
+
+ return simple_read_from_buffer(ubuf, size, offp, mw->peer, mw->size);
+}
+
+static ssize_t tool_peer_mw_write(struct file *filep, const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+
+ if (!mw->peer)
+ return -ENXIO;
+
+ return simple_write_to_buffer(mw->peer, mw->size, offp, ubuf, size);
+}
+
+static TOOL_FOPS_RDWR(tool_peer_mw_fops,
+ tool_peer_mw_read,
+ tool_peer_mw_write);
+
+static int tool_setup_mw(struct tool_ctx *tc, int idx, size_t req_size)
+{
+ int rc;
+ struct tool_mw *mw = &tc->mws[idx];
+ phys_addr_t base;
+ resource_size_t size, align, align_size;
+ char buf[16];
+
+ if (mw->peer)
+ return 0;
+
+ rc = ntb_mw_get_range(tc->ntb, idx, &base, &size, &align,
+ &align_size);
+ if (rc)
+ return rc;
+
+ mw->size = min_t(resource_size_t, req_size, size);
+ mw->size = round_up(mw->size, align);
+ mw->size = round_up(mw->size, align_size);
+ mw->peer = dma_alloc_coherent(&tc->ntb->pdev->dev, mw->size,
+ &mw->peer_dma, GFP_KERNEL);
+
+ if (!mw->peer)
+ return -ENOMEM;
+
+ rc = ntb_mw_set_trans(tc->ntb, idx, mw->peer_dma, mw->size);
+ if (rc)
+ goto err_free_dma;
+
+ snprintf(buf, sizeof(buf), "peer_mw%d", idx);
+ mw->peer_dbg_file = debugfs_create_file(buf, S_IRUSR | S_IWUSR,
+ mw->tc->dbgfs, mw,
+ &tool_peer_mw_fops);
+
+ return 0;
+
+err_free_dma:
+ dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
+ mw->peer,
+ mw->peer_dma);
+ mw->peer = NULL;
+ mw->peer_dma = 0;
+ mw->size = 0;
+
+ return rc;
+}
+
+static void tool_free_mw(struct tool_ctx *tc, int idx)
+{
+ struct tool_mw *mw = &tc->mws[idx];
+
+ if (mw->peer) {
+ ntb_mw_clear_trans(tc->ntb, idx);
+ dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
+ mw->peer,
+ mw->peer_dma);
+ }
+
+ mw->peer = NULL;
+ mw->peer_dma = 0;
+
+ debugfs_remove(mw->peer_dbg_file);
+
+ mw->peer_dbg_file = NULL;
+}
+
+static ssize_t tool_peer_mw_trans_read(struct file *filep,
+ char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+
+ char *buf;
+ size_t buf_size;
+ ssize_t ret, off = 0;
+
+ phys_addr_t base;
+ resource_size_t mw_size;
+ resource_size_t align;
+ resource_size_t align_size;
+
+ buf_size = min_t(size_t, size, 512);
+
+ buf = kmalloc(buf_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ntb_mw_get_range(mw->tc->ntb, mw->idx,
+ &base, &mw_size, &align, &align_size);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Peer MW %d Information:\n", mw->idx);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Physical Address \t%pa[p]\n",
+ &base);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Window Size \t%lld\n",
+ (unsigned long long)mw_size);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Alignment \t%lld\n",
+ (unsigned long long)align);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Size Alignment \t%lld\n",
+ (unsigned long long)align_size);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Ready \t%c\n",
+ (mw->peer) ? 'Y' : 'N');
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Allocated Size \t%zd\n",
+ (mw->peer) ? (size_t)mw->size : 0);
+
+ ret = simple_read_from_buffer(ubuf, size, offp, buf, off);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t tool_peer_mw_trans_write(struct file *filep,
+ const char __user *ubuf,
+ size_t size, loff_t *offp)
+{
+ struct tool_mw *mw = filep->private_data;
+
+ char buf[32];
+ size_t buf_size;
+ unsigned long long val;
+ int rc;
+
+ buf_size = min(size, (sizeof(buf) - 1));
+ if (copy_from_user(buf, ubuf, buf_size))
+ return -EFAULT;
+
+ buf[buf_size] = '\0';
+
+ rc = kstrtoull(buf, 0, &val);
+ if (rc)
+ return rc;
+
+ tool_free_mw(mw->tc, mw->idx);
+ if (val)
+ rc = tool_setup_mw(mw->tc, mw->idx, val);
+
+ if (rc)
+ return rc;
+
+ return size;
+}
+
+static TOOL_FOPS_RDWR(tool_peer_mw_trans_fops,
+ tool_peer_mw_trans_read,
+ tool_peer_mw_trans_write);
+
+static int tool_init_mw(struct tool_ctx *tc, int idx)
+{
+ struct tool_mw *mw = &tc->mws[idx];
+ phys_addr_t base;
+ int rc;
+
+ rc = ntb_mw_get_range(tc->ntb, idx, &base, &mw->win_size,
+ NULL, NULL);
+ if (rc)
+ return rc;
+
+ mw->tc = tc;
+ mw->idx = idx;
+ mw->local = ioremap_wc(base, mw->win_size);
+ if (!mw->local)
+ return -EFAULT;
+
+ return 0;
+}
+
+static void tool_free_mws(struct tool_ctx *tc)
+{
+ int i;
+
+ for (i = 0; i < tc->mw_count; i++) {
+ tool_free_mw(tc, i);
+
+ if (tc->mws[i].local)
+ iounmap(tc->mws[i].local);
+
+ tc->mws[i].local = NULL;
+ }
+}
+
static void tool_setup_dbgfs(struct tool_ctx *tc)
{
+ int i;
+
/* This modules is useless without dbgfs... */
if (!tool_dbgfs) {
tc->dbgfs = NULL;
@@ -472,12 +887,31 @@ static void tool_setup_dbgfs(struct tool_ctx *tc)
debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs,
tc, &tool_peer_spad_fops);
+
+ debugfs_create_file("link", S_IRUSR | S_IWUSR, tc->dbgfs,
+ tc, &tool_link_fops);
+
+ debugfs_create_file("link_event", S_IWUSR, tc->dbgfs,
+ tc, &tool_link_event_fops);
+
+ for (i = 0; i < tc->mw_count; i++) {
+ char buf[30];
+
+ snprintf(buf, sizeof(buf), "mw%d", i);
+ debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
+ &tc->mws[i], &tool_mw_fops);
+
+ snprintf(buf, sizeof(buf), "peer_trans%d", i);
+ debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
+ &tc->mws[i], &tool_peer_mw_trans_fops);
+ }
}
static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
{
struct tool_ctx *tc;
int rc;
+ int i;
if (ntb_db_is_unsafe(ntb))
dev_dbg(&ntb->dev, "doorbell is unsafe\n");
@@ -485,13 +919,21 @@ static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
if (ntb_spad_is_unsafe(ntb))
dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
- tc = kmalloc(sizeof(*tc), GFP_KERNEL);
+ tc = kzalloc(sizeof(*tc), GFP_KERNEL);
if (!tc) {
rc = -ENOMEM;
goto err_tc;
}
tc->ntb = ntb;
+ init_waitqueue_head(&tc->link_wq);
+
+ tc->mw_count = min(ntb_mw_count(tc->ntb), MAX_MWS);
+ for (i = 0; i < tc->mw_count; i++) {
+ rc = tool_init_mw(tc, i);
+ if (rc)
+ goto err_ctx;
+ }
tool_setup_dbgfs(tc);
@@ -505,6 +947,7 @@ static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
return 0;
err_ctx:
+ tool_free_mws(tc);
debugfs_remove_recursive(tc->dbgfs);
kfree(tc);
err_tc:
@@ -515,6 +958,8 @@ static void tool_remove(struct ntb_client *self, struct ntb_dev *ntb)
{
struct tool_ctx *tc = ntb->ctx;
+ tool_free_mws(tc);
+
ntb_clear_ctx(ntb);
ntb_link_disable(ntb);
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 9dce03f420eb..368795aad5c9 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1133,11 +1133,11 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip,
static int btt_do_bvec(struct btt *btt, struct bio_integrity_payload *bip,
struct page *page, unsigned int len, unsigned int off,
- int rw, sector_t sector)
+ bool is_write, sector_t sector)
{
int ret;
- if (rw == READ) {
+ if (!is_write) {
ret = btt_read_pg(btt, bip, page, off, sector, len);
flush_dcache_page(page);
} else {
@@ -1155,7 +1155,7 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
struct bvec_iter iter;
unsigned long start;
struct bio_vec bvec;
- int err = 0, rw;
+ int err = 0;
bool do_acct;
/*
@@ -1170,7 +1170,6 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
}
do_acct = nd_iostat_start(bio, &start);
- rw = bio_data_dir(bio);
bio_for_each_segment(bvec, bio, iter) {
unsigned int len = bvec.bv_len;
@@ -1181,11 +1180,12 @@ static blk_qc_t btt_make_request(struct request_queue *q, struct bio *bio)
BUG_ON(len % btt->sector_size);
err = btt_do_bvec(btt, bip, bvec.bv_page, len, bvec.bv_offset,
- rw, iter.bi_sector);
+ op_is_write(bio_op(bio)), iter.bi_sector);
if (err) {
dev_info(&btt->nd_btt->dev,
"io error in %s sector %lld, len %d,\n",
- (rw == READ) ? "READ" : "WRITE",
+ (op_is_write(bio_op(bio))) ? "WRITE" :
+ "READ",
(unsigned long long) iter.bi_sector, len);
bio->bi_error = err;
break;
@@ -1200,12 +1200,12 @@ out:
}
static int btt_rw_page(struct block_device *bdev, sector_t sector,
- struct page *page, int rw)
+ struct page *page, bool is_write)
{
struct btt *btt = bdev->bd_disk->private_data;
- btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, rw, sector);
- page_endio(page, rw & WRITE, 0);
+ btt_do_bvec(btt, NULL, page, PAGE_SIZE, 0, is_write, sector);
+ page_endio(page, is_write, 0);
return 0;
}
@@ -1269,6 +1269,7 @@ static int btt_blk_init(struct btt *btt)
}
}
set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
+ btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
revalidate_disk(btt->btt_disk);
return 0;
diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index 3fa7919f94a8..97dd2925ed6e 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -140,10 +140,30 @@ static ssize_t namespace_store(struct device *dev,
}
static DEVICE_ATTR_RW(namespace);
+static ssize_t size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nd_btt *nd_btt = to_nd_btt(dev);
+ ssize_t rc;
+
+ device_lock(dev);
+ if (dev->driver)
+ rc = sprintf(buf, "%llu\n", nd_btt->size);
+ else {
+ /* no size to convey if the btt instance is disabled */
+ rc = -ENXIO;
+ }
+ device_unlock(dev);
+
+ return rc;
+}
+static DEVICE_ATTR_RO(size);
+
static struct attribute *nd_btt_attributes[] = {
&dev_attr_sector_size.attr,
&dev_attr_namespace.attr,
&dev_attr_uuid.attr,
+ &dev_attr_size.attr,
NULL,
};
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 40476399d227..8024a0ef86d3 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -143,6 +143,7 @@ struct nd_btt {
struct nd_namespace_common *ndns;
struct btt *btt;
unsigned long lbasize;
+ u64 size;
u8 *uuid;
int id;
};
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index b511099457db..571a6c7ee2fc 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -67,7 +67,7 @@ static void pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset,
}
static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
- unsigned int len, unsigned int off, int rw,
+ unsigned int len, unsigned int off, bool is_write,
sector_t sector)
{
int rc = 0;
@@ -79,7 +79,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
if (unlikely(is_bad_pmem(&pmem->bb, sector, len)))
bad_pmem = true;
- if (rw == READ) {
+ if (!is_write) {
if (unlikely(bad_pmem))
rc = -EIO;
else {
@@ -128,13 +128,13 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
struct pmem_device *pmem = q->queuedata;
struct nd_region *nd_region = to_region(pmem);
- if (bio->bi_rw & REQ_FLUSH)
+ if (bio->bi_opf & REQ_FLUSH)
nvdimm_flush(nd_region);
do_acct = nd_iostat_start(bio, &start);
bio_for_each_segment(bvec, bio, iter) {
rc = pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len,
- bvec.bv_offset, bio_data_dir(bio),
+ bvec.bv_offset, op_is_write(bio_op(bio)),
iter.bi_sector);
if (rc) {
bio->bi_error = rc;
@@ -144,7 +144,7 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
if (do_acct)
nd_iostat_end(bio, start);
- if (bio->bi_rw & REQ_FUA)
+ if (bio->bi_opf & REQ_FUA)
nvdimm_flush(nd_region);
bio_endio(bio);
@@ -152,12 +152,12 @@ static blk_qc_t pmem_make_request(struct request_queue *q, struct bio *bio)
}
static int pmem_rw_page(struct block_device *bdev, sector_t sector,
- struct page *page, int rw)
+ struct page *page, bool is_write)
{
struct pmem_device *pmem = bdev->bd_queue->queuedata;
int rc;
- rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, rw, sector);
+ rc = pmem_do_bvec(pmem, page, PAGE_SIZE, 0, is_write, sector);
/*
* The ->rw_page interface is subtle and tricky. The core
@@ -166,7 +166,7 @@ static int pmem_rw_page(struct block_device *bdev, sector_t sector,
* caused by double completion.
*/
if (rc == 0)
- page_endio(page, rw & WRITE, 0);
+ page_endio(page, is_write, 0);
return rc;
}
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index d7c33f9361aa..8dcf5a960951 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -1543,15 +1543,10 @@ static void nvme_disable_io_queues(struct nvme_dev *dev)
reinit_completion(&dev->ioq_wait);
retry:
timeout = ADMIN_TIMEOUT;
- for (; i > 0; i--) {
- struct nvme_queue *nvmeq = dev->queues[i];
-
- if (!pass)
- nvme_suspend_queue(nvmeq);
- if (nvme_delete_queue(nvmeq, opcode))
+ for (; i > 0; i--, sent++)
+ if (nvme_delete_queue(dev->queues[i], opcode))
break;
- ++sent;
- }
+
while (sent--) {
timeout = wait_for_completion_io_timeout(&dev->ioq_wait, timeout);
if (timeout == 0)
@@ -1693,11 +1688,12 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
nvme_stop_queues(&dev->ctrl);
csts = readl(dev->bar + NVME_REG_CSTS);
}
+
+ for (i = dev->queue_count - 1; i > 0; i--)
+ nvme_suspend_queue(dev->queues[i]);
+
if (csts & NVME_CSTS_CFS || !(csts & NVME_CSTS_RDY)) {
- for (i = dev->queue_count - 1; i >= 0; i--) {
- struct nvme_queue *nvmeq = dev->queues[i];
- nvme_suspend_queue(nvmeq);
- }
+ nvme_suspend_queue(dev->queues[0]);
} else {
nvme_disable_io_queues(dev);
nvme_disable_admin_queue(dev, shutdown);
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 3e3ce2b0424e..8d2875b4c56d 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -12,13 +12,11 @@
* more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/delay.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/string.h>
-#include <linux/jiffies.h>
#include <linux/atomic.h>
#include <linux/blk-mq.h>
#include <linux/types.h>
@@ -26,7 +24,6 @@
#include <linux/mutex.h>
#include <linux/scatterlist.h>
#include <linux/nvme.h>
-#include <linux/t10-pi.h>
#include <asm/unaligned.h>
#include <rdma/ib_verbs.h>
@@ -169,7 +166,6 @@ MODULE_PARM_DESC(register_always,
static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event);
static void nvme_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
-static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl);
/* XXX: really should move to a generic header sooner or later.. */
static inline void put_unaligned_le24(u32 val, u8 *p)
@@ -687,11 +683,6 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
list_del(&ctrl->list);
mutex_unlock(&nvme_rdma_ctrl_mutex);
- if (ctrl->ctrl.tagset) {
- blk_cleanup_queue(ctrl->ctrl.connect_q);
- blk_mq_free_tag_set(&ctrl->tag_set);
- nvme_rdma_dev_put(ctrl->device);
- }
kfree(ctrl->queues);
nvmf_free_options(nctrl->opts);
free_ctrl:
@@ -748,8 +739,11 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
WARN_ON_ONCE(!changed);
- if (ctrl->queue_count > 1)
+ if (ctrl->queue_count > 1) {
nvme_start_queues(&ctrl->ctrl);
+ nvme_queue_scan(&ctrl->ctrl);
+ nvme_queue_async_events(&ctrl->ctrl);
+ }
dev_info(ctrl->ctrl.device, "Successfully reconnected\n");
@@ -1269,7 +1263,7 @@ static int nvme_rdma_route_resolved(struct nvme_rdma_queue *queue)
{
struct nvme_rdma_ctrl *ctrl = queue->ctrl;
struct rdma_conn_param param = { };
- struct nvme_rdma_cm_req priv;
+ struct nvme_rdma_cm_req priv = { };
int ret;
param.qp_num = queue->qp->qp_num;
@@ -1318,37 +1312,39 @@ out_destroy_queue_ib:
* that caught the event. Since we hold the callout until the controller
* deletion is completed, we'll deadlock if the controller deletion will
* call rdma_destroy_id on this queue's cm_id. Thus, we claim ownership
- * of destroying this queue before-hand, destroy the queue resources
- * after the controller deletion completed with the exception of destroying
- * the cm_id implicitely by returning a non-zero rc to the callout.
+ * of destroying this queue before-hand, destroy the queue resources,
+ * then queue the controller deletion which won't destroy this queue and
+ * we destroy the cm_id implicitely by returning a non-zero rc to the callout.
*/
static int nvme_rdma_device_unplug(struct nvme_rdma_queue *queue)
{
struct nvme_rdma_ctrl *ctrl = queue->ctrl;
- int ret, ctrl_deleted = 0;
+ int ret;
- /* First disable the queue so ctrl delete won't free it */
- if (!test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags))
- goto out;
+ /* Own the controller deletion */
+ if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING))
+ return 0;
- /* delete the controller */
- ret = __nvme_rdma_del_ctrl(ctrl);
- if (!ret) {
- dev_warn(ctrl->ctrl.device,
- "Got rdma device removal event, deleting ctrl\n");
- flush_work(&ctrl->delete_work);
+ dev_warn(ctrl->ctrl.device,
+ "Got rdma device removal event, deleting ctrl\n");
- /* Return non-zero so the cm_id will destroy implicitly */
- ctrl_deleted = 1;
+ /* Get rid of reconnect work if its running */
+ cancel_delayed_work_sync(&ctrl->reconnect_work);
+ /* Disable the queue so ctrl delete won't free it */
+ if (test_and_clear_bit(NVME_RDMA_Q_CONNECTED, &queue->flags)) {
/* Free this queue ourselves */
- rdma_disconnect(queue->cm_id);
- ib_drain_qp(queue->qp);
+ nvme_rdma_stop_queue(queue);
nvme_rdma_destroy_queue_ib(queue);
+
+ /* Return non-zero so the cm_id will destroy implicitly */
+ ret = 1;
}
-out:
- return ctrl_deleted;
+ /* Queue controller deletion */
+ queue_work(nvme_rdma_wq, &ctrl->delete_work);
+ flush_work(&ctrl->delete_work);
+ return ret;
}
static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id,
@@ -1648,7 +1644,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)
nvme_rdma_free_io_queues(ctrl);
}
- if (ctrl->ctrl.state == NVME_CTRL_LIVE)
+ if (test_bit(NVME_RDMA_Q_CONNECTED, &ctrl->queues[0].flags))
nvme_shutdown_ctrl(&ctrl->ctrl);
blk_mq_stop_hw_queues(ctrl->ctrl.admin_q);
@@ -1657,15 +1653,27 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl)
nvme_rdma_destroy_admin_queue(ctrl);
}
+static void __nvme_rdma_remove_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
+{
+ nvme_uninit_ctrl(&ctrl->ctrl);
+ if (shutdown)
+ nvme_rdma_shutdown_ctrl(ctrl);
+
+ if (ctrl->ctrl.tagset) {
+ blk_cleanup_queue(ctrl->ctrl.connect_q);
+ blk_mq_free_tag_set(&ctrl->tag_set);
+ nvme_rdma_dev_put(ctrl->device);
+ }
+
+ nvme_put_ctrl(&ctrl->ctrl);
+}
+
static void nvme_rdma_del_ctrl_work(struct work_struct *work)
{
struct nvme_rdma_ctrl *ctrl = container_of(work,
struct nvme_rdma_ctrl, delete_work);
- nvme_remove_namespaces(&ctrl->ctrl);
- nvme_rdma_shutdown_ctrl(ctrl);
- nvme_uninit_ctrl(&ctrl->ctrl);
- nvme_put_ctrl(&ctrl->ctrl);
+ __nvme_rdma_remove_ctrl(ctrl, true);
}
static int __nvme_rdma_del_ctrl(struct nvme_rdma_ctrl *ctrl)
@@ -1698,9 +1706,7 @@ static void nvme_rdma_remove_ctrl_work(struct work_struct *work)
struct nvme_rdma_ctrl *ctrl = container_of(work,
struct nvme_rdma_ctrl, delete_work);
- nvme_remove_namespaces(&ctrl->ctrl);
- nvme_uninit_ctrl(&ctrl->ctrl);
- nvme_put_ctrl(&ctrl->ctrl);
+ __nvme_rdma_remove_ctrl(ctrl, false);
}
static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
@@ -1739,6 +1745,7 @@ static void nvme_rdma_reset_ctrl_work(struct work_struct *work)
if (ctrl->queue_count > 1) {
nvme_start_queues(&ctrl->ctrl);
nvme_queue_scan(&ctrl->ctrl);
+ nvme_queue_async_events(&ctrl->ctrl);
}
return;
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 2fac17a5ad53..47c564b5a289 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -13,7 +13,6 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
-#include <linux/random.h>
#include <generated/utsrelease.h>
#include "nvmet.h"
@@ -83,7 +82,6 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
struct nvme_id_ctrl *id;
- u64 serial;
u16 status = 0;
id = kzalloc(sizeof(*id), GFP_KERNEL);
@@ -96,10 +94,8 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->vid = 0;
id->ssvid = 0;
- /* generate a random serial number as our controllers are ephemeral: */
- get_random_bytes(&serial, sizeof(serial));
memset(id->sn, ' ', sizeof(id->sn));
- snprintf(id->sn, sizeof(id->sn), "%llx", serial);
+ snprintf(id->sn, sizeof(id->sn), "%llx", ctrl->serial);
memset(id->mn, ' ', sizeof(id->mn));
strncpy((char *)id->mn, "Linux", sizeof(id->mn));
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 8a891ca53367..6559d5afa7bf 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -13,6 +13,7 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
+#include <linux/random.h>
#include "nvmet.h"
static struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX];
@@ -728,6 +729,9 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
memcpy(ctrl->subsysnqn, subsysnqn, NVMF_NQN_SIZE);
memcpy(ctrl->hostnqn, hostnqn, NVMF_NQN_SIZE);
+ /* generate a random serial number as our controllers are ephemeral: */
+ get_random_bytes(&ctrl->serial, sizeof(ctrl->serial));
+
kref_init(&ctrl->ref);
ctrl->subsys = subsys;
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 94e782987cc9..7affd40a6b33 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -414,9 +414,8 @@ static void nvme_loop_del_ctrl_work(struct work_struct *work)
struct nvme_loop_ctrl *ctrl = container_of(work,
struct nvme_loop_ctrl, delete_work);
- nvme_remove_namespaces(&ctrl->ctrl);
- nvme_loop_shutdown_ctrl(ctrl);
nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_loop_shutdown_ctrl(ctrl);
nvme_put_ctrl(&ctrl->ctrl);
}
@@ -501,7 +500,6 @@ out_free_queues:
nvme_loop_destroy_admin_queue(ctrl);
out_disable:
dev_warn(ctrl->ctrl.device, "Removing after reset failure\n");
- nvme_remove_namespaces(&ctrl->ctrl);
nvme_uninit_ctrl(&ctrl->ctrl);
nvme_put_ctrl(&ctrl->ctrl);
}
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 57dd6d834c28..76b6eedccaf9 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -113,6 +113,7 @@ struct nvmet_ctrl {
struct mutex lock;
u64 cap;
+ u64 serial;
u32 cc;
u32 csts;
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
index e06d504bdf0c..b4d648536c3e 100644
--- a/drivers/nvme/target/rdma.c
+++ b/drivers/nvme/target/rdma.c
@@ -77,6 +77,7 @@ enum nvmet_rdma_queue_state {
NVMET_RDMA_Q_CONNECTING,
NVMET_RDMA_Q_LIVE,
NVMET_RDMA_Q_DISCONNECTING,
+ NVMET_RDMA_IN_DEVICE_REMOVAL,
};
struct nvmet_rdma_queue {
@@ -615,15 +616,10 @@ static u16 nvmet_rdma_map_sgl_keyed(struct nvmet_rdma_rsp *rsp,
if (!len)
return 0;
- /* use the already allocated data buffer if possible */
- if (len <= NVMET_RDMA_INLINE_DATA_SIZE && rsp->queue->host_qid) {
- nvmet_rdma_use_inline_sg(rsp, len, 0);
- } else {
- status = nvmet_rdma_alloc_sgl(&rsp->req.sg, &rsp->req.sg_cnt,
- len);
- if (status)
- return status;
- }
+ status = nvmet_rdma_alloc_sgl(&rsp->req.sg, &rsp->req.sg_cnt,
+ len);
+ if (status)
+ return status;
ret = rdma_rw_ctx_init(&rsp->rw, cm_id->qp, cm_id->port_num,
rsp->req.sg, rsp->req.sg_cnt, 0, addr, key,
@@ -984,7 +980,10 @@ static void nvmet_rdma_release_queue_work(struct work_struct *w)
struct nvmet_rdma_device *dev = queue->dev;
nvmet_rdma_free_queue(queue);
- rdma_destroy_id(cm_id);
+
+ if (queue->state != NVMET_RDMA_IN_DEVICE_REMOVAL)
+ rdma_destroy_id(cm_id);
+
kref_put(&dev->ref, nvmet_rdma_free_dev);
}
@@ -1233,8 +1232,9 @@ static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue)
switch (queue->state) {
case NVMET_RDMA_Q_CONNECTING:
case NVMET_RDMA_Q_LIVE:
- disconnect = true;
queue->state = NVMET_RDMA_Q_DISCONNECTING;
+ case NVMET_RDMA_IN_DEVICE_REMOVAL:
+ disconnect = true;
break;
case NVMET_RDMA_Q_DISCONNECTING:
break;
@@ -1272,6 +1272,62 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,
schedule_work(&queue->release_work);
}
+/**
+ * nvme_rdma_device_removal() - Handle RDMA device removal
+ * @queue: nvmet rdma queue (cm id qp_context)
+ * @addr: nvmet address (cm_id context)
+ *
+ * DEVICE_REMOVAL event notifies us that the RDMA device is about
+ * to unplug so we should take care of destroying our RDMA resources.
+ * This event will be generated for each allocated cm_id.
+ *
+ * Note that this event can be generated on a normal queue cm_id
+ * and/or a device bound listener cm_id (where in this case
+ * queue will be null).
+ *
+ * we claim ownership on destroying the cm_id. For queues we move
+ * the queue state to NVMET_RDMA_IN_DEVICE_REMOVAL and for port
+ * we nullify the priv to prevent double cm_id destruction and destroying
+ * the cm_id implicitely by returning a non-zero rc to the callout.
+ */
+static int nvmet_rdma_device_removal(struct rdma_cm_id *cm_id,
+ struct nvmet_rdma_queue *queue)
+{
+ unsigned long flags;
+
+ if (!queue) {
+ struct nvmet_port *port = cm_id->context;
+
+ /*
+ * This is a listener cm_id. Make sure that
+ * future remove_port won't invoke a double
+ * cm_id destroy. use atomic xchg to make sure
+ * we don't compete with remove_port.
+ */
+ if (xchg(&port->priv, NULL) != cm_id)
+ return 0;
+ } else {
+ /*
+ * This is a queue cm_id. Make sure that
+ * release queue will not destroy the cm_id
+ * and schedule all ctrl queues removal (only
+ * if the queue is not disconnecting already).
+ */
+ spin_lock_irqsave(&queue->state_lock, flags);
+ if (queue->state != NVMET_RDMA_Q_DISCONNECTING)
+ queue->state = NVMET_RDMA_IN_DEVICE_REMOVAL;
+ spin_unlock_irqrestore(&queue->state_lock, flags);
+ nvmet_rdma_queue_disconnect(queue);
+ flush_scheduled_work();
+ }
+
+ /*
+ * We need to return 1 so that the core will destroy
+ * it's own ID. What a great API design..
+ */
+ return 1;
+}
+
static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id,
struct rdma_cm_event *event)
{
@@ -1294,20 +1350,11 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id,
break;
case RDMA_CM_EVENT_ADDR_CHANGE:
case RDMA_CM_EVENT_DISCONNECTED:
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
case RDMA_CM_EVENT_TIMEWAIT_EXIT:
- /*
- * We can get the device removal callback even for a
- * CM ID that we aren't actually using. In that case
- * the context pointer is NULL, so we shouldn't try
- * to disconnect a non-existing queue. But we also
- * need to return 1 so that the core will destroy
- * it's own ID. What a great API design..
- */
- if (queue)
- nvmet_rdma_queue_disconnect(queue);
- else
- ret = 1;
+ nvmet_rdma_queue_disconnect(queue);
+ break;
+ case RDMA_CM_EVENT_DEVICE_REMOVAL:
+ ret = nvmet_rdma_device_removal(cm_id, queue);
break;
case RDMA_CM_EVENT_REJECTED:
case RDMA_CM_EVENT_UNREACHABLE:
@@ -1396,9 +1443,10 @@ out_destroy_id:
static void nvmet_rdma_remove_port(struct nvmet_port *port)
{
- struct rdma_cm_id *cm_id = port->priv;
+ struct rdma_cm_id *cm_id = xchg(&port->priv, NULL);
- rdma_destroy_id(cm_id);
+ if (cm_id)
+ rdma_destroy_id(cm_id);
}
static struct nvmet_fabrics_ops nvmet_rdma_ops = {
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 765390e3ed8d..8aa197691074 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -499,8 +499,24 @@ EXPORT_SYMBOL_GPL(of_platform_default_populate);
static int __init of_platform_default_populate_init(void)
{
- if (of_have_populated_dt())
- of_platform_default_populate(NULL, NULL, NULL);
+ struct device_node *node;
+
+ if (!of_have_populated_dt())
+ return -ENODEV;
+
+ /*
+ * Handle ramoops explicitly, since it is inside /reserved-memory,
+ * which lacks a "compatible" property.
+ */
+ node = of_find_node_by_path("/reserved-memory");
+ if (node) {
+ node = of_find_compatible_node(node, NULL, "ramoops");
+ if (node)
+ of_platform_device_create(node, NULL, NULL);
+ }
+
+ /* Populate everything else. */
+ of_platform_default_populate(NULL, NULL, NULL);
return 0;
}
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
index e24b05996a1b..3ed6238f8f6e 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -790,7 +790,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size,
static dma_addr_t
ccio_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return ccio_map_single(dev, page_address(page) + offset, size,
direction);
@@ -806,7 +806,7 @@ ccio_map_page(struct device *dev, struct page *page, unsigned long offset,
*/
static void
ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
unsigned long flags;
@@ -844,7 +844,7 @@ ccio_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
*/
static void *
ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
#if 0
@@ -878,9 +878,9 @@ ccio_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag,
*/
static void
ccio_free(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
- ccio_unmap_page(dev, dma_handle, size, 0, NULL);
+ ccio_unmap_page(dev, dma_handle, size, 0, 0);
free_pages((unsigned long)cpu_addr, get_order(size));
}
@@ -907,7 +907,7 @@ ccio_free(struct device *dev, size_t size, void *cpu_addr,
*/
static int
ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
int coalesced, filled = 0;
@@ -984,7 +984,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
*/
static void
ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
@@ -1004,7 +1004,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
#endif
ccio_unmap_page(dev, sg_dma_address(sglist),
- sg_dma_len(sglist), direction, NULL);
+ sg_dma_len(sglist), direction, 0);
++sglist;
}
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index 42ec4600b7e4..151b86b6d2e2 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -783,7 +783,7 @@ sba_map_single(struct device *dev, void *addr, size_t size,
static dma_addr_t
sba_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return sba_map_single(dev, page_address(page) + offset, size,
direction);
@@ -801,7 +801,7 @@ sba_map_page(struct device *dev, struct page *page, unsigned long offset,
*/
static void
sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
#if DELAYED_RESOURCE_CNT > 0
@@ -876,7 +876,7 @@ sba_unmap_page(struct device *dev, dma_addr_t iova, size_t size,
* See Documentation/DMA-API-HOWTO.txt
*/
static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp, struct dma_attrs *attrs)
+ gfp_t gfp, unsigned long attrs)
{
void *ret;
@@ -908,9 +908,9 @@ static void *sba_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle
*/
static void
sba_free(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle, struct dma_attrs *attrs)
+ dma_addr_t dma_handle, unsigned long attrs)
{
- sba_unmap_page(hwdev, dma_handle, size, 0, NULL);
+ sba_unmap_page(hwdev, dma_handle, size, 0, 0);
free_pages((unsigned long) vaddr, get_order(size));
}
@@ -943,7 +943,7 @@ int dump_run_sg = 0;
*/
static int
sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
int coalesced, filled = 0;
@@ -1026,7 +1026,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
*/
static void
sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction, struct dma_attrs *attrs)
+ enum dma_data_direction direction, unsigned long attrs)
{
struct ioc *ioc;
#ifdef ASSERT_PDIR_SANITY
@@ -1051,7 +1051,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents,
while (sg_dma_len(sglist) && nents--) {
sba_unmap_page(dev, sg_dma_address(sglist), sg_dma_len(sglist),
- direction, NULL);
+ direction, 0);
#ifdef SBA_COLLECT_STATS
ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT;
ioc->usingle_calls--; /* kluge since call is unmap_sg() */
diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index 66e0d718472f..43ed08dd8b01 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -27,7 +27,7 @@
* since we have enough virtual address range available. On 32-bit, we
* ioremap the config space for each bus individually.
*/
-static const bool per_bus_mapping = !config_enabled(CONFIG_64BIT);
+static const bool per_bus_mapping = !IS_ENABLED(CONFIG_64BIT);
/*
* Create a PCI config space window
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 6a33ddcfa20b..a46b585fae31 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -675,7 +675,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
if (bridge->is_going_away)
return;
- pm_runtime_get_sync(&bridge->pci_dev->dev);
+ if (bridge->pci_dev)
+ pm_runtime_get_sync(&bridge->pci_dev->dev);
list_for_each_entry(slot, &bridge->slots, node) {
struct pci_bus *bus = slot->bus;
@@ -697,7 +698,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
}
}
- pm_runtime_put(&bridge->pci_dev->dev);
+ if (bridge->pci_dev)
+ pm_runtime_put(&bridge->pci_dev->dev);
}
/*
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a02981efdad5..eafa6138a6b8 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1411,6 +1411,8 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
pci_msi_domain_update_chip_ops(info);
+ info->flags |= MSI_FLAG_ACTIVATE_EARLY;
+
domain = msi_create_irq_domain(fwnode, info, parent);
if (!domain)
return NULL;
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 6ccb994bdfcb..c494613c1909 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -688,7 +688,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
return 0;
}
-static DEFINE_MUTEX(arm_pmu_mutex);
+static DEFINE_SPINLOCK(arm_pmu_lock);
static LIST_HEAD(arm_pmu_list);
/*
@@ -701,7 +701,7 @@ static int arm_perf_starting_cpu(unsigned int cpu)
{
struct arm_pmu *pmu;
- mutex_lock(&arm_pmu_mutex);
+ spin_lock(&arm_pmu_lock);
list_for_each_entry(pmu, &arm_pmu_list, entry) {
if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
@@ -709,7 +709,7 @@ static int arm_perf_starting_cpu(unsigned int cpu)
if (pmu->reset)
pmu->reset(pmu);
}
- mutex_unlock(&arm_pmu_mutex);
+ spin_unlock(&arm_pmu_lock);
return 0;
}
@@ -821,9 +821,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
if (!cpu_hw_events)
return -ENOMEM;
- mutex_lock(&arm_pmu_mutex);
+ spin_lock(&arm_pmu_lock);
list_add_tail(&cpu_pmu->entry, &arm_pmu_list);
- mutex_unlock(&arm_pmu_mutex);
+ spin_unlock(&arm_pmu_lock);
err = cpu_pm_pmu_register(cpu_pmu);
if (err)
@@ -859,9 +859,9 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
return 0;
out_unregister:
- mutex_lock(&arm_pmu_mutex);
+ spin_lock(&arm_pmu_lock);
list_del(&cpu_pmu->entry);
- mutex_unlock(&arm_pmu_mutex);
+ spin_unlock(&arm_pmu_lock);
free_percpu(cpu_hw_events);
return err;
}
@@ -869,9 +869,9 @@ out_unregister:
static void cpu_pmu_destroy(struct arm_pmu *cpu_pmu)
{
cpu_pm_pmu_unregister(cpu_pmu);
- mutex_lock(&arm_pmu_mutex);
+ spin_lock(&arm_pmu_lock);
list_del(&cpu_pmu->entry);
- mutex_unlock(&arm_pmu_mutex);
+ spin_unlock(&arm_pmu_lock);
free_percpu(cpu_pmu->hw_events);
}
@@ -967,11 +967,12 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
/* If we didn't manage to parse anything, try the interrupt affinity */
if (cpumask_weight(&pmu->supported_cpus) == 0) {
- if (!using_spi) {
+ int irq = platform_get_irq(pdev, 0);
+
+ if (irq_is_percpu(irq)) {
/* If using PPIs, check the affinity of the partition */
- int ret, irq;
+ int ret;
- irq = platform_get_irq(pdev, 0);
ret = irq_get_percpu_devid_partition(irq, &pmu->supported_cpus);
if (ret) {
kfree(irqs);
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index eb4990ff26ca..7fb765642ee7 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/err.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinconf.h>
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 11623c6b0cb3..44e69c963f5d 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -727,13 +727,7 @@ static int meson_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(pc->pcdev);
}
- ret = meson_gpiolib_register(pc);
- if (ret) {
- pinctrl_unregister(pc->pcdev);
- return ret;
- }
-
- return 0;
+ return meson_gpiolib_register(pc);
}
static struct platform_driver meson_pinctrl_driver = {
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 634b4d30eefb..b3e772390ab6 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -43,17 +43,6 @@ static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
- /*
- * Suppose BIOS or Bootloader sets specific debounce for the
- * GPIO. if not, set debounce to be 2.75ms and remove glitch.
- */
- if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
- pin_reg |= 0xf;
- pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
- pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
- pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
- }
-
pin_reg &= ~BIT(OUTPUT_ENABLE_OFF);
writel(pin_reg, gpio_dev->base + offset * 4);
spin_unlock_irqrestore(&gpio_dev->lock, flags);
@@ -326,15 +315,6 @@ static void amd_gpio_irq_enable(struct irq_data *d)
spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
- /*
- Suppose BIOS or Bootloader sets specific debounce for the
- GPIO. if not, set debounce to be 2.75ms.
- */
- if ((pin_reg & DB_TMR_OUT_MASK) == 0) {
- pin_reg |= 0xf;
- pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
- pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
- }
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c
index c6d410ef8de0..7bad200bd67c 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1432,7 +1432,6 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
{
struct pistachio_pinctrl *pctl;
struct resource *res;
- int ret;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -1464,13 +1463,7 @@ static int pistachio_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(pctl->pctldev);
}
- ret = pistachio_gpio_register(pctl);
- if (ret < 0) {
- pinctrl_unregister(pctl->pctldev);
- return ret;
- }
-
- return 0;
+ return pistachio_gpio_register(pctl);
}
static struct platform_driver pistachio_pinctrl_driver = {
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index b6e161f71b26..6c084b266651 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -380,3 +380,20 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
return ret;
}
EXPORT_SYMBOL(cros_ec_cmd_xfer);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg)
+{
+ int ret;
+
+ ret = cros_ec_cmd_xfer(ec_dev, msg);
+ if (ret < 0) {
+ dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+ } else if (msg->result != EC_RES_SUCCESS) {
+ dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
+ return -EPROTO;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index d2bc092defd7..da2fe18162e1 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -110,8 +110,8 @@ static const struct key_entry dell_wmi_keymap_type_0000[] __initconst = {
/* BIOS error detected */
{ KE_IGNORE, 0xe00d, { KEY_RESERVED } },
- /* Unknown, defined in ACPI DSDT */
- /* { KE_IGNORE, 0xe00e, { KEY_RESERVED } }, */
+ /* Battery was removed or inserted */
+ { KE_IGNORE, 0xe00e, { KEY_RESERVED } },
/* Wifi Catcher */
{ KE_KEY, 0xe011, { KEY_PROG2 } },
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index bedb361746a0..c38a5b9733c8 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -60,6 +60,7 @@
#include <linux/delay.h>
#include <linux/acpi.h>
#include <linux/freezer.h>
+#include <linux/kmod.h>
#include <linux/kthread.h>
#include <asm/page.h>
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 9c65f134d447..da7a75f82489 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -457,13 +457,16 @@ static inline void max17042_write_model_data(struct max17042_chip *chip,
}
static inline void max17042_read_model_data(struct max17042_chip *chip,
- u8 addr, u32 *data, int size)
+ u8 addr, u16 *data, int size)
{
struct regmap *map = chip->regmap;
int i;
+ u32 tmp;
- for (i = 0; i < size; i++)
- regmap_read(map, addr + i, &data[i]);
+ for (i = 0; i < size; i++) {
+ regmap_read(map, addr + i, &tmp);
+ data[i] = (u16)tmp;
+ }
}
static inline int max17042_model_data_compare(struct max17042_chip *chip,
@@ -486,7 +489,7 @@ static int max17042_init_model(struct max17042_chip *chip)
{
int ret;
int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
- u32 *temp_data;
+ u16 *temp_data;
temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
if (!temp_data)
@@ -501,7 +504,7 @@ static int max17042_init_model(struct max17042_chip *chip)
ret = max17042_model_data_compare(
chip,
chip->pdata->config_data->cell_char_tbl,
- (u16 *)temp_data,
+ temp_data,
table_size);
max10742_lock_model(chip);
@@ -514,7 +517,7 @@ static int max17042_verify_model_lock(struct max17042_chip *chip)
{
int i;
int table_size = ARRAY_SIZE(chip->pdata->config_data->cell_char_tbl);
- u32 *temp_data;
+ u16 *temp_data;
int ret = 0;
temp_data = kcalloc(table_size, sizeof(*temp_data), GFP_KERNEL);
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 3bfac539334b..c74c3f67b8da 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -200,8 +200,8 @@ config REBOOT_MODE
config SYSCON_REBOOT_MODE
tristate "Generic SYSCON regmap reboot mode driver"
depends on OF
+ depends on MFD_SYSCON
select REBOOT_MODE
- select MFD_SYSCON
help
Say y here will enable reboot mode driver. This will
get reboot mode arguments and store it in SYSCON mapped
diff --git a/drivers/power/reset/hisi-reboot.c b/drivers/power/reset/hisi-reboot.c
index 9ab7f562a83b..f69387e12c1e 100644
--- a/drivers/power/reset/hisi-reboot.c
+++ b/drivers/power/reset/hisi-reboot.c
@@ -53,13 +53,16 @@ static int hisi_reboot_probe(struct platform_device *pdev)
if (of_property_read_u32(np, "reboot-offset", &reboot_offset) < 0) {
pr_err("failed to find reboot-offset property\n");
+ iounmap(base);
return -EINVAL;
}
err = register_restart_handler(&hisi_restart_nb);
- if (err)
+ if (err) {
dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
err);
+ iounmap(base);
+ }
return err;
}
diff --git a/drivers/power/tps65217_charger.c b/drivers/power/tps65217_charger.c
index 73dfae41def8..4c56e54af6ac 100644
--- a/drivers/power/tps65217_charger.c
+++ b/drivers/power/tps65217_charger.c
@@ -206,6 +206,7 @@ static int tps65217_charger_probe(struct platform_device *pdev)
if (!charger)
return -ENOMEM;
+ platform_set_drvdata(pdev, charger);
charger->tps = tps;
charger->dev = &pdev->dev;
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc62c7b..80a566a00d04 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -74,6 +74,16 @@ config PWM_ATMEL_TCB
To compile this driver as a module, choose M here: the module
will be called pwm-atmel-tcb.
+config PWM_BCM_IPROC
+ tristate "iProc PWM support"
+ depends on ARCH_BCM_IPROC
+ help
+ Generic PWM framework driver for Broadcom iProc PWM block. This
+ block is used in Broadcom iProc SoC's.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-bcm-iproc.
+
config PWM_BCM_KONA
tristate "Kona PWM support"
depends on ARCH_BCM_MOBILE
@@ -137,6 +147,13 @@ config PWM_CRC
Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM
control.
+config PWM_CROS_EC
+ tristate "ChromeOS EC PWM driver"
+ depends on MFD_CROS_EC
+ help
+ PWM driver for exposing a PWM attached to the ChromeOS Embedded
+ Controller.
+
config PWM_EP93XX
tristate "Cirrus Logic EP93xx PWM support"
depends on ARCH_EP93XX
@@ -305,7 +322,7 @@ config PWM_PXA
config PWM_RCAR
tristate "Renesas R-Car PWM support"
- depends on ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || COMPILE_TEST
+ depends on ARCH_RENESAS || COMPILE_TEST
depends on HAS_IOMEM
help
This driver exposes the PWM Timer controller found in Renesas
@@ -362,6 +379,13 @@ config PWM_STI
To compile this driver as a module, choose M here: the module
will be called pwm-sti.
+config PWM_STMPE
+ bool "STMPE expander PWM export"
+ depends on MFD_STMPE
+ help
+ This enables support for the PWMs found in the STMPE I/O
+ expanders.
+
config PWM_SUN4I
tristate "Allwinner PWM support"
depends on ARCH_SUNXI || COMPILE_TEST
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc121a18..feef1dd29f73 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o
obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o
@@ -11,6 +12,7 @@ obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o
obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o
obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o
obj-$(CONFIG_PWM_CRC) += pwm-crc.o
+obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o
obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o
obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o
obj-$(CONFIG_PWM_IMG) += pwm-img.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
obj-$(CONFIG_PWM_STI) += pwm-sti.o
+obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o
obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o
obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index ed337a8c34ab..0dbd29e287db 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -526,6 +526,33 @@ int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *state)
EXPORT_SYMBOL_GPL(pwm_apply_state);
/**
+ * pwm_capture() - capture and report a PWM signal
+ * @pwm: PWM device
+ * @result: structure to fill with capture result
+ * @timeout: time to wait, in milliseconds, before giving up on capture
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+ unsigned long timeout)
+{
+ int err;
+
+ if (!pwm || !pwm->chip->ops)
+ return -EINVAL;
+
+ if (!pwm->chip->ops->capture)
+ return -ENOSYS;
+
+ mutex_lock(&pwm_lock);
+ err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
+ mutex_unlock(&pwm_lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(pwm_capture);
+
+/**
* pwm_adjust_config() - adjust the current PWM config to the PWM arguments
* @pwm: PWM device
*
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
index 0e4bd4e8e582..e6b8b1b7e6ba 100644
--- a/drivers/pwm/pwm-atmel.c
+++ b/drivers/pwm/pwm-atmel.c
@@ -64,7 +64,8 @@ struct atmel_pwm_chip {
void __iomem *base;
unsigned int updated_pwms;
- struct mutex isr_lock; /* ISR is cleared when read, ensure only one thread does that */
+ /* ISR is cleared when read, ensure only one thread does that */
+ struct mutex isr_lock;
void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
unsigned long dty, unsigned long prd);
@@ -271,6 +272,16 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
mutex_unlock(&atmel_pwm->isr_lock);
atmel_pwm_writel(atmel_pwm, PWM_DIS, 1 << pwm->hwpwm);
+ /*
+ * Wait for the PWM channel disable operation to be effective before
+ * stopping the clock.
+ */
+ timeout = jiffies + 2 * HZ;
+
+ while ((atmel_pwm_readl(atmel_pwm, PWM_SR) & (1 << pwm->hwpwm)) &&
+ time_before(jiffies, timeout))
+ usleep_range(10, 100);
+
clk_disable(atmel_pwm->clk);
}
@@ -324,21 +335,14 @@ MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
static inline const struct atmel_pwm_data *
atmel_pwm_get_driver_data(struct platform_device *pdev)
{
- if (pdev->dev.of_node) {
- const struct of_device_id *match;
-
- match = of_match_device(atmel_pwm_dt_ids, &pdev->dev);
- if (!match)
- return NULL;
+ const struct platform_device_id *id;
- return match->data;
- } else {
- const struct platform_device_id *id;
+ if (pdev->dev.of_node)
+ return of_device_get_match_data(&pdev->dev);
- id = platform_get_device_id(pdev);
+ id = platform_get_device_id(pdev);
- return (struct atmel_pwm_data *)id->driver_data;
- }
+ return (struct atmel_pwm_data *)id->driver_data;
}
static int atmel_pwm_probe(struct platform_device *pdev)
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
new file mode 100644
index 000000000000..d961a8207b1c
--- /dev/null
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 "as is" 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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define IPROC_PWM_CTRL_OFFSET 0x00
+#define IPROC_PWM_CTRL_TYPE_SHIFT(ch) (15 + (ch))
+#define IPROC_PWM_CTRL_POLARITY_SHIFT(ch) (8 + (ch))
+#define IPROC_PWM_CTRL_EN_SHIFT(ch) (ch)
+
+#define IPROC_PWM_PERIOD_OFFSET(ch) (0x04 + ((ch) << 3))
+#define IPROC_PWM_PERIOD_MIN 0x02
+#define IPROC_PWM_PERIOD_MAX 0xffff
+
+#define IPROC_PWM_DUTY_CYCLE_OFFSET(ch) (0x08 + ((ch) << 3))
+#define IPROC_PWM_DUTY_CYCLE_MIN 0x00
+#define IPROC_PWM_DUTY_CYCLE_MAX 0xffff
+
+#define IPROC_PWM_PRESCALE_OFFSET 0x24
+#define IPROC_PWM_PRESCALE_BITS 0x06
+#define IPROC_PWM_PRESCALE_SHIFT(ch) ((3 - (ch)) * \
+ IPROC_PWM_PRESCALE_BITS)
+#define IPROC_PWM_PRESCALE_MASK(ch) (IPROC_PWM_PRESCALE_MAX << \
+ IPROC_PWM_PRESCALE_SHIFT(ch))
+#define IPROC_PWM_PRESCALE_MIN 0x00
+#define IPROC_PWM_PRESCALE_MAX 0x3f
+
+struct iproc_pwmc {
+ struct pwm_chip chip;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip)
+{
+ return container_of(chip, struct iproc_pwmc, chip);
+}
+
+static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel)
+{
+ u32 value;
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(channel);
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ /* must be a 400 ns delay between clearing and setting enable bit */
+ ndelay(400);
+}
+
+static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel)
+{
+ u32 value;
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(channel));
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ /* must be a 400 ns delay between clearing and setting enable bit */
+ ndelay(400);
+}
+
+static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ u64 tmp, multi, rate;
+ u32 value, prescale;
+
+ rate = clk_get_rate(ip->clk);
+
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm)))
+ state->enabled = true;
+ else
+ state->enabled = false;
+
+ if (value & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm)))
+ state->polarity = PWM_POLARITY_NORMAL;
+ else
+ state->polarity = PWM_POLARITY_INVERSED;
+
+ value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
+ prescale &= IPROC_PWM_PRESCALE_MAX;
+
+ multi = NSEC_PER_SEC * (prescale + 1);
+
+ value = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
+ tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
+ state->period = div64_u64(tmp, rate);
+
+ value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
+ tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
+ state->duty_cycle = div64_u64(tmp, rate);
+}
+
+static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ u32 value, period, duty;
+ u64 rate;
+
+ rate = clk_get_rate(ip->clk);
+
+ /*
+ * Find period count, duty count and prescale to suit duty_cycle and
+ * period. This is done according to formulas described below:
+ *
+ * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
+ * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ *
+ * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+ * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+ */
+ while (1) {
+ u64 value, div;
+
+ div = NSEC_PER_SEC * (prescale + 1);
+ value = rate * state->period;
+ period = div64_u64(value, div);
+ value = rate * state->duty_cycle;
+ duty = div64_u64(value, div);
+
+ if (period < IPROC_PWM_PERIOD_MIN ||
+ duty < IPROC_PWM_DUTY_CYCLE_MIN)
+ return -EINVAL;
+
+ if (period <= IPROC_PWM_PERIOD_MAX &&
+ duty <= IPROC_PWM_DUTY_CYCLE_MAX)
+ break;
+
+ /* Otherwise, increase prescale and recalculate counts */
+ if (++prescale > IPROC_PWM_PRESCALE_MAX)
+ return -EINVAL;
+ }
+
+ iproc_pwmc_disable(ip, pwm->hwpwm);
+
+ /* Set prescale */
+ value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm);
+ value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
+ writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+
+ /* set period and duty cycle */
+ writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
+ writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
+
+ /* set polarity */
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (state->polarity == PWM_POLARITY_NORMAL)
+ value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm);
+ else
+ value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm));
+
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (state->enabled)
+ iproc_pwmc_enable(ip, pwm->hwpwm);
+
+ return 0;
+}
+
+static const struct pwm_ops iproc_pwm_ops = {
+ .apply = iproc_pwmc_apply,
+ .get_state = iproc_pwmc_get_state,
+};
+
+static int iproc_pwmc_probe(struct platform_device *pdev)
+{
+ struct iproc_pwmc *ip;
+ struct resource *res;
+ unsigned int i;
+ u32 value;
+ int ret;
+
+ ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
+ if (!ip)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ip);
+
+ ip->chip.dev = &pdev->dev;
+ ip->chip.ops = &iproc_pwm_ops;
+ ip->chip.base = -1;
+ ip->chip.npwm = 4;
+ ip->chip.of_xlate = of_pwm_xlate_with_flags;
+ ip->chip.of_pwm_n_cells = 3;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ip->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ip->base))
+ return PTR_ERR(ip->base);
+
+ ip->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ip->clk)) {
+ dev_err(&pdev->dev, "failed to get clock: %ld\n",
+ PTR_ERR(ip->clk));
+ return PTR_ERR(ip->clk);
+ }
+
+ ret = clk_prepare_enable(ip->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
+ return ret;
+ }
+
+ /* Set full drive and normal polarity for all channels */
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ for (i = 0; i < ip->chip.npwm; i++) {
+ value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(i));
+ value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(i);
+ }
+
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ ret = pwmchip_add(&ip->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+ clk_disable_unprepare(ip->clk);
+ }
+
+ return ret;
+}
+
+static int iproc_pwmc_remove(struct platform_device *pdev)
+{
+ struct iproc_pwmc *ip = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ip->clk);
+
+ return pwmchip_remove(&ip->chip);
+}
+
+static const struct of_device_id bcm_iproc_pwmc_dt[] = {
+ { .compatible = "brcm,iproc-pwm" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt);
+
+static struct platform_driver iproc_pwmc_driver = {
+ .driver = {
+ .name = "bcm-iproc-pwm",
+ .of_match_table = bcm_iproc_pwmc_dt,
+ },
+ .probe = iproc_pwmc_probe,
+ .remove = iproc_pwmc_remove,
+};
+module_platform_driver(iproc_pwmc_driver);
+
+MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom iProc PWM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
new file mode 100644
index 000000000000..99b9acc1a420
--- /dev/null
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ *
+ * 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.
+ *
+ * Expose a PWM controlled by the ChromeOS EC to the host processor.
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+/**
+ * struct cros_ec_pwm_device - Driver data for EC PWM
+ *
+ * @dev: Device node
+ * @ec: Pointer to EC device
+ * @chip: PWM controller chip
+ */
+struct cros_ec_pwm_device {
+ struct device *dev;
+ struct cros_ec_device *ec;
+ struct pwm_chip chip;
+};
+
+static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c)
+{
+ return container_of(c, struct cros_ec_pwm_device, chip);
+}
+
+static int cros_ec_pwm_set_duty(struct cros_ec_device *ec, u8 index, u16 duty)
+{
+ struct {
+ struct cros_ec_command msg;
+ struct ec_params_pwm_set_duty params;
+ } buf;
+ struct ec_params_pwm_set_duty *params = &buf.params;
+ struct cros_ec_command *msg = &buf.msg;
+
+ memset(&buf, 0, sizeof(buf));
+
+ msg->version = 0;
+ msg->command = EC_CMD_PWM_SET_DUTY;
+ msg->insize = 0;
+ msg->outsize = sizeof(*params);
+
+ params->duty = duty;
+ params->pwm_type = EC_PWM_TYPE_GENERIC;
+ params->index = index;
+
+ return cros_ec_cmd_xfer_status(ec, msg);
+}
+
+static int __cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index,
+ u32 *result)
+{
+ struct {
+ struct cros_ec_command msg;
+ union {
+ struct ec_params_pwm_get_duty params;
+ struct ec_response_pwm_get_duty resp;
+ };
+ } buf;
+ struct ec_params_pwm_get_duty *params = &buf.params;
+ struct ec_response_pwm_get_duty *resp = &buf.resp;
+ struct cros_ec_command *msg = &buf.msg;
+ int ret;
+
+ memset(&buf, 0, sizeof(buf));
+
+ msg->version = 0;
+ msg->command = EC_CMD_PWM_GET_DUTY;
+ msg->insize = sizeof(*params);
+ msg->outsize = sizeof(*resp);
+
+ params->pwm_type = EC_PWM_TYPE_GENERIC;
+ params->index = index;
+
+ ret = cros_ec_cmd_xfer_status(ec, msg);
+ if (result)
+ *result = msg->result;
+ if (ret < 0)
+ return ret;
+
+ return resp->duty;
+}
+
+static int cros_ec_pwm_get_duty(struct cros_ec_device *ec, u8 index)
+{
+ return __cros_ec_pwm_get_duty(ec, index, NULL);
+}
+
+static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
+ int duty_cycle;
+
+ /* The EC won't let us change the period */
+ if (state->period != EC_PWM_MAX_DUTY)
+ return -EINVAL;
+
+ /*
+ * EC doesn't separate the concept of duty cycle and enabled, but
+ * kernel does. Translate.
+ */
+ duty_cycle = state->enabled ? state->duty_cycle : 0;
+
+ return cros_ec_pwm_set_duty(ec_pwm->ec, pwm->hwpwm, duty_cycle);
+}
+
+static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
+ int ret;
+
+ ret = cros_ec_pwm_get_duty(ec_pwm->ec, pwm->hwpwm);
+ if (ret < 0) {
+ dev_err(chip->dev, "error getting initial duty: %d\n", ret);
+ return;
+ }
+
+ state->enabled = (ret > 0);
+ state->period = EC_PWM_MAX_DUTY;
+
+ /* Note that "disabled" and "duty cycle == 0" are treated the same */
+ state->duty_cycle = ret;
+}
+
+static struct pwm_device *
+cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
+{
+ struct pwm_device *pwm;
+
+ if (args->args[0] >= pc->npwm)
+ return ERR_PTR(-EINVAL);
+
+ pwm = pwm_request_from_chip(pc, args->args[0], NULL);
+ if (IS_ERR(pwm))
+ return pwm;
+
+ /* The EC won't let us change the period */
+ pwm->args.period = EC_PWM_MAX_DUTY;
+
+ return pwm;
+}
+
+static const struct pwm_ops cros_ec_pwm_ops = {
+ .get_state = cros_ec_pwm_get_state,
+ .apply = cros_ec_pwm_apply,
+ .owner = THIS_MODULE,
+};
+
+static int cros_ec_num_pwms(struct cros_ec_device *ec)
+{
+ int i, ret;
+
+ /* The index field is only 8 bits */
+ for (i = 0; i <= U8_MAX; i++) {
+ u32 result = 0;
+
+ ret = __cros_ec_pwm_get_duty(ec, i, &result);
+ /* We want to parse EC protocol errors */
+ if (ret < 0 && !(ret == -EPROTO && result))
+ return ret;
+
+ /*
+ * We look for SUCCESS, INVALID_COMMAND, or INVALID_PARAM
+ * responses; everything else is treated as an error.
+ */
+ if (result == EC_RES_INVALID_COMMAND)
+ return -ENODEV;
+ else if (result == EC_RES_INVALID_PARAM)
+ return i;
+ else if (result)
+ return -EPROTO;
+ }
+
+ return U8_MAX;
+}
+
+static int cros_ec_pwm_probe(struct platform_device *pdev)
+{
+ struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct cros_ec_pwm_device *ec_pwm;
+ struct pwm_chip *chip;
+ int ret;
+
+ if (!ec) {
+ dev_err(dev, "no parent EC device\n");
+ return -EINVAL;
+ }
+
+ ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL);
+ if (!ec_pwm)
+ return -ENOMEM;
+ chip = &ec_pwm->chip;
+ ec_pwm->ec = ec;
+
+ /* PWM chip */
+ chip->dev = dev;
+ chip->ops = &cros_ec_pwm_ops;
+ chip->of_xlate = cros_ec_pwm_xlate;
+ chip->of_pwm_n_cells = 1;
+ chip->base = -1;
+ ret = cros_ec_num_pwms(ec);
+ if (ret < 0) {
+ dev_err(dev, "Couldn't find PWMs: %d\n", ret);
+ return ret;
+ }
+ chip->npwm = ret;
+ dev_dbg(dev, "Probed %u PWMs\n", chip->npwm);
+
+ ret = pwmchip_add(chip);
+ if (ret < 0) {
+ dev_err(dev, "cannot register PWM: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, ec_pwm);
+
+ return ret;
+}
+
+static int cros_ec_pwm_remove(struct platform_device *dev)
+{
+ struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev);
+ struct pwm_chip *chip = &ec_pwm->chip;
+
+ return pwmchip_remove(chip);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id cros_ec_pwm_of_match[] = {
+ { .compatible = "google,cros-ec-pwm" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match);
+#endif
+
+static struct platform_driver cros_ec_pwm_driver = {
+ .probe = cros_ec_pwm_probe,
+ .remove = cros_ec_pwm_remove,
+ .driver = {
+ .name = "cros-ec-pwm",
+ .of_match_table = of_match_ptr(cros_ec_pwm_of_match),
+ },
+};
+module_platform_driver(cros_ec_pwm_driver);
+
+MODULE_ALIAS("platform:cros-ec-pwm");
+MODULE_DESCRIPTION("ChromeOS EC PWM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c
index 4d470c1a406a..a9b3cff96aac 100644
--- a/drivers/pwm/pwm-lpc32xx.c
+++ b/drivers/pwm/pwm-lpc32xx.c
@@ -25,6 +25,7 @@ struct lpc32xx_pwm_chip {
};
#define PWM_ENABLE BIT(31)
+#define PWM_PIN_LEVEL BIT(30)
#define to_lpc32xx_pwm_chip(_chip) \
container_of(_chip, struct lpc32xx_pwm_chip, chip)
@@ -103,6 +104,7 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
struct lpc32xx_pwm_chip *lpc32xx;
struct resource *res;
int ret;
+ u32 val;
lpc32xx = devm_kzalloc(&pdev->dev, sizeof(*lpc32xx), GFP_KERNEL);
if (!lpc32xx)
@@ -128,6 +130,11 @@ static int lpc32xx_pwm_probe(struct platform_device *pdev)
return ret;
}
+ /* When PWM is disable, configure the output to the default value */
+ val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
+ val &= ~PWM_PIN_LEVEL;
+ writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
+
platform_set_drvdata(pdev, lpc32xx);
return 0;
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
index 7160e8ab38a4..3622f093490e 100644
--- a/drivers/pwm/pwm-lpss-pci.c
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -76,6 +76,7 @@ static const struct pci_device_id pwm_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x0ac8), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x0f08), (unsigned long)&pwm_lpss_byt_info},
{ PCI_VDEVICE(INTEL, 0x0f09), (unsigned long)&pwm_lpss_byt_info},
+ { PCI_VDEVICE(INTEL, 0x11a5), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x1ac8), (unsigned long)&pwm_lpss_bxt_info},
{ PCI_VDEVICE(INTEL, 0x2288), (unsigned long)&pwm_lpss_bsw_info},
{ PCI_VDEVICE(INTEL, 0x2289), (unsigned long)&pwm_lpss_bsw_info},
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 295b963dbddb..72c0bce5a75c 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -27,7 +27,6 @@
#define PWM_SW_UPDATE BIT(30)
#define PWM_BASE_UNIT_SHIFT 8
#define PWM_ON_TIME_DIV_MASK 0x000000ff
-#define PWM_DIVISION_CORRECTION 0x2
/* Size of each PWM register space if multiple */
#define PWM_SIZE 0x400
@@ -92,8 +91,8 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct pwm_lpss_chip *lpwm = to_lpwm(chip);
- u8 on_time_div;
- unsigned long c, base_unit_range;
+ unsigned long long on_time_div;
+ unsigned long c = lpwm->info->clk_rate, base_unit_range;
unsigned long long base_unit, freq = NSEC_PER_SEC;
u32 ctrl;
@@ -101,21 +100,18 @@ static int pwm_lpss_config(struct pwm_chip *chip, struct pwm_device *pwm,
/*
* The equation is:
- * base_unit = ((freq / c) * base_unit_range) + correction
+ * base_unit = round(base_unit_range * freq / c)
*/
base_unit_range = BIT(lpwm->info->base_unit_bits);
- base_unit = freq * base_unit_range;
+ freq *= base_unit_range;
- c = lpwm->info->clk_rate;
- if (!c)
- return -EINVAL;
-
- do_div(base_unit, c);
- base_unit += PWM_DIVISION_CORRECTION;
+ base_unit = DIV_ROUND_CLOSEST_ULL(freq, c);
if (duty_ns <= 0)
duty_ns = 1;
- on_time_div = 255 - (255 * duty_ns / period_ns);
+ on_time_div = 255ULL * duty_ns;
+ do_div(on_time_div, period_ns);
+ on_time_div = 255ULL - on_time_div;
pm_runtime_get_sync(chip->dev);
@@ -169,6 +165,7 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
const struct pwm_lpss_boardinfo *info)
{
struct pwm_lpss_chip *lpwm;
+ unsigned long c;
int ret;
lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL);
@@ -180,6 +177,11 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
return ERR_CAST(lpwm->regs);
lpwm->info = info;
+
+ c = lpwm->info->clk_rate;
+ if (!c)
+ return ERR_PTR(-EINVAL);
+
lpwm->chip.dev = dev;
lpwm->chip.ops = &pwm_lpss_ops;
lpwm->chip.base = -1;
diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c
index 7d9cc9049522..ef89df1f7336 100644
--- a/drivers/pwm/pwm-rockchip.c
+++ b/drivers/pwm/pwm-rockchip.c
@@ -47,10 +47,14 @@ struct rockchip_pwm_regs {
struct rockchip_pwm_data {
struct rockchip_pwm_regs regs;
unsigned int prescaler;
+ bool supports_polarity;
const struct pwm_ops *ops;
void (*set_enable)(struct pwm_chip *chip,
- struct pwm_device *pwm, bool enable);
+ struct pwm_device *pwm, bool enable,
+ enum pwm_polarity polarity);
+ void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state);
};
static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
@@ -59,7 +63,8 @@ static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
}
static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
- struct pwm_device *pwm, bool enable)
+ struct pwm_device *pwm, bool enable,
+ enum pwm_polarity polarity)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
@@ -75,15 +80,29 @@ static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip,
writel_relaxed(val, pc->base + pc->data->regs.ctrl);
}
+static void rockchip_pwm_get_state_v1(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
+ u32 val;
+
+ val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+ if ((val & enable_conf) == enable_conf)
+ state->enabled = true;
+}
+
static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
- struct pwm_device *pwm, bool enable)
+ struct pwm_device *pwm, bool enable,
+ enum pwm_polarity polarity)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
PWM_CONTINUOUS;
u32 val;
- if (pwm_get_polarity(pwm) == PWM_POLARITY_INVERSED)
+ if (polarity == PWM_POLARITY_INVERSED)
enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE;
else
enable_conf |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE;
@@ -98,13 +117,59 @@ static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip,
writel_relaxed(val, pc->base + pc->data->regs.ctrl);
}
+static void rockchip_pwm_get_state_v2(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
+ PWM_CONTINUOUS;
+ u32 val;
+
+ val = readl_relaxed(pc->base + pc->data->regs.ctrl);
+ if ((val & enable_conf) != enable_conf)
+ return;
+
+ state->enabled = true;
+
+ if (!(val & PWM_DUTY_POSITIVE))
+ state->polarity = PWM_POLARITY_INVERSED;
+}
+
+static void rockchip_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ unsigned long clk_rate;
+ u64 tmp;
+ int ret;
+
+ ret = clk_enable(pc->clk);
+ if (ret)
+ return;
+
+ clk_rate = clk_get_rate(pc->clk);
+
+ tmp = readl_relaxed(pc->base + pc->data->regs.period);
+ tmp *= pc->data->prescaler * NSEC_PER_SEC;
+ state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
+
+ tmp = readl_relaxed(pc->base + pc->data->regs.duty);
+ tmp *= pc->data->prescaler * NSEC_PER_SEC;
+ state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
+
+ pc->data->get_state(chip, pwm, state);
+
+ clk_disable(pc->clk);
+}
+
static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
unsigned long period, duty;
u64 clk_rate, div;
- int ret;
clk_rate = clk_get_rate(pc->clk);
@@ -114,74 +179,72 @@ static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* default prescaler value for all practical clock rate values.
*/
div = clk_rate * period_ns;
- do_div(div, pc->data->prescaler * NSEC_PER_SEC);
- period = div;
+ period = DIV_ROUND_CLOSEST_ULL(div,
+ pc->data->prescaler * NSEC_PER_SEC);
div = clk_rate * duty_ns;
- do_div(div, pc->data->prescaler * NSEC_PER_SEC);
- duty = div;
-
- ret = clk_enable(pc->clk);
- if (ret)
- return ret;
+ duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC);
writel(period, pc->base + pc->data->regs.period);
writel(duty, pc->base + pc->data->regs.duty);
- writel(0, pc->base + pc->data->regs.cntr);
-
- clk_disable(pc->clk);
-
- return 0;
-}
-
-static int rockchip_pwm_set_polarity(struct pwm_chip *chip,
- struct pwm_device *pwm,
- enum pwm_polarity polarity)
-{
- /*
- * No action needed here because pwm->polarity will be set by the core
- * and the core will only change polarity when the PWM is not enabled.
- * We'll handle things in set_enable().
- */
return 0;
}
-static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
{
struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ struct pwm_state curstate;
+ bool enabled;
int ret;
+ pwm_get_state(pwm, &curstate);
+ enabled = curstate.enabled;
+
ret = clk_enable(pc->clk);
if (ret)
return ret;
- pc->data->set_enable(chip, pwm, true);
+ if (state->polarity != curstate.polarity && enabled) {
+ pc->data->set_enable(chip, pwm, false, state->polarity);
+ enabled = false;
+ }
- return 0;
-}
+ ret = rockchip_pwm_config(chip, pwm, state->duty_cycle, state->period);
+ if (ret) {
+ if (enabled != curstate.enabled)
+ pc->data->set_enable(chip, pwm, !enabled,
+ state->polarity);
-static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
- struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
+ goto out;
+ }
+
+ if (state->enabled != enabled)
+ pc->data->set_enable(chip, pwm, state->enabled,
+ state->polarity);
- pc->data->set_enable(chip, pwm, false);
+ /*
+ * Update the state with the real hardware, which can differ a bit
+ * because of period/duty_cycle approximation.
+ */
+ rockchip_pwm_get_state(chip, pwm, state);
+out:
clk_disable(pc->clk);
+
+ return ret;
}
static const struct pwm_ops rockchip_pwm_ops_v1 = {
- .config = rockchip_pwm_config,
- .enable = rockchip_pwm_enable,
- .disable = rockchip_pwm_disable,
+ .get_state = rockchip_pwm_get_state,
+ .apply = rockchip_pwm_apply,
.owner = THIS_MODULE,
};
static const struct pwm_ops rockchip_pwm_ops_v2 = {
- .config = rockchip_pwm_config,
- .set_polarity = rockchip_pwm_set_polarity,
- .enable = rockchip_pwm_enable,
- .disable = rockchip_pwm_disable,
+ .get_state = rockchip_pwm_get_state,
+ .apply = rockchip_pwm_apply,
.owner = THIS_MODULE,
};
@@ -195,6 +258,7 @@ static const struct rockchip_pwm_data pwm_data_v1 = {
.prescaler = 2,
.ops = &rockchip_pwm_ops_v1,
.set_enable = rockchip_pwm_set_enable_v1,
+ .get_state = rockchip_pwm_get_state_v1,
};
static const struct rockchip_pwm_data pwm_data_v2 = {
@@ -205,8 +269,10 @@ static const struct rockchip_pwm_data pwm_data_v2 = {
.ctrl = 0x0c,
},
.prescaler = 1,
+ .supports_polarity = true,
.ops = &rockchip_pwm_ops_v2,
.set_enable = rockchip_pwm_set_enable_v2,
+ .get_state = rockchip_pwm_get_state_v2,
};
static const struct rockchip_pwm_data pwm_data_vop = {
@@ -217,8 +283,10 @@ static const struct rockchip_pwm_data pwm_data_vop = {
.ctrl = 0x00,
},
.prescaler = 1,
+ .supports_polarity = true,
.ops = &rockchip_pwm_ops_v2,
.set_enable = rockchip_pwm_set_enable_v2,
+ .get_state = rockchip_pwm_get_state_v2,
};
static const struct of_device_id rockchip_pwm_dt_ids[] = {
@@ -253,7 +321,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pc->clk))
return PTR_ERR(pc->clk);
- ret = clk_prepare(pc->clk);
+ ret = clk_prepare_enable(pc->clk);
if (ret)
return ret;
@@ -265,7 +333,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
pc->chip.base = -1;
pc->chip.npwm = 1;
- if (pc->data->ops->set_polarity) {
+ if (pc->data->supports_polarity) {
pc->chip.of_xlate = of_pwm_xlate_with_flags;
pc->chip.of_pwm_n_cells = 3;
}
@@ -276,6 +344,10 @@ static int rockchip_pwm_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
}
+ /* Keep the PWM clk enabled if the PWM appears to be up and running. */
+ if (!pwm_is_enabled(pc->chip.pwms))
+ clk_disable(pc->clk);
+
return ret;
}
@@ -283,6 +355,20 @@ static int rockchip_pwm_remove(struct platform_device *pdev)
{
struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
+ /*
+ * Disable the PWM clk before unpreparing it if the PWM device is still
+ * running. This should only happen when the last PWM user left it
+ * enabled, or when nobody requested a PWM that was previously enabled
+ * by the bootloader.
+ *
+ * FIXME: Maybe the core should disable all PWM devices in
+ * pwmchip_remove(). In this case we'd only have to call
+ * clk_unprepare() after pwmchip_remove().
+ *
+ */
+ if (pwm_is_enabled(pc->chip.pwms))
+ clk_disable(pc->clk);
+
clk_unprepare(pc->clk);
return pwmchip_remove(&pc->chip);
diff --git a/drivers/pwm/pwm-stmpe.c b/drivers/pwm/pwm-stmpe.c
new file mode 100644
index 000000000000..e464582a390a
--- /dev/null
+++ b/drivers/pwm/pwm-stmpe.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2016 Linaro Ltd.
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2, as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define STMPE24XX_PWMCS 0x30
+#define PWMCS_EN_PWM0 BIT(0)
+#define PWMCS_EN_PWM1 BIT(1)
+#define PWMCS_EN_PWM2 BIT(2)
+#define STMPE24XX_PWMIC0 0x38
+#define STMPE24XX_PWMIC1 0x39
+#define STMPE24XX_PWMIC2 0x3a
+
+#define STMPE_PWM_24XX_PINBASE 21
+
+struct stmpe_pwm {
+ struct stmpe *stmpe;
+ struct pwm_chip chip;
+ u8 last_duty;
+};
+
+static inline struct stmpe_pwm *to_stmpe_pwm(struct pwm_chip *chip)
+{
+ return container_of(chip, struct stmpe_pwm, chip);
+}
+
+static int stmpe_24xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+ struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
+ u8 value;
+ int ret;
+
+ ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
+ if (ret < 0) {
+ dev_err(chip->dev, "error reading PWM#%u control\n",
+ pwm->hwpwm);
+ return ret;
+ }
+
+ value = ret | BIT(pwm->hwpwm);
+
+ ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
+ if (ret) {
+ dev_err(chip->dev, "error writing PWM#%u control\n",
+ pwm->hwpwm);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void stmpe_24xx_pwm_disable(struct pwm_chip *chip,
+ struct pwm_device *pwm)
+{
+ struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
+ u8 value;
+ int ret;
+
+ ret = stmpe_reg_read(stmpe_pwm->stmpe, STMPE24XX_PWMCS);
+ if (ret < 0) {
+ dev_err(chip->dev, "error reading PWM#%u control\n",
+ pwm->hwpwm);
+ return;
+ }
+
+ value = ret & ~BIT(pwm->hwpwm);
+
+ ret = stmpe_reg_write(stmpe_pwm->stmpe, STMPE24XX_PWMCS, value);
+ if (ret) {
+ dev_err(chip->dev, "error writing PWM#%u control\n",
+ pwm->hwpwm);
+ return;
+ }
+}
+
+/* STMPE 24xx PWM instructions */
+#define SMAX 0x007f
+#define SMIN 0x00ff
+#define GTS 0x0000
+#define LOAD BIT(14) /* Only available on 2403 */
+#define RAMPUP 0x0000
+#define RAMPDOWN BIT(7)
+#define PRESCALE_512 BIT(14)
+#define STEPTIME_1 BIT(8)
+#define BRANCH (BIT(15) | BIT(13))
+
+static int stmpe_24xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+ int duty_ns, int period_ns)
+{
+ struct stmpe_pwm *stmpe_pwm = to_stmpe_pwm(chip);
+ unsigned int i, pin;
+ u16 program[3] = {
+ SMAX,
+ GTS,
+ GTS,
+ };
+ u8 offset;
+ int ret;
+
+ /* Make sure we are disabled */
+ if (pwm_is_enabled(pwm)) {
+ stmpe_24xx_pwm_disable(chip, pwm);
+ } else {
+ /* Connect the PWM to the pin */
+ pin = pwm->hwpwm;
+
+ /* On STMPE2401 and 2403 pins 21,22,23 are used */
+ if (stmpe_pwm->stmpe->partnum == STMPE2401 ||
+ stmpe_pwm->stmpe->partnum == STMPE2403)
+ pin += STMPE_PWM_24XX_PINBASE;
+
+ ret = stmpe_set_altfunc(stmpe_pwm->stmpe, BIT(pin),
+ STMPE_BLOCK_PWM);
+ if (ret) {
+ dev_err(chip->dev, "unable to connect PWM#%u to pin\n",
+ pwm->hwpwm);
+ return ret;
+ }
+ }
+
+ /* STMPE24XX */
+ switch (pwm->hwpwm) {
+ case 0:
+ offset = STMPE24XX_PWMIC0;
+ break;
+
+ case 1:
+ offset = STMPE24XX_PWMIC1;
+ break;
+
+ case 2:
+ offset = STMPE24XX_PWMIC1;
+ break;
+
+ default:
+ /* Should not happen as npwm is 3 */
+ return -ENODEV;
+ }
+
+ dev_dbg(chip->dev, "PWM#%u: config duty %d ns, period %d ns\n",
+ pwm->hwpwm, duty_ns, period_ns);
+
+ if (duty_ns == 0) {
+ if (stmpe_pwm->stmpe->partnum == STMPE2401)
+ program[0] = SMAX; /* off all the time */
+
+ if (stmpe_pwm->stmpe->partnum == STMPE2403)
+ program[0] = LOAD | 0xff; /* LOAD 0xff */
+
+ stmpe_pwm->last_duty = 0x00;
+ } else if (duty_ns == period_ns) {
+ if (stmpe_pwm->stmpe->partnum == STMPE2401)
+ program[0] = SMIN; /* on all the time */
+
+ if (stmpe_pwm->stmpe->partnum == STMPE2403)
+ program[0] = LOAD | 0x00; /* LOAD 0x00 */
+
+ stmpe_pwm->last_duty = 0xff;
+ } else {
+ u8 value, last = stmpe_pwm->last_duty;
+ unsigned long duty;
+
+ /*
+ * Counter goes from 0x00 to 0xff repeatedly at 32768 Hz,
+ * (means a period of 30517 ns) then this is compared to the
+ * counter from the ramp, if this is >= PWM counter the output
+ * is high. With LOAD we can define how much of the cycle it
+ * is on.
+ *
+ * Prescale = 0 -> 2 kHz -> T = 1/f = 488281.25 ns
+ */
+
+ /* Scale to 0..0xff */
+ duty = duty_ns * 256;
+ duty = DIV_ROUND_CLOSEST(duty, period_ns);
+ value = duty;
+
+ if (value == last) {
+ /* Run the old program */
+ if (pwm_is_enabled(pwm))
+ stmpe_24xx_pwm_enable(chip, pwm);
+
+ return 0;
+ } else if (stmpe_pwm->stmpe->partnum == STMPE2403) {
+ /* STMPE2403 can simply set the right PWM value */
+ program[0] = LOAD | value;
+ program[1] = 0x0000;
+ } else if (stmpe_pwm->stmpe->partnum == STMPE2401) {
+ /* STMPE2401 need a complex program */
+ u16 incdec = 0x0000;
+
+ if (last < value)
+ /* Count up */
+ incdec = RAMPUP | (value - last);
+ else
+ /* Count down */
+ incdec = RAMPDOWN | (last - value);
+
+ /* Step to desired value, smoothly */
+ program[0] = PRESCALE_512 | STEPTIME_1 | incdec;
+
+ /* Loop eternally to 0x00 */
+ program[1] = BRANCH;
+ }
+
+ dev_dbg(chip->dev,
+ "PWM#%u: value = %02x, last_duty = %02x, program=%04x,%04x,%04x\n",
+ pwm->hwpwm, value, last, program[0], program[1],
+ program[2]);
+ stmpe_pwm->last_duty = value;
+ }
+
+ /*
+ * We can write programs of up to 64 16-bit words into this channel.
+ */
+ for (i = 0; i < ARRAY_SIZE(program); i++) {
+ u8 value;
+
+ value = (program[i] >> 8) & 0xff;
+
+ ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
+ if (ret) {
+ dev_err(chip->dev, "error writing register %02x: %d\n",
+ offset, ret);
+ return ret;
+ }
+
+ value = program[i] & 0xff;
+
+ ret = stmpe_reg_write(stmpe_pwm->stmpe, offset, value);
+ if (ret) {
+ dev_err(chip->dev, "error writing register %02x: %d\n",
+ offset, ret);
+ return ret;
+ }
+ }
+
+ /* If we were enabled, re-enable this PWM */
+ if (pwm_is_enabled(pwm))
+ stmpe_24xx_pwm_enable(chip, pwm);
+
+ /* Sleep for 200ms so we're sure it will take effect */
+ msleep(200);
+
+ dev_dbg(chip->dev, "programmed PWM#%u, %u bytes\n", pwm->hwpwm, i);
+
+ return 0;
+}
+
+static const struct pwm_ops stmpe_24xx_pwm_ops = {
+ .config = stmpe_24xx_pwm_config,
+ .enable = stmpe_24xx_pwm_enable,
+ .disable = stmpe_24xx_pwm_disable,
+ .owner = THIS_MODULE,
+};
+
+static int __init stmpe_pwm_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_pwm *pwm;
+ int ret;
+
+ pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
+ if (!pwm)
+ return -ENOMEM;
+
+ pwm->stmpe = stmpe;
+ pwm->chip.dev = &pdev->dev;
+ pwm->chip.base = -1;
+
+ if (stmpe->partnum == STMPE2401 || stmpe->partnum == STMPE2403) {
+ pwm->chip.ops = &stmpe_24xx_pwm_ops;
+ pwm->chip.npwm = 3;
+ } else {
+ if (stmpe->partnum == STMPE1601)
+ dev_err(&pdev->dev, "STMPE1601 not yet supported\n");
+ else
+ dev_err(&pdev->dev, "Unknown STMPE PWM\n");
+
+ return -ENODEV;
+ }
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_PWM);
+ if (ret)
+ return ret;
+
+ ret = pwmchip_add(&pwm->chip);
+ if (ret) {
+ stmpe_disable(stmpe, STMPE_BLOCK_PWM);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, pwm);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_pwm_driver = {
+ .driver = {
+ .name = "stmpe-pwm",
+ },
+};
+builtin_platform_driver_probe(stmpe_pwm_driver, stmpe_pwm_probe);
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index d4de0607b502..e4647840cd6e 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -26,9 +26,11 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/pwm.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/reset.h>
#define PWM_ENABLE (1 << 31)
#define PWM_DUTY_WIDTH 8
@@ -36,15 +38,20 @@
#define PWM_SCALE_WIDTH 13
#define PWM_SCALE_SHIFT 0
-#define NUM_PWM 4
+struct tegra_pwm_soc {
+ unsigned int num_channels;
+};
struct tegra_pwm_chip {
- struct pwm_chip chip;
- struct device *dev;
+ struct pwm_chip chip;
+ struct device *dev;
+
+ struct clk *clk;
+ struct reset_control*rst;
- struct clk *clk;
+ void __iomem *regs;
- void __iomem *mmio_base;
+ const struct tegra_pwm_soc *soc;
};
static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip)
@@ -54,20 +61,20 @@ static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip)
static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num)
{
- return readl(chip->mmio_base + (num << 4));
+ return readl(chip->regs + (num << 4));
}
static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num,
unsigned long val)
{
- writel(val, chip->mmio_base + (num << 4));
+ writel(val, chip->regs + (num << 4));
}
static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
- unsigned long long c;
+ unsigned long long c = duty_ns;
unsigned long rate, hz;
u32 val = 0;
int err;
@@ -77,7 +84,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
* per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the
* nearest integer during division.
*/
- c = duty_ns * ((1 << PWM_DUTY_WIDTH) - 1) + period_ns / 2;
+ c *= (1 << PWM_DUTY_WIDTH);
+ c += period_ns / 2;
do_div(c, period_ns);
val = (u32)c << PWM_DUTY_SHIFT;
@@ -176,12 +184,13 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (!pwm)
return -ENOMEM;
+ pwm->soc = of_device_get_match_data(&pdev->dev);
pwm->dev = &pdev->dev;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(pwm->mmio_base))
- return PTR_ERR(pwm->mmio_base);
+ pwm->regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(pwm->regs))
+ return PTR_ERR(pwm->regs);
platform_set_drvdata(pdev, pwm);
@@ -189,14 +198,24 @@ static int tegra_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pwm->clk))
return PTR_ERR(pwm->clk);
+ pwm->rst = devm_reset_control_get(&pdev->dev, "pwm");
+ if (IS_ERR(pwm->rst)) {
+ ret = PTR_ERR(pwm->rst);
+ dev_err(&pdev->dev, "Reset control is not found: %d\n", ret);
+ return ret;
+ }
+
+ reset_control_deassert(pwm->rst);
+
pwm->chip.dev = &pdev->dev;
pwm->chip.ops = &tegra_pwm_ops;
pwm->chip.base = -1;
- pwm->chip.npwm = NUM_PWM;
+ pwm->chip.npwm = pwm->soc->num_channels;
ret = pwmchip_add(&pwm->chip);
if (ret < 0) {
dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+ reset_control_assert(pwm->rst);
return ret;
}
@@ -206,12 +225,17 @@ static int tegra_pwm_probe(struct platform_device *pdev)
static int tegra_pwm_remove(struct platform_device *pdev)
{
struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
- int i;
+ unsigned int i;
+ int err;
if (WARN_ON(!pc))
return -ENODEV;
- for (i = 0; i < NUM_PWM; i++) {
+ err = clk_prepare_enable(pc->clk);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i < pc->chip.npwm; i++) {
struct pwm_device *pwm = &pc->chip.pwms[i];
if (!pwm_is_enabled(pwm))
@@ -223,12 +247,23 @@ static int tegra_pwm_remove(struct platform_device *pdev)
clk_disable_unprepare(pc->clk);
}
+ reset_control_assert(pc->rst);
+ clk_disable_unprepare(pc->clk);
+
return pwmchip_remove(&pc->chip);
}
+static const struct tegra_pwm_soc tegra20_pwm_soc = {
+ .num_channels = 4,
+};
+
+static const struct tegra_pwm_soc tegra186_pwm_soc = {
+ .num_channels = 1,
+};
+
static const struct of_device_id tegra_pwm_of_match[] = {
- { .compatible = "nvidia,tegra20-pwm" },
- { .compatible = "nvidia,tegra30-pwm" },
+ { .compatible = "nvidia,tegra20-pwm", .data = &tegra20_pwm_soc },
+ { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc },
{ }
};
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index 616af764a276..6ec342dd3eea 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -27,8 +27,6 @@
#include <linux/pwm.h>
#include <linux/of_device.h>
-#include "pwm-tipwmss.h"
-
/* ECAP registers and bits definitions */
#define CAP1 0x08
#define CAP2 0x0C
@@ -195,6 +193,7 @@ static const struct pwm_ops ecap_pwm_ops = {
};
static const struct of_device_id ecap_of_match[] = {
+ { .compatible = "ti,am3352-ecap" },
{ .compatible = "ti,am33xx-ecap" },
{},
};
@@ -202,11 +201,11 @@ MODULE_DEVICE_TABLE(of, ecap_of_match);
static int ecap_pwm_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
int ret;
struct resource *r;
struct clk *clk;
struct ecap_pwm_chip *pc;
- u16 status;
pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
if (!pc)
@@ -214,6 +213,13 @@ static int ecap_pwm_probe(struct platform_device *pdev)
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
+ if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
+ dev_warn(&pdev->dev, "Binding is obsolete.\n");
+ clk = devm_clk_get(pdev->dev.parent, "fck");
+ }
+ }
+
+ if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
return PTR_ERR(clk);
}
@@ -243,40 +249,15 @@ static int ecap_pwm_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
- status = pwmss_submodule_state_change(pdev->dev.parent,
- PWMSS_ECAPCLK_EN);
- if (!(status & PWMSS_ECAPCLK_EN_ACK)) {
- dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
- ret = -EINVAL;
- goto pwmss_clk_failure;
- }
-
- pm_runtime_put_sync(&pdev->dev);
platform_set_drvdata(pdev, pc);
return 0;
-
-pwmss_clk_failure:
- pm_runtime_put_sync(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- pwmchip_remove(&pc->chip);
- return ret;
}
static int ecap_pwm_remove(struct platform_device *pdev)
{
struct ecap_pwm_chip *pc = platform_get_drvdata(pdev);
- pm_runtime_get_sync(&pdev->dev);
- /*
- * Due to hardware misbehaviour, acknowledge of the stop_req
- * is missing. Hence checking of the status bit skipped.
- */
- pwmss_submodule_state_change(pdev->dev.parent, PWMSS_ECAPCLK_STOP_REQ);
- pm_runtime_put_sync(&pdev->dev);
-
pm_runtime_disable(&pdev->dev);
return pwmchip_remove(&pc->chip);
}
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 6a41e66015b6..b5c6b0636893 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -27,8 +27,6 @@
#include <linux/pm_runtime.h>
#include <linux/of_device.h>
-#include "pwm-tipwmss.h"
-
/* EHRPWM registers and bits definitions */
/* Time base module registers */
@@ -426,6 +424,7 @@ static const struct pwm_ops ehrpwm_pwm_ops = {
};
static const struct of_device_id ehrpwm_of_match[] = {
+ { .compatible = "ti,am3352-ehrpwm" },
{ .compatible = "ti,am33xx-ehrpwm" },
{},
};
@@ -433,11 +432,11 @@ MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
static int ehrpwm_pwm_probe(struct platform_device *pdev)
{
+ struct device_node *np = pdev->dev.of_node;
int ret;
struct resource *r;
struct clk *clk;
struct ehrpwm_pwm_chip *pc;
- u16 status;
pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
if (!pc)
@@ -445,6 +444,13 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(clk)) {
+ if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
+ dev_warn(&pdev->dev, "Binding is obsolete.\n");
+ clk = devm_clk_get(pdev->dev.parent, "fck");
+ }
+ }
+
+ if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clock\n");
return PTR_ERR(clk);
}
@@ -487,27 +493,9 @@ static int ehrpwm_pwm_probe(struct platform_device *pdev)
}
pm_runtime_enable(&pdev->dev);
- pm_runtime_get_sync(&pdev->dev);
-
- status = pwmss_submodule_state_change(pdev->dev.parent,
- PWMSS_EPWMCLK_EN);
- if (!(status & PWMSS_EPWMCLK_EN_ACK)) {
- dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
- ret = -EINVAL;
- goto pwmss_clk_failure;
- }
-
- pm_runtime_put_sync(&pdev->dev);
platform_set_drvdata(pdev, pc);
return 0;
-
-pwmss_clk_failure:
- pm_runtime_put_sync(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- pwmchip_remove(&pc->chip);
- clk_unprepare(pc->tbclk);
- return ret;
}
static int ehrpwm_pwm_remove(struct platform_device *pdev)
@@ -516,14 +504,6 @@ static int ehrpwm_pwm_remove(struct platform_device *pdev)
clk_unprepare(pc->tbclk);
- pm_runtime_get_sync(&pdev->dev);
- /*
- * Due to hardware misbehaviour, acknowledge of the stop_req
- * is missing. Hence checking of the status bit skipped.
- */
- pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EPWMCLK_STOP_REQ);
- pm_runtime_put_sync(&pdev->dev);
-
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return pwmchip_remove(&pc->chip);
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
index 5cf65a15d021..829f4991c96f 100644
--- a/drivers/pwm/pwm-tipwmss.c
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -22,32 +22,6 @@
#include <linux/pm_runtime.h>
#include <linux/of_device.h>
-#include "pwm-tipwmss.h"
-
-#define PWMSS_CLKCONFIG 0x8 /* Clock gating reg */
-#define PWMSS_CLKSTATUS 0xc /* Clock gating status reg */
-
-struct pwmss_info {
- void __iomem *mmio_base;
- struct mutex pwmss_lock;
- u16 pwmss_clkconfig;
-};
-
-u16 pwmss_submodule_state_change(struct device *dev, int set)
-{
- struct pwmss_info *info = dev_get_drvdata(dev);
- u16 val;
-
- mutex_lock(&info->pwmss_lock);
- val = readw(info->mmio_base + PWMSS_CLKCONFIG);
- val |= set;
- writew(val , info->mmio_base + PWMSS_CLKCONFIG);
- mutex_unlock(&info->pwmss_lock);
-
- return readw(info->mmio_base + PWMSS_CLKSTATUS);
-}
-EXPORT_SYMBOL(pwmss_submodule_state_change);
-
static const struct of_device_id pwmss_of_match[] = {
{ .compatible = "ti,am33xx-pwmss" },
{},
@@ -57,24 +31,10 @@ MODULE_DEVICE_TABLE(of, pwmss_of_match);
static int pwmss_probe(struct platform_device *pdev)
{
int ret;
- struct resource *r;
- struct pwmss_info *info;
struct device_node *node = pdev->dev.of_node;
- info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- mutex_init(&info->pwmss_lock);
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
- if (IS_ERR(info->mmio_base))
- return PTR_ERR(info->mmio_base);
-
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
- platform_set_drvdata(pdev, info);
/* Populate all the child nodes here... */
ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
@@ -86,30 +46,21 @@ static int pwmss_probe(struct platform_device *pdev)
static int pwmss_remove(struct platform_device *pdev)
{
- struct pwmss_info *info = platform_get_drvdata(pdev);
-
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- mutex_destroy(&info->pwmss_lock);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int pwmss_suspend(struct device *dev)
{
- struct pwmss_info *info = dev_get_drvdata(dev);
-
- info->pwmss_clkconfig = readw(info->mmio_base + PWMSS_CLKCONFIG);
pm_runtime_put_sync(dev);
return 0;
}
static int pwmss_resume(struct device *dev)
{
- struct pwmss_info *info = dev_get_drvdata(dev);
-
pm_runtime_get_sync(dev);
- writew(info->pwmss_clkconfig, info->mmio_base + PWMSS_CLKCONFIG);
return 0;
}
#endif
diff --git a/drivers/pwm/pwm-tipwmss.h b/drivers/pwm/pwm-tipwmss.h
deleted file mode 100644
index 10ad8040408b..000000000000
--- a/drivers/pwm/pwm-tipwmss.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * TI PWM Subsystem driver
- *
- * Copyright (C) 2012 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; 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.
- *
- */
-
-#ifndef __TIPWMSS_H
-#define __TIPWMSS_H
-
-/* PWM substem clock gating */
-#define PWMSS_ECAPCLK_EN BIT(0)
-#define PWMSS_ECAPCLK_STOP_REQ BIT(1)
-#define PWMSS_EPWMCLK_EN BIT(8)
-#define PWMSS_EPWMCLK_STOP_REQ BIT(9)
-
-#define PWMSS_ECAPCLK_EN_ACK BIT(0)
-#define PWMSS_EPWMCLK_EN_ACK BIT(8)
-
-#ifdef CONFIG_PWM_TIPWMSS
-extern u16 pwmss_submodule_state_change(struct device *dev, int set);
-#else
-static inline u16 pwmss_submodule_state_change(struct device *dev, int set)
-{
- /* return success status value */
- return 0xFFFF;
-}
-#endif
-#endif /* __TIPWMSS_H */
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 01695d48dd54..18ed725594c3 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -208,16 +208,33 @@ static ssize_t polarity_store(struct device *child,
return ret ? : size;
}
+static ssize_t capture_show(struct device *child,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pwm_device *pwm = child_to_pwm_device(child);
+ struct pwm_capture result;
+ int ret;
+
+ ret = pwm_capture(pwm, &result, jiffies_to_msecs(HZ));
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
+}
+
static DEVICE_ATTR_RW(period);
static DEVICE_ATTR_RW(duty_cycle);
static DEVICE_ATTR_RW(enable);
static DEVICE_ATTR_RW(polarity);
+static DEVICE_ATTR_RO(capture);
static struct attribute *pwm_attrs[] = {
&dev_attr_period.attr,
&dev_attr_duty_cycle.attr,
&dev_attr_enable.attr,
&dev_attr_polarity.attr,
+ &dev_attr_capture.attr,
NULL
};
ATTRIBUTE_GROUPS(pwm);
diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c
index cecc15a880de..3fa17ac8df54 100644
--- a/drivers/rapidio/rio_cm.c
+++ b/drivers/rapidio/rio_cm.c
@@ -1080,8 +1080,8 @@ static int riocm_send_ack(struct rio_channel *ch)
static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
long timeout)
{
- struct rio_channel *ch = NULL;
- struct rio_channel *new_ch = NULL;
+ struct rio_channel *ch;
+ struct rio_channel *new_ch;
struct conn_req *req;
struct cm_peer *peer;
int found = 0;
@@ -1155,6 +1155,7 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
spin_unlock_bh(&ch->lock);
riocm_put_channel(ch);
+ ch = NULL;
kfree(req);
down_read(&rdev_sem);
@@ -1172,7 +1173,7 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
if (!found) {
/* If peer device object not found, simply ignore the request */
err = -ENODEV;
- goto err_nodev;
+ goto err_put_new_ch;
}
new_ch->rdev = peer->rdev;
@@ -1184,15 +1185,16 @@ static struct rio_channel *riocm_ch_accept(u16 ch_id, u16 *new_ch_id,
*new_ch_id = new_ch->id;
return new_ch;
+
+err_put_new_ch:
+ spin_lock_bh(&idr_lock);
+ idr_remove(&ch_idr, new_ch->id);
+ spin_unlock_bh(&idr_lock);
+ riocm_put_channel(new_ch);
+
err_put:
- riocm_put_channel(ch);
-err_nodev:
- if (new_ch) {
- spin_lock_bh(&idr_lock);
- idr_remove(&ch_idr, new_ch->id);
- spin_unlock_bh(&idr_lock);
- riocm_put_channel(new_ch);
- }
+ if (ch)
+ riocm_put_channel(ch);
*new_ch_id = 0;
return ERR_PTR(err);
}
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c
index 666bc3bb52ef..c24524242da2 100644
--- a/drivers/regulator/pwm-regulator.c
+++ b/drivers/regulator/pwm-regulator.c
@@ -22,6 +22,12 @@
#include <linux/pwm.h>
#include <linux/gpio/consumer.h>
+struct pwm_continuous_reg_data {
+ unsigned int min_uV_dutycycle;
+ unsigned int max_uV_dutycycle;
+ unsigned int dutycycle_unit;
+};
+
struct pwm_regulator_data {
/* Shared */
struct pwm_device *pwm;
@@ -29,6 +35,9 @@ struct pwm_regulator_data {
/* Voltage table */
struct pwm_voltages *duty_cycle_table;
+ /* Continuous mode info */
+ struct pwm_continuous_reg_data continuous;
+
/* regulator descriptor */
struct regulator_desc desc;
@@ -37,9 +46,6 @@ struct pwm_regulator_data {
int state;
- /* Continuous voltage */
- int volt_uV;
-
/* Enable GPIO */
struct gpio_desc *enb_gpio;
};
@@ -52,10 +58,31 @@ struct pwm_voltages {
/**
* Voltage table call-backs
*/
+static void pwm_regulator_init_state(struct regulator_dev *rdev)
+{
+ struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+ struct pwm_state pwm_state;
+ unsigned int dutycycle;
+ int i;
+
+ pwm_get_state(drvdata->pwm, &pwm_state);
+ dutycycle = pwm_get_relative_duty_cycle(&pwm_state, 100);
+
+ for (i = 0; i < rdev->desc->n_voltages; i++) {
+ if (dutycycle == drvdata->duty_cycle_table[i].dutycycle) {
+ drvdata->state = i;
+ return;
+ }
+ }
+}
+
static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+ if (drvdata->state < 0)
+ pwm_regulator_init_state(rdev);
+
return drvdata->state;
}
@@ -63,16 +90,14 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
- struct pwm_args pargs;
- int dutycycle;
+ struct pwm_state pstate;
int ret;
- pwm_get_args(drvdata->pwm, &pargs);
-
- dutycycle = (pargs.period *
- drvdata->duty_cycle_table[selector].dutycycle) / 100;
+ pwm_init_state(drvdata->pwm, &pstate);
+ pwm_set_relative_duty_cycle(&pstate,
+ drvdata->duty_cycle_table[selector].dutycycle, 100);
- ret = pwm_config(drvdata->pwm, dutycycle, pargs.period);
+ ret = pwm_apply_state(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
@@ -129,57 +154,90 @@ static int pwm_regulator_is_enabled(struct regulator_dev *dev)
static int pwm_regulator_get_voltage(struct regulator_dev *rdev)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+ unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle;
+ unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle;
+ unsigned int duty_unit = drvdata->continuous.dutycycle_unit;
+ int min_uV = rdev->constraints->min_uV;
+ int max_uV = rdev->constraints->max_uV;
+ int diff_uV = max_uV - min_uV;
+ struct pwm_state pstate;
+ unsigned int diff_duty;
+ unsigned int voltage;
+
+ pwm_get_state(drvdata->pwm, &pstate);
+
+ voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit);
+
+ /*
+ * The dutycycle for min_uV might be greater than the one for max_uV.
+ * This is happening when the user needs an inversed polarity, but the
+ * PWM device does not support inversing it in hardware.
+ */
+ if (max_uV_duty < min_uV_duty) {
+ voltage = min_uV_duty - voltage;
+ diff_duty = min_uV_duty - max_uV_duty;
+ } else {
+ voltage = voltage - min_uV_duty;
+ diff_duty = max_uV_duty - min_uV_duty;
+ }
- return drvdata->volt_uV;
+ voltage = DIV_ROUND_CLOSEST_ULL((u64)voltage * diff_uV, diff_duty);
+
+ return voltage + min_uV;
}
static int pwm_regulator_set_voltage(struct regulator_dev *rdev,
- int min_uV, int max_uV,
- unsigned *selector)
+ int req_min_uV, int req_max_uV,
+ unsigned int *selector)
{
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
+ unsigned int min_uV_duty = drvdata->continuous.min_uV_dutycycle;
+ unsigned int max_uV_duty = drvdata->continuous.max_uV_dutycycle;
+ unsigned int duty_unit = drvdata->continuous.dutycycle_unit;
unsigned int ramp_delay = rdev->constraints->ramp_delay;
- struct pwm_args pargs;
- unsigned int req_diff = min_uV - rdev->constraints->min_uV;
- unsigned int diff;
- unsigned int duty_pulse;
- u64 req_period;
- u32 rem;
+ int min_uV = rdev->constraints->min_uV;
+ int max_uV = rdev->constraints->max_uV;
+ int diff_uV = max_uV - min_uV;
+ struct pwm_state pstate;
int old_uV = pwm_regulator_get_voltage(rdev);
+ unsigned int diff_duty;
+ unsigned int dutycycle;
int ret;
- pwm_get_args(drvdata->pwm, &pargs);
- diff = rdev->constraints->max_uV - rdev->constraints->min_uV;
+ pwm_init_state(drvdata->pwm, &pstate);
- /* First try to find out if we get the iduty cycle time which is
- * factor of PWM period time. If (request_diff_to_min * pwm_period)
- * is perfect divided by voltage_range_diff then it is possible to
- * get duty cycle time which is factor of PWM period. This will help
- * to get output voltage nearer to requested value as there is no
- * calculation loss.
+ /*
+ * The dutycycle for min_uV might be greater than the one for max_uV.
+ * This is happening when the user needs an inversed polarity, but the
+ * PWM device does not support inversing it in hardware.
*/
- req_period = req_diff * pargs.period;
- div_u64_rem(req_period, diff, &rem);
- if (!rem) {
- do_div(req_period, diff);
- duty_pulse = (unsigned int)req_period;
- } else {
- duty_pulse = (pargs.period / 100) * ((req_diff * 100) / diff);
- }
+ if (max_uV_duty < min_uV_duty)
+ diff_duty = min_uV_duty - max_uV_duty;
+ else
+ diff_duty = max_uV_duty - min_uV_duty;
+
+ dutycycle = DIV_ROUND_CLOSEST_ULL((u64)(req_min_uV - min_uV) *
+ diff_duty,
+ diff_uV);
+
+ if (max_uV_duty < min_uV_duty)
+ dutycycle = min_uV_duty - dutycycle;
+ else
+ dutycycle = min_uV_duty + dutycycle;
+
+ pwm_set_relative_duty_cycle(&pstate, dutycycle, duty_unit);
- ret = pwm_config(drvdata->pwm, duty_pulse, pargs.period);
+ ret = pwm_apply_state(drvdata->pwm, &pstate);
if (ret) {
dev_err(&rdev->dev, "Failed to configure PWM: %d\n", ret);
return ret;
}
- drvdata->volt_uV = min_uV;
-
if ((ramp_delay == 0) || !pwm_regulator_is_enabled(rdev))
return 0;
/* Ramp delay is in uV/uS. Adjust to uS and delay */
- ramp_delay = DIV_ROUND_UP(abs(min_uV - old_uV), ramp_delay);
+ ramp_delay = DIV_ROUND_UP(abs(req_min_uV - old_uV), ramp_delay);
usleep_range(ramp_delay, ramp_delay + DIV_ROUND_UP(ramp_delay, 10));
return 0;
@@ -239,6 +297,7 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
return ret;
}
+ drvdata->state = -EINVAL;
drvdata->duty_cycle_table = duty_cycle_table;
memcpy(&drvdata->ops, &pwm_regulator_voltage_table_ops,
sizeof(drvdata->ops));
@@ -251,11 +310,28 @@ static int pwm_regulator_init_table(struct platform_device *pdev,
static int pwm_regulator_init_continuous(struct platform_device *pdev,
struct pwm_regulator_data *drvdata)
{
+ u32 dutycycle_range[2] = { 0, 100 };
+ u32 dutycycle_unit = 100;
+
memcpy(&drvdata->ops, &pwm_regulator_voltage_continuous_ops,
sizeof(drvdata->ops));
drvdata->desc.ops = &drvdata->ops;
drvdata->desc.continuous_voltage_range = true;
+ of_property_read_u32_array(pdev->dev.of_node,
+ "pwm-dutycycle-range",
+ dutycycle_range, 2);
+ of_property_read_u32(pdev->dev.of_node, "pwm-dutycycle-unit",
+ &dutycycle_unit);
+
+ if (dutycycle_range[0] > dutycycle_unit ||
+ dutycycle_range[1] > dutycycle_unit)
+ return -EINVAL;
+
+ drvdata->continuous.dutycycle_unit = dutycycle_unit;
+ drvdata->continuous.min_uV_dutycycle = dutycycle_range[0];
+ drvdata->continuous.max_uV_dutycycle = dutycycle_range[1];
+
return 0;
}
@@ -316,11 +392,9 @@ static int pwm_regulator_probe(struct platform_device *pdev)
return ret;
}
- /*
- * FIXME: pwm_apply_args() should be removed when switching to the
- * atomic PWM API.
- */
- pwm_apply_args(drvdata->pwm);
+ ret = pwm_adjust_config(drvdata->pwm);
+ if (ret)
+ return ret;
regulator = devm_regulator_register(&pdev->dev,
&drvdata->desc, &config);
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index 24791886219a..2a1b2c7d8f2c 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -349,13 +349,12 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc,
static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
{
- DEFINE_DMA_ATTRS(attrs);
+ unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
dma_addr_t phys;
void *ptr;
int ret;
- dma_set_attr(DMA_ATTR_FORCE_CONTIGUOUS, &attrs);
- ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, &attrs);
+ ptr = dma_alloc_attrs(qproc->dev, fw->size, &phys, GFP_KERNEL, dma_attrs);
if (!ptr) {
dev_err(qproc->dev, "failed to allocate mdt buffer\n");
return -ENOMEM;
@@ -372,7 +371,7 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw)
else if (ret < 0)
dev_err(qproc->dev, "MPSS header authentication failed: %d\n", ret);
- dma_free_attrs(qproc->dev, fw->size, ptr, phys, &attrs);
+ dma_free_attrs(qproc->dev, fw->size, ptr, phys, dma_attrs);
return ret < 0 ? ret : 0;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 18639e0cb6e2..e215f50794b6 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -5,6 +5,10 @@
config RTC_LIB
bool
+config RTC_MC146818_LIB
+ bool
+ select RTC_LIB
+
menuconfig RTC_CLASS
bool "Real Time Clock"
default n
@@ -574,10 +578,10 @@ config RTC_DRV_EM3027
will be called rtc-em3027.
config RTC_DRV_RV8803
- tristate "Micro Crystal RV8803"
+ tristate "Micro Crystal RV8803, Epson RX8900"
help
- If you say yes here you get support for the Micro Crystal
- RV8803 RTC chips.
+ If you say yes here you get support for the Micro Crystal RV8803 and
+ Epson RX8900 RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-rv8803.
@@ -670,6 +674,18 @@ config RTC_DRV_DS1390
This driver can also be built as a module. If so, the module
will be called rtc-ds1390.
+config RTC_DRV_MAX6916
+ tristate "Maxim MAX6916"
+ help
+ If you say yes here you will get support for the
+ Maxim MAX6916 SPI RTC chip.
+
+ This driver only supports the RTC feature, and not other chip
+ features such as alarms.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-max6916.
+
config RTC_DRV_R9701
tristate "Epson RTC-9701JE"
help
@@ -795,8 +811,9 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
- depends on X86 || ARM || M32R || PPC || MIPS || SPARC64
+ depends on X86 || ARM || M32R || PPC || MIPS || SPARC64 || MN10300
default y if X86
+ select RTC_MC146818_LIB
help
Say "yes" here to get direct support for the real time clock
found in every PC or ACPI-based system, and some other boards.
@@ -815,6 +832,7 @@ config RTC_DRV_CMOS
config RTC_DRV_ALPHA
bool "Alpha PC-style CMOS"
depends on ALPHA
+ select RTC_MC146818_LIB
default y
help
Direct support for the real-time clock found on every Alpha
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ea2833723fa9..7cf7ad559c79 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o
obj-$(CONFIG_RTC_SYSTOHC) += systohc.o
obj-$(CONFIG_RTC_CLASS) += rtc-core.o
+obj-$(CONFIG_RTC_MC146818_LIB) += rtc-mc146818-lib.o
rtc-core-y := class.o interface.o
ifdef CONFIG_RTC_DRV_EFI
@@ -85,6 +86,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_MAX6916) += rtc-max6916.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 9ef5f6f89f98..84a52db9b05f 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -104,7 +104,17 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al
else if (!rtc->ops->read_alarm)
err = -EINVAL;
else {
- memset(alarm, 0, sizeof(struct rtc_wkalrm));
+ alarm->enabled = 0;
+ alarm->pending = 0;
+ alarm->time.tm_sec = -1;
+ alarm->time.tm_min = -1;
+ alarm->time.tm_hour = -1;
+ alarm->time.tm_mday = -1;
+ alarm->time.tm_mon = -1;
+ alarm->time.tm_year = -1;
+ alarm->time.tm_wday = -1;
+ alarm->time.tm_yday = -1;
+ alarm->time.tm_isdst = -1;
err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
}
@@ -383,7 +393,7 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
rtc->aie_timer.period = ktime_set(0, 0);
- /* Alarm has to be enabled & in the futrure for us to enqueue it */
+ /* Alarm has to be enabled & in the future for us to enqueue it */
if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 <
rtc->aie_timer.node.expires.tv64)) {
@@ -395,8 +405,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
-
-
int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
int err = mutex_lock_interruptible(&rtc->ops_lock);
@@ -748,9 +756,23 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
*/
static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
{
+ struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
+ struct rtc_time tm;
+ ktime_t now;
+
timer->enabled = 1;
+ __rtc_read_time(rtc, &tm);
+ now = rtc_tm_to_ktime(tm);
+
+ /* Skip over expired timers */
+ while (next) {
+ if (next->expires.tv64 >= now.tv64)
+ break;
+ next = timerqueue_iterate_next(next);
+ }
+
timerqueue_add(&rtc->timerqueue, &timer->node);
- if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) {
+ if (!next) {
struct rtc_wkalrm alarm;
int err;
alarm.time = rtc_ktime_to_tm(timer->node.expires);
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index ba0d61934d35..fea9a60b06cf 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -643,17 +643,15 @@ static int abx80x_probe(struct i2c_client *client,
return err;
}
- err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group,
- &client->dev);
- if (err) {
- rtc_calib_remove_sysfs_group(&client->dev);
+ err = devm_add_action_or_reset(&client->dev,
+ rtc_calib_remove_sysfs_group,
+ &client->dev);
+ if (err)
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n",
err);
- return err;
- }
- return 0;
+ return err;
}
static int abx80x_remove(struct i2c_client *client)
diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c
index 355fdb97a006..5219916ce11d 100644
--- a/drivers/rtc/rtc-asm9260.c
+++ b/drivers/rtc/rtc-asm9260.c
@@ -343,7 +343,6 @@ static struct platform_driver asm9260_rtc_driver = {
.remove = asm9260_rtc_remove,
.driver = {
.name = "asm9260-rtc",
- .owner = THIS_MODULE,
.of_match_table = asm9260_dt_ids,
},
};
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 99732e6f8c3b..7418a763ce52 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -375,6 +375,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (!rtc)
return -ENOMEM;
+ spin_lock_init(&rtc->lock);
rtc->irq = irq;
/* platform setup code should have handled this; sigh */
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index fbe9c72438e1..43745cac0141 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -43,7 +43,7 @@
#include <linux/of_platform.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
-#include <asm-generic/rtc.h>
+#include <linux/mc146818rtc.h>
struct cmos_rtc {
struct rtc_device *rtc;
@@ -190,10 +190,10 @@ static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
- * that instead of the heuristic in get_rtc_time().
+ * that instead of the heuristic in mc146818_get_time().
* That'll make Y3K compatility (year > 2070) easy!
*/
- get_rtc_time(t);
+ mc146818_get_time(t);
return 0;
}
@@ -205,7 +205,7 @@ static int cmos_set_time(struct device *dev, struct rtc_time *t)
* takes effect exactly 500ms after we write the register.
* (Also queueing and other delays before we get this far.)
*/
- return set_rtc_time(t);
+ return mc146818_set_time(t);
}
static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
@@ -220,8 +220,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
* Some also support day and month, for alarms up to a year in
* the future.
*/
- t->time.tm_mday = -1;
- t->time.tm_mon = -1;
spin_lock_irq(&rtc_lock);
t->time.tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
@@ -272,7 +270,6 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
}
}
}
- t->time.tm_year = -1;
t->enabled = !!(rtc_control & RTC_AIE);
t->pending = 0;
@@ -630,7 +627,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
address_space = 64;
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) \
|| defined(__sparc__) || defined(__mips__) \
- || defined(__powerpc__)
+ || defined(__powerpc__) || defined(CONFIG_MN10300)
address_space = 128;
#else
#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
@@ -1142,14 +1139,14 @@ static __init void cmos_of_init(struct platform_device *pdev)
if (val)
CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
- get_rtc_time(&time);
+ cmos_read_time(&pdev->dev, &time);
ret = rtc_valid_tm(&time);
if (ret) {
struct rtc_time def_time = {
.tm_year = 1,
.tm_mday = 1,
};
- set_rtc_time(&def_time);
+ cmos_set_time(&pdev->dev, &def_time);
}
}
#else
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c
index a20bcf0e33cd..4273377562ec 100644
--- a/drivers/rtc/rtc-da9052.c
+++ b/drivers/rtc/rtc-da9052.c
@@ -85,6 +85,7 @@ static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
rtc_tm->tm_mday = v[0][2] & DA9052_RTC_DAY;
rtc_tm->tm_hour = v[0][1] & DA9052_RTC_HOUR;
rtc_tm->tm_min = v[0][0] & DA9052_RTC_MIN;
+ rtc_tm->tm_sec = 0;
ret = rtc_valid_tm(rtc_tm);
return ret;
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
index 7ec0872d5e3b..678af8648c45 100644
--- a/drivers/rtc/rtc-da9055.c
+++ b/drivers/rtc/rtc-da9055.c
@@ -74,6 +74,7 @@ static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm)
rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY;
rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR;
rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN;
+ rtc_tm->tm_sec = 0;
return rtc_valid_tm(rtc_tm);
}
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index c5432bf64e1c..dba60c1dfce2 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -388,6 +388,8 @@ static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
u8 day0, day1;
unsigned long flags;
+ alm->time.tm_sec = 0;
+
spin_lock_irqsave(&davinci_rtc_lock, flags);
davinci_rtcss_calendar_wait(davinci_rtc);
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c
index 756e509f6ed2..ef75c349dff9 100644
--- a/drivers/rtc/rtc-ds1286.c
+++ b/drivers/rtc/rtc-ds1286.c
@@ -16,7 +16,7 @@
#include <linux/rtc.h>
#include <linux/platform_device.h>
#include <linux/bcd.h>
-#include <linux/ds1286.h>
+#include <linux/rtc/ds1286.h>
#include <linux/io.h>
#include <linux/slab.h>
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 8e41c4613e51..72b22935eb62 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -313,13 +313,6 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]);
alm->time.tm_min = bcd2bin(buf[DS1305_MIN]);
alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
- alm->time.tm_mday = -1;
- alm->time.tm_mon = -1;
- alm->time.tm_year = -1;
- /* next three fields are unused by Linux */
- alm->time.tm_wday = -1;
- alm->time.tm_mday = -1;
- alm->time.tm_isdst = -1;
return 0;
}
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 821d9c089cdb..8e1c5cb6ece6 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -482,11 +482,6 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
- t->time.tm_mon = -1;
- t->time.tm_year = -1;
- t->time.tm_wday = -1;
- t->time.tm_yday = -1;
- t->time.tm_isdst = -1;
/* ... and status */
t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
@@ -602,6 +597,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
* Alarm support for mcp794xx devices.
*/
+#define MCP794XX_REG_WEEKDAY 0x3
+#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7
#define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10
# define MCP794XX_BIT_ALM1_EN 0x20
@@ -1231,13 +1228,16 @@ static int ds1307_probe(struct i2c_client *client,
{
struct ds1307 *ds1307;
int err = -ENODEV;
- int tmp;
+ int tmp, wday;
struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
bool ds1307_can_wakeup_device = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
+ struct rtc_time tm;
+ unsigned long timestamp;
+
irq_handler_t irq_handler = ds1307_irq;
static const int bbsqi_bitpos[] = {
@@ -1526,6 +1526,27 @@ read_rtc:
bin2bcd(tmp));
}
+ /*
+ * Some IPs have weekday reset value = 0x1 which might not correct
+ * hence compute the wday using the current date/month/year values
+ */
+ ds1307_get_time(&client->dev, &tm);
+ wday = tm.tm_wday;
+ timestamp = rtc_tm_to_time64(&tm);
+ rtc_time64_to_tm(timestamp, &tm);
+
+ /*
+ * Check if reset wday is different from the computed wday
+ * If different then set the wday which we computed using
+ * timestamp
+ */
+ if (wday != tm.tm_wday) {
+ wday = i2c_smbus_read_byte_data(client, MCP794XX_REG_WEEKDAY);
+ wday = wday & ~MCP794XX_REG_WEEKDAY_WDAY_MASK;
+ wday = wday | (tm.tm_wday + 1);
+ i2c_smbus_write_byte_data(client, MCP794XX_REG_WEEKDAY, wday);
+ }
+
if (want_irq) {
device_set_wakeup_capable(&client->dev, true);
set_bit(HAS_ALARM, &ds1307->flags);
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index 23fa9f0cb5e3..895fbeeb47fe 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -504,12 +504,6 @@ static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour;
alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday;
- alarm->time.tm_mon = -1;
- alarm->time.tm_year = -1;
- alarm->time.tm_wday = -1;
- alarm->time.tm_yday = -1;
- alarm->time.tm_isdst = -1;
-
out:
mutex_unlock(&priv->mutex);
return res;
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index b3ce3c652fcd..ed43b4311660 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -103,6 +103,26 @@ ds1685_rtc_bin2bcd(struct ds1685_priv *rtc, u8 val, u8 bin_mask, u8 bcd_mask)
}
/**
+ * s1685_rtc_check_mday - check validity of the day of month.
+ * @rtc: pointer to the ds1685 rtc structure.
+ * @mday: day of month.
+ *
+ * Returns -EDOM if the day of month is not within 1..31 range.
+ */
+static inline int
+ds1685_rtc_check_mday(struct ds1685_priv *rtc, u8 mday)
+{
+ if (rtc->bcd_mode) {
+ if (mday < 0x01 || mday > 0x31 || (mday & 0x0f) > 0x09)
+ return -EDOM;
+ } else {
+ if (mday < 1 || mday > 31)
+ return -EDOM;
+ }
+ return 0;
+}
+
+/**
* ds1685_rtc_switch_to_bank0 - switch the rtc to bank 0.
* @rtc: pointer to the ds1685 rtc structure.
*/
@@ -377,6 +397,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
+ int ret;
/* Fetch the alarm info from the RTC alarm registers. */
ds1685_rtc_begin_data_access(rtc);
@@ -388,34 +409,29 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ctrlc = rtc->read(rtc, RTC_CTRL_C);
ds1685_rtc_end_data_access(rtc);
- /* Check month date. */
- if (!(mday >= 1) && (mday <= 31))
- return -EDOM;
+ /* Check the month date for validity. */
+ ret = ds1685_rtc_check_mday(rtc, mday);
+ if (ret)
+ return ret;
/*
* Check the three alarm bytes.
*
* The Linux RTC system doesn't support the "don't care" capability
* of this RTC chip. We check for it anyways in case support is
- * added in the future.
+ * added in the future and only assign when we care.
*/
- if (unlikely(seconds >= 0xc0))
- alrm->time.tm_sec = -1;
- else
+ if (likely(seconds < 0xc0))
alrm->time.tm_sec = ds1685_rtc_bcd2bin(rtc, seconds,
RTC_SECS_BCD_MASK,
RTC_SECS_BIN_MASK);
- if (unlikely(minutes >= 0xc0))
- alrm->time.tm_min = -1;
- else
+ if (likely(minutes < 0xc0))
alrm->time.tm_min = ds1685_rtc_bcd2bin(rtc, minutes,
RTC_MINS_BCD_MASK,
RTC_MINS_BIN_MASK);
- if (unlikely(hours >= 0xc0))
- alrm->time.tm_hour = -1;
- else
+ if (likely(hours < 0xc0))
alrm->time.tm_hour = ds1685_rtc_bcd2bin(rtc, hours,
RTC_HRS_24_BCD_MASK,
RTC_HRS_24_BIN_MASK);
@@ -423,11 +439,6 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Write the data to rtc_wkalrm. */
alrm->time.tm_mday = ds1685_rtc_bcd2bin(rtc, mday, RTC_MDAY_BCD_MASK,
RTC_MDAY_BIN_MASK);
- alrm->time.tm_mon = -1;
- alrm->time.tm_year = -1;
- alrm->time.tm_wday = -1;
- alrm->time.tm_yday = -1;
- alrm->time.tm_isdst = -1;
alrm->enabled = !!(ctrlb & RTC_CTRL_B_AIE);
alrm->pending = !!(ctrlc & RTC_CTRL_C_AF);
@@ -445,6 +456,7 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct platform_device *pdev = to_platform_device(dev);
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
u8 ctrlb, seconds, minutes, hours, mday;
+ int ret;
/* Fetch the alarm info and convert to BCD. */
seconds = ds1685_rtc_bin2bcd(rtc, alrm->time.tm_sec,
@@ -461,8 +473,9 @@ ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
RTC_MDAY_BCD_MASK);
/* Check the month date for validity. */
- if (!(mday >= 1) && (mday <= 31))
- return -EDOM;
+ ret = ds1685_rtc_check_mday(rtc, mday);
+ if (ret)
+ return ret;
/*
* Check the three alarm bytes.
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c
index 16310fe79d76..9a1582ed7070 100644
--- a/drivers/rtc/rtc-ds2404.c
+++ b/drivers/rtc/rtc-ds2404.c
@@ -13,7 +13,7 @@
#include <linux/rtc.h>
#include <linux/types.h>
#include <linux/bcd.h>
-#include <linux/rtc-ds2404.h>
+#include <linux/platform_data/rtc-ds2404.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 04fbd7fffd0d..b1f20d8c358f 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -197,12 +197,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = bcd2bin(buf[2] & 0x7F);
alarm->time.tm_mday = bcd2bin(buf[3] & 0x7F);
- alarm->time.tm_mon = -1;
- alarm->time.tm_year = -1;
- alarm->time.tm_wday = -1;
- alarm->time.tm_yday = -1;
- alarm->time.tm_isdst = -1;
-
alarm->enabled = !!(control & DS3232_REG_CR_A1IE);
alarm->pending = !!(stat & DS3232_REG_SR_A1F);
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index 96d38609d803..0130afd7fe88 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -259,6 +259,12 @@ static const struct rtc_class_ops efi_rtc_ops = {
static int __init efi_rtc_probe(struct platform_device *dev)
{
struct rtc_device *rtc;
+ efi_time_t eft;
+ efi_time_cap_t cap;
+
+ /* First check if the RTC is usable */
+ if (efi.get_time(&eft, &cap) != EFI_SUCCESS)
+ return -ENODEV;
rtc = devm_rtc_device_register(&dev->dev, "rtc-efi", &efi_rtc_ops,
THIS_MODULE);
diff --git a/drivers/rtc/rtc-generic.c b/drivers/rtc/rtc-generic.c
index d726c6aa96a8..1bf5d2347928 100644
--- a/drivers/rtc/rtc-generic.c
+++ b/drivers/rtc/rtc-generic.c
@@ -9,44 +9,10 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
-#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
- defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
-#include <asm/rtc.h>
-
-static int generic_get_time(struct device *dev, struct rtc_time *tm)
-{
- unsigned int ret = get_rtc_time(tm);
-
- if (ret & RTC_BATT_BAD)
- return -EOPNOTSUPP;
-
- return rtc_valid_tm(tm);
-}
-
-static int generic_set_time(struct device *dev, struct rtc_time *tm)
-{
- if (set_rtc_time(tm) < 0)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
-static const struct rtc_class_ops generic_rtc_ops = {
- .read_time = generic_get_time,
- .set_time = generic_set_time,
-};
-#else
-#define generic_rtc_ops *(struct rtc_class_ops*)NULL
-#endif
-
static int __init generic_rtc_probe(struct platform_device *dev)
{
struct rtc_device *rtc;
- const struct rtc_class_ops *ops;
-
- ops = dev_get_platdata(&dev->dev);
- if (!ops)
- ops = &generic_rtc_ops;
+ const struct rtc_class_ops *ops = dev_get_platdata(&dev->dev);
rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
ops, THIS_MODULE);
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 207270376b55..e5ad527cb75e 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -198,7 +198,7 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
/* The alarm only has a minute accuracy */
- alm_tm->tm_sec = -1;
+ alm_tm->tm_sec = 0;
alm_tm->tm_min = (buf[0] & HYM8563_ALM_BIT_DISABLE) ?
-1 :
@@ -213,9 +213,6 @@ static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
-1 :
bcd2bin(buf[3] & HYM8563_WEEKDAY_MASK);
- alm_tm->tm_mon = -1;
- alm_tm->tm_year = -1;
-
ret = i2c_smbus_read_byte_data(client, HYM8563_CTL2);
if (ret < 0)
return ret;
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c
index 54328d4ac0d3..0e7f0f52bfe4 100644
--- a/drivers/rtc/rtc-isl12057.c
+++ b/drivers/rtc/rtc-isl12057.c
@@ -245,8 +245,7 @@ static int isl12057_rtc_update_alarm(struct device *dev, int enable)
static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
- struct rtc_time rtc_tm, *alarm_tm = &alarm->time;
- unsigned long rtc_secs, alarm_secs;
+ struct rtc_time *alarm_tm = &alarm->time;
u8 regs[ISL12057_A1_SEC_LEN];
unsigned int ir;
int ret;
@@ -264,36 +263,6 @@ static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f);
alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f);
alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f);
- alarm_tm->tm_wday = -1;
-
- /*
- * The alarm section does not store year/month. We use the ones in rtc
- * section as a basis and increment month and then year if needed to get
- * alarm after current time.
- */
- ret = _isl12057_rtc_read_time(dev, &rtc_tm);
- if (ret)
- goto err_unlock;
-
- alarm_tm->tm_year = rtc_tm.tm_year;
- alarm_tm->tm_mon = rtc_tm.tm_mon;
-
- ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
- if (ret)
- goto err_unlock;
-
- ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
- if (ret)
- goto err_unlock;
-
- if (alarm_secs < rtc_secs) {
- if (alarm_tm->tm_mon == 11) {
- alarm_tm->tm_mon = 0;
- alarm_tm->tm_year += 1;
- } else {
- alarm_tm->tm_mon += 1;
- }
- }
ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir);
if (ret) {
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index d1bf93a87200..58698d21c2c3 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -244,7 +244,7 @@ static int m41t80_alarm_irq_enable(struct device *dev, unsigned int enabled)
retval = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, flags);
if (retval < 0) {
- dev_info(dev, "Unable to enable alarm IRQ %d\n", retval);
+ dev_err(dev, "Unable to enable alarm IRQ %d\n", retval);
return retval;
}
return 0;
@@ -320,10 +320,8 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
alrm->time.tm_sec = bcd2bin(alarmvals[4] & 0x7f);
alrm->time.tm_min = bcd2bin(alarmvals[3] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[2] & 0x3f);
- alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_mon = bcd2bin(alarmvals[0] & 0x3f);
- alrm->time.tm_year = -1;
alrm->enabled = !!(alarmvals[0] & M41T80_ALMON_AFE);
alrm->pending = (flags & M41T80_FLAGS_AF) && alrm->enabled;
@@ -337,6 +335,30 @@ static struct rtc_class_ops m41t80_rtc_ops = {
.proc = m41t80_rtc_proc,
};
+#ifdef CONFIG_PM_SLEEP
+static int m41t80_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ if (client->irq >= 0 && device_may_wakeup(dev))
+ enable_irq_wake(client->irq);
+
+ return 0;
+}
+
+static int m41t80_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ if (client->irq >= 0 && device_may_wakeup(dev))
+ disable_irq_wake(client->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume);
+
static ssize_t flags_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -831,10 +853,9 @@ static int m41t80_probe(struct i2c_client *client,
return rc;
}
- rc = devm_add_action(&client->dev, m41t80_remove_sysfs_group,
- &client->dev);
+ rc = devm_add_action_or_reset(&client->dev, m41t80_remove_sysfs_group,
+ &client->dev);
if (rc) {
- m41t80_remove_sysfs_group(&client->dev);
dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n", rc);
return rc;
@@ -873,6 +894,7 @@ static int m41t80_remove(struct i2c_client *client)
static struct i2c_driver m41t80_driver = {
.driver = {
.name = "rtc-m41t80",
+ .pm = &m41t80_pm,
},
.probe = m41t80_probe,
.remove = m41t80_remove,
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index f72b91f2501f..0eeb5714c00f 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -16,7 +16,7 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h>
#define M48T86_REG_SEC 0x00
diff --git a/drivers/rtc/rtc-max6916.c b/drivers/rtc/rtc-max6916.c
new file mode 100644
index 000000000000..623ab27b2757
--- /dev/null
+++ b/drivers/rtc/rtc-max6916.c
@@ -0,0 +1,164 @@
+/* rtc-max6916.c
+ *
+ * Driver for MAXIM max6916 Low Current, SPI Compatible
+ * Real Time Clock
+ *
+ * Author : Venkat Prashanth B U <venkat.prashanth2498@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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+
+/* Registers in max6916 rtc */
+
+#define MAX6916_SECONDS_REG 0x01
+#define MAX6916_MINUTES_REG 0x02
+#define MAX6916_HOURS_REG 0x03
+#define MAX6916_DATE_REG 0x04
+#define MAX6916_MONTH_REG 0x05
+#define MAX6916_DAY_REG 0x06
+#define MAX6916_YEAR_REG 0x07
+#define MAX6916_CONTROL_REG 0x08
+#define MAX6916_STATUS_REG 0x0C
+#define MAX6916_CLOCK_BURST 0x3F
+
+static int max6916_read_reg(struct device *dev, unsigned char address,
+ unsigned char *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ *data = address | 0x80;
+
+ return spi_write_then_read(spi, data, 1, data, 1);
+}
+
+static int max6916_write_reg(struct device *dev, unsigned char address,
+ unsigned char data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ unsigned char buf[2];
+
+ buf[0] = address & 0x7F;
+ buf[1] = data;
+
+ return spi_write_then_read(spi, buf, 2, NULL, 0);
+}
+
+static int max6916_read_time(struct device *dev, struct rtc_time *dt)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ int err;
+ unsigned char buf[8];
+
+ buf[0] = MAX6916_CLOCK_BURST | 0x80;
+
+ err = spi_write_then_read(spi, buf, 1, buf, 8);
+
+ if (err)
+ return err;
+
+ dt->tm_sec = bcd2bin(buf[0]);
+ dt->tm_min = bcd2bin(buf[1]);
+ dt->tm_hour = bcd2bin(buf[2] & 0x3F);
+ dt->tm_mday = bcd2bin(buf[3]);
+ dt->tm_mon = bcd2bin(buf[4]) - 1;
+ dt->tm_wday = bcd2bin(buf[5]) - 1;
+ dt->tm_year = bcd2bin(buf[6]) + 100;
+
+ return rtc_valid_tm(dt);
+}
+
+static int max6916_set_time(struct device *dev, struct rtc_time *dt)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ unsigned char buf[9];
+
+ if (dt->tm_year < 100 || dt->tm_year > 199) {
+ dev_err(&spi->dev, "Year must be between 2000 and 2099. It's %d.\n",
+ dt->tm_year + 1900);
+ return -EINVAL;
+ }
+
+ buf[0] = MAX6916_CLOCK_BURST & 0x7F;
+ buf[1] = bin2bcd(dt->tm_sec);
+ buf[2] = bin2bcd(dt->tm_min);
+ buf[3] = (bin2bcd(dt->tm_hour) & 0X3F);
+ buf[4] = bin2bcd(dt->tm_mday);
+ buf[5] = bin2bcd(dt->tm_mon + 1);
+ buf[6] = bin2bcd(dt->tm_wday + 1);
+ buf[7] = bin2bcd(dt->tm_year % 100);
+ buf[8] = bin2bcd(0x00);
+
+ /* write the rtc settings */
+ return spi_write_then_read(spi, buf, 9, NULL, 0);
+}
+
+static const struct rtc_class_ops max6916_rtc_ops = {
+ .read_time = max6916_read_time,
+ .set_time = max6916_set_time,
+};
+
+static int max6916_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ unsigned char data;
+ int res;
+
+ /* spi setup with max6916 in mode 3 and bits per word as 8 */
+ spi->mode = SPI_MODE_3;
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ /* RTC Settings */
+ res = max6916_read_reg(&spi->dev, MAX6916_SECONDS_REG, &data);
+ if (res)
+ return res;
+
+ /* Disable the write protect of rtc */
+ max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
+ data = data & ~(1 << 7);
+ max6916_write_reg(&spi->dev, MAX6916_CONTROL_REG, data);
+
+ /*Enable oscillator,disable oscillator stop flag, glitch filter*/
+ max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
+ data = data & 0x1B;
+ max6916_write_reg(&spi->dev, MAX6916_STATUS_REG, data);
+
+ /* display the settings */
+ max6916_read_reg(&spi->dev, MAX6916_CONTROL_REG, &data);
+ dev_info(&spi->dev, "MAX6916 RTC CTRL Reg = 0x%02x\n", data);
+
+ max6916_read_reg(&spi->dev, MAX6916_STATUS_REG, &data);
+ dev_info(&spi->dev, "MAX6916 RTC Status Reg = 0x%02x\n", data);
+
+ rtc = devm_rtc_device_register(&spi->dev, "max6916",
+ &max6916_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ spi_set_drvdata(spi, rtc);
+
+ return 0;
+}
+
+static struct spi_driver max6916_driver = {
+ .driver = {
+ .name = "max6916",
+ },
+ .probe = max6916_probe,
+};
+module_spi_driver(max6916_driver);
+
+MODULE_DESCRIPTION("MAX6916 SPI RTC DRIVER");
+MODULE_AUTHOR("Venkat Prashanth B U <venkat.prashanth2498@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/asm-generic/rtc.h b/drivers/rtc/rtc-mc146818-lib.c
index 4e3b6558331e..2f1772a358ca 100644
--- a/include/asm-generic/rtc.h
+++ b/drivers/rtc/rtc-mc146818-lib.c
@@ -1,40 +1,16 @@
-/*
- * include/asm-generic/rtc.h
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * Based on:
- * drivers/char/rtc.c
- *
- * Please read the COPYING file for all license details.
- */
-
-#ifndef __ASM_RTC_H__
-#define __ASM_RTC_H__
-
-#include <linux/mc146818rtc.h>
-#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/mc146818rtc.h>
+
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
#endif
-#define RTC_PIE 0x40 /* periodic interrupt enable */
-#define RTC_AIE 0x20 /* alarm interrupt enable */
-#define RTC_UIE 0x10 /* update-finished interrupt enable */
-
-/* some dummy definitions */
-#define RTC_BATT_BAD 0x100 /* battery bad */
-#define RTC_SQWE 0x08 /* enable square-wave output */
-#define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
-#define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
-#define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
-
/*
* Returns true if a clock update is in progress
*/
-static inline unsigned char rtc_is_updating(void)
+static inline unsigned char mc146818_is_updating(void)
{
unsigned char uip;
unsigned long flags;
@@ -45,7 +21,7 @@ static inline unsigned char rtc_is_updating(void)
return uip;
}
-static inline unsigned int __get_rtc_time(struct rtc_time *time)
+unsigned int mc146818_get_time(struct rtc_time *time)
{
unsigned char ctrl;
unsigned long flags;
@@ -60,11 +36,11 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
* can take just over 2ms. We wait 20ms. There is no need to
* to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
* If you need to know *exactly* when a second has started, enable
- * periodic update complete interrupts, (via ioctl) and then
+ * periodic update complete interrupts, (via ioctl) and then
* immediately read /dev/rtc which will block until you get the IRQ.
* Once the read clears, read the RTC time (again via ioctl). Easy.
*/
- if (rtc_is_updating())
+ if (mc146818_is_updating())
mdelay(20);
/*
@@ -120,13 +96,10 @@ static inline unsigned int __get_rtc_time(struct rtc_time *time)
return RTC_24H;
}
-
-#ifndef get_rtc_time
-#define get_rtc_time __get_rtc_time
-#endif
+EXPORT_SYMBOL_GPL(mc146818_get_time);
/* Set the current date and time in the real time clock. */
-static inline int __set_rtc_time(struct rtc_time *time)
+int mc146818_set_time(struct rtc_time *time)
{
unsigned long flags;
unsigned char mon, day, hrs, min, sec;
@@ -222,26 +195,4 @@ static inline int __set_rtc_time(struct rtc_time *time)
return 0;
}
-
-#ifndef set_rtc_time
-#define set_rtc_time __set_rtc_time
-#endif
-
-static inline unsigned int get_rtc_ss(void)
-{
- struct rtc_time h;
-
- get_rtc_time(&h);
- return h.tm_sec;
-}
-
-static inline int get_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-static inline int set_rtc_pll(struct rtc_pll_info *pll)
-{
- return -EINVAL;
-}
-
-#endif /* __ASM_RTC_H__ */
+EXPORT_SYMBOL_GPL(mc146818_set_time);
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 0094d9bdd1e6..7334c44fa7c3 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -32,11 +32,11 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/kernel.h>
+#include <linux/mc146818rtc.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sfi.h>
-#include <asm-generic/rtc.h>
#include <asm/intel_scu_ipc.h>
#include <asm/intel-mid.h>
#include <asm/intel_mid_vrtc.h>
@@ -149,14 +149,6 @@ static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (mrst->irq <= 0)
return -EIO;
- /* Basic alarms only support hour, minute, and seconds fields.
- * Some also support day and month, for alarms up to a year in
- * the future.
- */
- t->time.tm_mday = -1;
- t->time.tm_mon = -1;
- t->time.tm_year = -1;
-
/* vRTC only supports binary mode */
spin_lock_irq(&rtc_lock);
t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM);
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index f22e060709e5..b4478cc92b55 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -96,7 +96,7 @@
#define CD_TMR_TE BIT(3) /* Countdown timer enable */
/* PCF2123_REG_OFFSET BITS */
-#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */
+#define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */
#define OFFSET_COARSE BIT(7) /* Coarse mode offset */
#define OFFSET_STEP (2170) /* Offset step in parts per billion */
@@ -217,7 +217,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset)
if (reg & OFFSET_COARSE)
reg <<= 1; /* multiply by 2 and sign extend */
else
- reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
+ reg = sign_extend32(reg, OFFSET_SIGN_BIT);
*offset = ((long)reg) * OFFSET_STEP;
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index e8ddbb359d11..efb0a08ac117 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -16,6 +16,16 @@
#include <linux/rtc.h>
#include <linux/module.h>
+/*
+ * Information for this driver was pulled from the following datasheets.
+ *
+ * http://www.nxp.com/documents/data_sheet/PCF85063A.pdf
+ * http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
+ *
+ * PCF85063A -- Rev. 6 — 18 November 2015
+ * PCF85063TP -- Rev. 4 — 6 May 2015
+*/
+
#define PCF85063_REG_CTRL1 0x00 /* status */
#define PCF85063_REG_CTRL1_STOP BIT(5)
#define PCF85063_REG_CTRL2 0x01
@@ -55,10 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
return 0;
}
-/*
- * In the routines that deal directly with the pcf85063 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- */
+static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
+{
+ s32 ret;
+
+ /* start the clock */
+ ctrl1 &= PCF85063_REG_CTRL1_STOP;
+
+ ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failing to start the clock\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
int rc;
@@ -90,8 +112,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_wday = regs[4] & 0x07;
tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
tm->tm_year = bcd2bin(regs[6]);
- if (tm->tm_year < 70)
- tm->tm_year += 100; /* assume we are in 1970...2069 */
+ tm->tm_year += 100;
return rtc_valid_tm(tm);
}
@@ -99,13 +120,17 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
int rc;
- u8 regs[8];
+ u8 regs[7];
+ u8 ctrl1;
+
+ if ((tm->tm_year < 100) || (tm->tm_year > 199))
+ return -EINVAL;
/*
* to accurately set the time, reset the divider chain and keep it in
* reset state until all time/date registers are written
*/
- rc = pcf85063_stop_clock(client, &regs[7]);
+ rc = pcf85063_stop_clock(client, &ctrl1);
if (rc != 0)
return rc;
@@ -125,14 +150,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
regs[5] = bin2bcd(tm->tm_mon + 1);
/* year and century */
- regs[6] = bin2bcd(tm->tm_year % 100);
-
- /*
- * after all time/date registers are written, let the 'address auto
- * increment' feature wrap around and write register CTRL1 to re-enable
- * the clock divider chain again
- */
- regs[7] &= ~PCF85063_REG_CTRL1_STOP;
+ regs[6] = bin2bcd(tm->tm_year - 100);
/* write all registers at once */
rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
@@ -142,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return rc;
}
+ /*
+ * Write the control register as a separate action since the size of
+ * the register space is different between the PCF85063TP and
+ * PCF85063A devices. The rollover point can not be used.
+ */
+ rc = pcf85063_start_clock(client, ctrl1);
+ if (rc != 0)
+ return rc;
+
return 0;
}
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index b9ddbb001283..1227ceab61ee 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -341,14 +341,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
__func__, buf[0], buf[1], buf[2], buf[3]);
+ tm->time.tm_sec = 0;
tm->time.tm_min = bcd2bin(buf[0] & 0x7F);
tm->time.tm_hour = bcd2bin(buf[1] & 0x3F);
tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
- tm->time.tm_mon = -1;
- tm->time.tm_year = -1;
- tm->time.tm_yday = -1;
- tm->time.tm_isdst = -1;
err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
if (err < 0)
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c
index f28d57788951..68ce77414bdc 100644
--- a/drivers/rtc/rtc-rc5t583.c
+++ b/drivers/rtc/rtc-rc5t583.c
@@ -128,6 +128,7 @@ static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
return ret;
}
+ alm->time.tm_sec = 0;
alm->time.tm_min = bcd2bin(alarm_data[0]);
alm->time.tm_hour = bcd2bin(alarm_data[1]);
alm->time.tm_mday = bcd2bin(alarm_data[2]);
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index ef86229428fc..c8c757466783 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -341,12 +341,6 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
- t->time.tm_mday = -1;
- t->time.tm_mon = -1;
- t->time.tm_year = -1;
- t->time.tm_wday = -1;
- t->time.tm_yday = -1;
- t->time.tm_isdst = -1;
/* ... and status */
t->enabled = !!(rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE);
diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c
index f623038e586e..9a2f6a95d5a7 100644
--- a/drivers/rtc/rtc-rv8803.c
+++ b/drivers/rtc/rtc-rv8803.c
@@ -13,12 +13,15 @@
#include <linux/bcd.h>
#include <linux/bitops.h>
+#include <linux/log2.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/rtc.h>
+#define RV8803_I2C_TRY_COUNT 4
+
#define RV8803_SEC 0x00
#define RV8803_MIN 0x01
#define RV8803_HOUR 0x02
@@ -56,19 +59,85 @@ struct rv8803_data {
u8 ctrl;
};
+static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
+{
+ int try = RV8803_I2C_TRY_COUNT;
+ s32 ret;
+
+ /*
+ * There is a 61µs window during which the RTC does not acknowledge I2C
+ * transfers. In that case, ensure that there are multiple attempts.
+ */
+ do
+ ret = i2c_smbus_read_byte_data(client, reg);
+ while ((ret == -ENXIO || ret == -EIO) && --try);
+ if (ret < 0)
+ dev_err(&client->dev, "Unable to read register 0x%02x\n", reg);
+
+ return ret;
+}
+
+static int rv8803_read_regs(const struct i2c_client *client,
+ u8 reg, u8 count, u8 *values)
+{
+ int try = RV8803_I2C_TRY_COUNT;
+ s32 ret;
+
+ do
+ ret = i2c_smbus_read_i2c_block_data(client, reg, count, values);
+ while ((ret == -ENXIO || ret == -EIO) && --try);
+ if (ret != count) {
+ dev_err(&client->dev,
+ "Unable to read registers 0x%02x..0x%02x\n",
+ reg, reg + count - 1);
+ return ret < 0 ? ret : -EIO;
+ }
+
+ return 0;
+}
+
+static int rv8803_write_reg(const struct i2c_client *client, u8 reg, u8 value)
+{
+ int try = RV8803_I2C_TRY_COUNT;
+ s32 ret;
+
+ do
+ ret = i2c_smbus_write_byte_data(client, reg, value);
+ while ((ret == -ENXIO || ret == -EIO) && --try);
+ if (ret)
+ dev_err(&client->dev, "Unable to write register 0x%02x\n", reg);
+
+ return ret;
+}
+
+static int rv8803_write_regs(const struct i2c_client *client,
+ u8 reg, u8 count, const u8 *values)
+{
+ int try = RV8803_I2C_TRY_COUNT;
+ s32 ret;
+
+ do
+ ret = i2c_smbus_write_i2c_block_data(client, reg, count,
+ values);
+ while ((ret == -ENXIO || ret == -EIO) && --try);
+ if (ret)
+ dev_err(&client->dev,
+ "Unable to write registers 0x%02x..0x%02x\n",
+ reg, reg + count - 1);
+
+ return ret;
+}
+
static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct rv8803_data *rv8803 = i2c_get_clientdata(client);
unsigned long events = 0;
- int flags, try = 0;
+ int flags;
mutex_lock(&rv8803->flags_lock);
- do {
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
- try++;
- } while ((flags == -ENXIO) && (try < 3));
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags <= 0) {
mutex_unlock(&rv8803->flags_lock);
return IRQ_NONE;
@@ -100,9 +169,8 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id)
if (events) {
rtc_update_irq(rv8803->rtc, 1, events);
- i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
- i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
- rv8803->ctrl);
+ rv8803_write_reg(client, RV8803_FLAG, flags);
+ rv8803_write_reg(rv8803->client, RV8803_CTRL, rv8803->ctrl);
}
mutex_unlock(&rv8803->flags_lock);
@@ -118,7 +186,7 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
u8 *date = date1;
int ret, flags;
- flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+ flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0)
return flags;
@@ -127,16 +195,14 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
- ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
- 7, date);
- if (ret != 7)
- return ret < 0 ? ret : -EIO;
+ ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date);
+ if (ret)
+ return ret;
if ((date1[RV8803_SEC] & 0x7f) == bin2bcd(59)) {
- ret = i2c_smbus_read_i2c_block_data(rv8803->client, RV8803_SEC,
- 7, date2);
- if (ret != 7)
- return ret < 0 ? ret : -EIO;
+ ret = rv8803_read_regs(rv8803->client, RV8803_SEC, 7, date2);
+ if (ret)
+ return ret;
if ((date2[RV8803_SEC] & 0x7f) != bin2bcd(59))
date = date2;
@@ -145,23 +211,33 @@ static int rv8803_get_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec = bcd2bin(date[RV8803_SEC] & 0x7f);
tm->tm_min = bcd2bin(date[RV8803_MIN] & 0x7f);
tm->tm_hour = bcd2bin(date[RV8803_HOUR] & 0x3f);
- tm->tm_wday = ffs(date[RV8803_WEEK] & 0x7f);
+ tm->tm_wday = ilog2(date[RV8803_WEEK] & 0x7f);
tm->tm_mday = bcd2bin(date[RV8803_DAY] & 0x3f);
tm->tm_mon = bcd2bin(date[RV8803_MONTH] & 0x1f) - 1;
tm->tm_year = bcd2bin(date[RV8803_YEAR]) + 100;
- return rtc_valid_tm(tm);
+ return 0;
}
static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
{
struct rv8803_data *rv8803 = dev_get_drvdata(dev);
u8 date[7];
- int flags, ret;
+ int ctrl, flags, ret;
if ((tm->tm_year < 100) || (tm->tm_year > 199))
return -EINVAL;
+ ctrl = rv8803_read_reg(rv8803->client, RV8803_CTRL);
+ if (ctrl < 0)
+ return ctrl;
+
+ /* Stop the clock */
+ ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+ ctrl | RV8803_CTRL_RESET);
+ if (ret)
+ return ret;
+
date[RV8803_SEC] = bin2bcd(tm->tm_sec);
date[RV8803_MIN] = bin2bcd(tm->tm_min);
date[RV8803_HOUR] = bin2bcd(tm->tm_hour);
@@ -170,21 +246,26 @@ static int rv8803_set_time(struct device *dev, struct rtc_time *tm)
date[RV8803_MONTH] = bin2bcd(tm->tm_mon + 1);
date[RV8803_YEAR] = bin2bcd(tm->tm_year - 100);
- ret = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_SEC,
- 7, date);
- if (ret < 0)
+ ret = rv8803_write_regs(rv8803->client, RV8803_SEC, 7, date);
+ if (ret)
+ return ret;
+
+ /* Restart the clock */
+ ret = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+ ctrl & ~RV8803_CTRL_RESET);
+ if (ret)
return ret;
mutex_lock(&rv8803->flags_lock);
- flags = i2c_smbus_read_byte_data(rv8803->client, RV8803_FLAG);
+ flags = rv8803_read_reg(rv8803->client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
- ret = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG,
- flags & ~RV8803_FLAG_V2F);
+ ret = rv8803_write_reg(rv8803->client, RV8803_FLAG,
+ flags & ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F));
mutex_unlock(&rv8803->flags_lock);
@@ -198,22 +279,18 @@ static int rv8803_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 alarmvals[3];
int flags, ret;
- ret = i2c_smbus_read_i2c_block_data(client, RV8803_ALARM_MIN,
- 3, alarmvals);
- if (ret != 3)
- return ret < 0 ? ret : -EIO;
+ ret = rv8803_read_regs(client, RV8803_ALARM_MIN, 3, alarmvals);
+ if (ret)
+ return ret;
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
alrm->time.tm_sec = 0;
alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
- alrm->time.tm_wday = -1;
alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
- alrm->time.tm_mon = -1;
- alrm->time.tm_year = -1;
alrm->enabled = !!(rv8803->ctrl & RV8803_CTRL_AIE);
alrm->pending = (flags & RV8803_FLAG_AF) && alrm->enabled;
@@ -239,10 +316,10 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
mutex_lock(&rv8803->flags_lock);
- ret = i2c_smbus_read_i2c_block_data(client, RV8803_FLAG, 2, ctrl);
- if (ret != 2) {
+ ret = rv8803_read_regs(client, RV8803_FLAG, 2, ctrl);
+ if (ret) {
mutex_unlock(&rv8803->flags_lock);
- return ret < 0 ? ret : -EIO;
+ return ret;
}
alarmvals[0] = bin2bcd(alrm->time.tm_min);
@@ -251,8 +328,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rv8803->ctrl & (RV8803_CTRL_AIE | RV8803_CTRL_UIE)) {
rv8803->ctrl &= ~(RV8803_CTRL_AIE | RV8803_CTRL_UIE);
- err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
- rv8803->ctrl);
+ err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+ rv8803->ctrl);
if (err) {
mutex_unlock(&rv8803->flags_lock);
return err;
@@ -260,13 +337,12 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
ctrl[1] &= ~RV8803_FLAG_AF;
- err = i2c_smbus_write_byte_data(rv8803->client, RV8803_FLAG, ctrl[1]);
+ err = rv8803_write_reg(rv8803->client, RV8803_FLAG, ctrl[1]);
mutex_unlock(&rv8803->flags_lock);
if (err)
return err;
- err = i2c_smbus_write_i2c_block_data(rv8803->client, RV8803_ALARM_MIN,
- 3, alarmvals);
+ err = rv8803_write_regs(rv8803->client, RV8803_ALARM_MIN, 3, alarmvals);
if (err)
return err;
@@ -276,8 +352,8 @@ static int rv8803_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (rv8803->rtc->aie_timer.enabled)
rv8803->ctrl |= RV8803_CTRL_AIE;
- err = i2c_smbus_write_byte_data(rv8803->client, RV8803_CTRL,
- rv8803->ctrl);
+ err = rv8803_write_reg(rv8803->client, RV8803_CTRL,
+ rv8803->ctrl);
if (err)
return err;
}
@@ -306,21 +382,20 @@ static int rv8803_alarm_irq_enable(struct device *dev, unsigned int enabled)
}
mutex_lock(&rv8803->flags_lock);
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
flags &= ~(RV8803_FLAG_AF | RV8803_FLAG_UF);
- err = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+ err = rv8803_write_reg(client, RV8803_FLAG, flags);
mutex_unlock(&rv8803->flags_lock);
if (err)
return err;
if (ctrl != rv8803->ctrl) {
rv8803->ctrl = ctrl;
- err = i2c_smbus_write_byte_data(client, RV8803_CTRL,
- rv8803->ctrl);
+ err = rv8803_write_reg(client, RV8803_CTRL, rv8803->ctrl);
if (err)
return err;
}
@@ -336,7 +411,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
switch (cmd) {
case RTC_VL_READ:
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
@@ -355,16 +430,16 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
case RTC_VL_CLR:
mutex_lock(&rv8803->flags_lock);
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0) {
mutex_unlock(&rv8803->flags_lock);
return flags;
}
flags &= ~(RV8803_FLAG_V1F | RV8803_FLAG_V2F);
- ret = i2c_smbus_write_byte_data(client, RV8803_FLAG, flags);
+ ret = rv8803_write_reg(client, RV8803_FLAG, flags);
mutex_unlock(&rv8803->flags_lock);
- if (ret < 0)
+ if (ret)
return ret;
return 0;
@@ -382,8 +457,8 @@ static ssize_t rv8803_nvram_write(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev);
int ret;
- ret = i2c_smbus_write_byte_data(client, RV8803_RAM, buf[0]);
- if (ret < 0)
+ ret = rv8803_write_reg(client, RV8803_RAM, buf[0]);
+ if (ret)
return ret;
return 1;
@@ -397,7 +472,7 @@ static ssize_t rv8803_nvram_read(struct file *filp, struct kobject *kobj,
struct i2c_client *client = to_i2c_client(dev);
int ret;
- ret = i2c_smbus_read_byte_data(client, RV8803_RAM);
+ ret = rv8803_read_reg(client, RV8803_RAM);
if (ret < 0)
return ret;
@@ -427,7 +502,7 @@ static int rv8803_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rv8803_data *rv8803;
- int err, flags, try = 0;
+ int err, flags;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_I2C_BLOCK)) {
@@ -444,16 +519,7 @@ static int rv8803_probe(struct i2c_client *client,
rv8803->client = client;
i2c_set_clientdata(client, rv8803);
- /*
- * There is a 60µs window where the RTC may not reply on the i2c bus in
- * that case, the transfer is not ACKed. In that case, ensure there are
- * multiple attempts.
- */
- do {
- flags = i2c_smbus_read_byte_data(client, RV8803_FLAG);
- try++;
- } while ((flags == -ENXIO) && (try < 3));
-
+ flags = rv8803_read_reg(client, RV8803_FLAG);
if (flags < 0)
return flags;
@@ -488,12 +554,7 @@ static int rv8803_probe(struct i2c_client *client,
return PTR_ERR(rv8803->rtc);
}
- try = 0;
- do {
- err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT,
- RV8803_EXT_WADA);
- try++;
- } while ((err == -ENXIO) && (try < 3));
+ err = rv8803_write_reg(rv8803->client, RV8803_EXT, RV8803_EXT_WADA);
if (err)
return err;
diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c
index 772d221ec2d9..7163b91bb773 100644
--- a/drivers/rtc/rtc-rx8010.c
+++ b/drivers/rtc/rtc-rx8010.c
@@ -272,15 +272,9 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
- if (alarmvals[2] & RX8010_ALARM_AE)
- t->time.tm_mday = -1;
- else
+ if (!(alarmvals[2] & RX8010_ALARM_AE))
t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f);
- t->time.tm_wday = -1;
- t->time.tm_mon = -1;
- t->time.tm_year = -1;
-
t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index 9f105efbc546..2b85cc7a24e7 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -319,11 +319,6 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->time.tm_hour = bcd2bin(ald[1] & 0x1f) % 12
+ (ald[1] & 0x20 ? 12 : 0);
- t->time.tm_wday = -1;
- t->time.tm_mday = -1;
- t->time.tm_mon = -1;
- t->time.tm_year = -1;
-
dev_dbg(dev, "%s: date: %ds %dm %dh %dmd %dm %dy\n",
__func__,
t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c
index f40afdd0e5f5..5dab4665ca3b 100644
--- a/drivers/rtc/rtc-s35390a.c
+++ b/drivers/rtc/rtc-s35390a.c
@@ -15,6 +15,7 @@
#include <linux/bitrev.h>
#include <linux/bcd.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#define S35390A_CMD_STATUS1 0
#define S35390A_CMD_STATUS2 1
@@ -34,10 +35,14 @@
#define S35390A_ALRM_BYTE_HOURS 1
#define S35390A_ALRM_BYTE_MINS 2
+/* flags for STATUS1 */
#define S35390A_FLAG_POC 0x01
#define S35390A_FLAG_BLD 0x02
+#define S35390A_FLAG_INT2 0x04
#define S35390A_FLAG_24H 0x40
#define S35390A_FLAG_RESET 0x80
+
+/* flag for STATUS2 */
#define S35390A_FLAG_TEST 0x01
#define S35390A_INT2_MODE_MASK 0xF0
@@ -94,19 +99,63 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len)
return 0;
}
-static int s35390a_reset(struct s35390a *s35390a)
+/*
+ * Returns <0 on error, 0 if rtc is setup fine and 1 if the chip was reset.
+ * To keep the information if an irq is pending, pass the value read from
+ * STATUS1 to the caller.
+ */
+static int s35390a_reset(struct s35390a *s35390a, char *status1)
{
- char buf[1];
-
- if (s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf)) < 0)
- return -EIO;
-
- if (!(buf[0] & (S35390A_FLAG_POC | S35390A_FLAG_BLD)))
+ char buf;
+ int ret;
+ unsigned initcount = 0;
+
+ ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, status1, 1);
+ if (ret < 0)
+ return ret;
+
+ if (*status1 & S35390A_FLAG_POC)
+ /*
+ * Do not communicate for 0.5 seconds since the power-on
+ * detection circuit is in operation.
+ */
+ msleep(500);
+ else if (!(*status1 & S35390A_FLAG_BLD))
+ /*
+ * If both POC and BLD are unset everything is fine.
+ */
return 0;
- buf[0] |= (S35390A_FLAG_RESET | S35390A_FLAG_24H);
- buf[0] &= 0xf0;
- return s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
+ /*
+ * At least one of POC and BLD are set, so reinitialise chip. Keeping
+ * this information in the hardware to know later that the time isn't
+ * valid is unfortunately not possible because POC and BLD are cleared
+ * on read. So the reset is best done now.
+ *
+ * The 24H bit is kept over reset, so set it already here.
+ */
+initialize:
+ *status1 = S35390A_FLAG_24H;
+ buf = S35390A_FLAG_RESET | S35390A_FLAG_24H;
+ ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+
+ if (ret < 0)
+ return ret;
+
+ ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1);
+ if (ret < 0)
+ return ret;
+
+ if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) {
+ /* Try up to five times to reset the chip */
+ if (initcount < 5) {
+ ++initcount;
+ goto initialize;
+ } else
+ return -EIO;
+ }
+
+ return 1;
}
static int s35390a_disable_test_mode(struct s35390a *s35390a)
@@ -217,12 +266,12 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday,
alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday);
- /* disable interrupt */
+ /* disable interrupt (which deasserts the irq line) */
err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts));
if (err < 0)
return err;
- /* clear pending interrupt, if any */
+ /* clear pending interrupt (in STATUS1 only), if any */
err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts));
if (err < 0)
return err;
@@ -242,6 +291,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (alm->time.tm_wday != -1)
buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
+ else
+ buf[S35390A_ALRM_BYTE_WDAY] = 0;
buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
alm->time.tm_hour) | 0x80;
@@ -269,23 +320,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
if (err < 0)
return err;
- if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
- return -EINVAL;
+ if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
+ /*
+ * When the alarm isn't enabled, the register to configure
+ * the alarm time isn't accessible.
+ */
+ alm->enabled = 0;
+ return 0;
+ } else {
+ alm->enabled = 1;
+ }
err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
if (err < 0)
return err;
/* This chip returns the bits of each byte in reverse order */
- for (i = 0; i < 3; ++i) {
+ for (i = 0; i < 3; ++i)
buf[i] = bitrev8(buf[i]);
- buf[i] &= ~0x80;
- }
- alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
- alm->time.tm_hour = s35390a_reg2hr(s35390a,
- buf[S35390A_ALRM_BYTE_HOURS]);
- alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
+ /*
+ * B0 of the three matching registers is an enable flag. Iff it is set
+ * the configured value is used for matching.
+ */
+ if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
+ alm->time.tm_wday =
+ bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
+
+ if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
+ alm->time.tm_hour =
+ s35390a_reg2hr(s35390a,
+ buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
+
+ if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
+ alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
+
+ /* alarm triggers always at s=0 */
+ alm->time.tm_sec = 0;
dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
__func__, alm->time.tm_min, alm->time.tm_hour,
@@ -327,11 +398,11 @@ static struct i2c_driver s35390a_driver;
static int s35390a_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int err;
+ int err, err_reset;
unsigned int i;
struct s35390a *s35390a;
struct rtc_time tm;
- char buf[1];
+ char buf, status1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
@@ -360,29 +431,35 @@ static int s35390a_probe(struct i2c_client *client,
}
}
- err = s35390a_reset(s35390a);
- if (err < 0) {
+ err_reset = s35390a_reset(s35390a, &status1);
+ if (err_reset < 0) {
+ err = err_reset;
dev_err(&client->dev, "error resetting chip\n");
goto exit_dummy;
}
- err = s35390a_disable_test_mode(s35390a);
- if (err < 0) {
- dev_err(&client->dev, "error disabling test mode\n");
- goto exit_dummy;
- }
-
- err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, buf, sizeof(buf));
- if (err < 0) {
- dev_err(&client->dev, "error checking 12/24 hour mode\n");
- goto exit_dummy;
- }
- if (buf[0] & S35390A_FLAG_24H)
+ if (status1 & S35390A_FLAG_24H)
s35390a->twentyfourhour = 1;
else
s35390a->twentyfourhour = 0;
- if (s35390a_get_datetime(client, &tm) < 0)
+ if (status1 & S35390A_FLAG_INT2) {
+ /* disable alarm (and maybe test mode) */
+ buf = 0;
+ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1);
+ if (err < 0) {
+ dev_err(&client->dev, "error disabling alarm");
+ goto exit_dummy;
+ }
+ } else {
+ err = s35390a_disable_test_mode(s35390a);
+ if (err < 0) {
+ dev_err(&client->dev, "error disabling test mode\n");
+ goto exit_dummy;
+ }
+ }
+
+ if (err_reset > 0 || s35390a_get_datetime(client, &tm) < 0)
dev_warn(&client->dev, "clock needs to be set\n");
device_set_wakeup_capable(&client->dev, 1);
@@ -395,6 +472,10 @@ static int s35390a_probe(struct i2c_client *client,
err = PTR_ERR(s35390a->rtc);
goto exit_dummy;
}
+
+ if (status1 & S35390A_FLAG_INT2)
+ rtc_update_irq(s35390a->rtc, 1, RTC_AF);
+
return 0;
exit_dummy:
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index d01ad7e8078e..d44fb34df8fe 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
if (!is_power_of_2(freq))
return -EINVAL;
+ s3c_rtc_enable_clk(info);
spin_lock_irq(&info->pie_lock);
if (info->data->set_freq)
info->data->set_freq(info, freq);
spin_unlock_irq(&info->pie_lock);
+ s3c_rtc_disable_clk(info);
return 0;
}
@@ -264,35 +266,23 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* decode the alarm enable field */
if (alm_en & S3C2410_RTCALM_SECEN)
alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
- else
- alm_tm->tm_sec = -1;
if (alm_en & S3C2410_RTCALM_MINEN)
alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
- else
- alm_tm->tm_min = -1;
if (alm_en & S3C2410_RTCALM_HOUREN)
alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
- else
- alm_tm->tm_hour = -1;
if (alm_en & S3C2410_RTCALM_DAYEN)
alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
- else
- alm_tm->tm_mday = -1;
if (alm_en & S3C2410_RTCALM_MONEN) {
alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
alm_tm->tm_mon -= 1;
- } else {
- alm_tm->tm_mon = -1;
}
if (alm_en & S3C2410_RTCALM_YEAREN)
alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
- else
- alm_tm->tm_year = -1;
return 0;
}
@@ -577,8 +567,6 @@ static int s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_setfreq(info, 1);
- s3c_rtc_disable_clk(info);
-
return 0;
err_nortc:
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index a45845a571e5..17b6235d67a5 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -481,7 +481,6 @@ static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
tm->tm_mon = sh_rtc_read_alarm_value(rtc, RMONAR);
if (tm->tm_mon > 0)
tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
- tm->tm_year = 0xffff;
wkalrm->enabled = (readb(rtc->regbase + RCR1) & RCR1_AIE) ? 1 : 0;
@@ -500,52 +499,13 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
writeb(bin2bcd(value) | AR_ENB, rtc->regbase + reg_off);
}
-static int sh_rtc_check_alarm(struct rtc_time *tm)
-{
- /*
- * The original rtc says anything > 0xc0 is "don't care" or "match
- * all" - most users use 0xff but rtc-dev uses -1 for the same thing.
- * The original rtc doesn't support years - some things use -1 and
- * some 0xffff. We use -1 to make out tests easier.
- */
- if (tm->tm_year == 0xffff)
- tm->tm_year = -1;
- if (tm->tm_mon >= 0xff)
- tm->tm_mon = -1;
- if (tm->tm_mday >= 0xff)
- tm->tm_mday = -1;
- if (tm->tm_wday >= 0xff)
- tm->tm_wday = -1;
- if (tm->tm_hour >= 0xff)
- tm->tm_hour = -1;
- if (tm->tm_min >= 0xff)
- tm->tm_min = -1;
- if (tm->tm_sec >= 0xff)
- tm->tm_sec = -1;
-
- if (tm->tm_year > 9999 ||
- tm->tm_mon >= 12 ||
- tm->tm_mday == 0 || tm->tm_mday >= 32 ||
- tm->tm_wday >= 7 ||
- tm->tm_hour >= 24 ||
- tm->tm_min >= 60 ||
- tm->tm_sec >= 60)
- return -EINVAL;
-
- return 0;
-}
-
static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
struct platform_device *pdev = to_platform_device(dev);
struct sh_rtc *rtc = platform_get_drvdata(pdev);
unsigned int rcr1;
struct rtc_time *tm = &wkalrm->time;
- int mon, err;
-
- err = sh_rtc_check_alarm(tm);
- if (unlikely(err < 0))
- return err;
+ int mon;
spin_lock_irq(&rtc->lock);
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 60232bd366ef..15ac597d54da 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -179,12 +179,6 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
if (sec == 0) {
/* alarm is disabled. */
alarm->enabled = 0;
- alarm->time.tm_mon = -1;
- alarm->time.tm_mday = -1;
- alarm->time.tm_year = -1;
- alarm->time.tm_hour = -1;
- alarm->time.tm_min = -1;
- alarm->time.tm_sec = -1;
} else {
/* alarm is enabled. */
alarm->enabled = 1;
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index 7a0436329d6c..1f3117b5a83c 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -25,7 +25,7 @@
#include <linux/rtc.h>
#include <linux/types.h>
#include <linux/bcd.h>
-#include <linux/rtc-v3020.h>
+#include <linux/platform_data/rtc-v3020.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 8973d34ce5ba..fb1b56a71475 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1643,9 +1643,18 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
u8 *sense = NULL;
int expires;
+ cqr = (struct dasd_ccw_req *) intparm;
if (IS_ERR(irb)) {
switch (PTR_ERR(irb)) {
case -EIO:
+ if (cqr && cqr->status == DASD_CQR_CLEAR_PENDING) {
+ device = (struct dasd_device *) cqr->startdev;
+ cqr->status = DASD_CQR_CLEARED;
+ dasd_device_clear_timer(device);
+ wake_up(&dasd_flush_wq);
+ dasd_schedule_device_bh(device);
+ return;
+ }
break;
case -ETIMEDOUT:
DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
@@ -1661,7 +1670,6 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
}
now = get_tod_clock();
- cqr = (struct dasd_ccw_req *) intparm;
/* check for conditions that should be handled immediately */
if (!cqr ||
!(scsw_dstat(&irb->scsw) == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) &&
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index fd2eff440098..98bbec44bcd0 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -5078,6 +5078,8 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
return PTR_ERR(cqr);
}
+ cqr->lpm = lpum;
+retry:
cqr->startdev = device;
cqr->memdev = device;
cqr->block = NULL;
@@ -5122,6 +5124,14 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
(prssdp + 1);
memcpy(messages, message_buf,
sizeof(struct dasd_rssd_messages));
+ } else if (cqr->lpm) {
+ /*
+ * on z/VM we might not be able to do I/O on the requested path
+ * but instead we get the required information on any path
+ * so retry with open path mask
+ */
+ cqr->lpm = 0;
+ goto retry;
} else
DBF_EVENT_DEVID(DBF_WARNING, device->cdev,
"Reading messages failed with rc=%d\n"
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 7ada078ffdd0..6a58bc8f46e2 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -762,7 +762,6 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
priv->state = DEV_STATE_NOT_OPER;
priv->dev_id.devno = sch->schib.pmcw.dev;
priv->dev_id.ssid = sch->schid.ssid;
- priv->schid = sch->schid;
INIT_WORK(&priv->todo_work, ccw_device_todo);
INIT_LIST_HEAD(&priv->cmb_list);
@@ -1000,7 +999,6 @@ static int ccw_device_move_to_sch(struct ccw_device *cdev,
put_device(&old_sch->dev);
/* Initialize new subchannel. */
spin_lock_irq(sch->lock);
- cdev->private->schid = sch->schid;
cdev->ccwlock = sch->lock;
if (!sch_is_pseudo_sch(sch))
sch_set_cdev(sch, cdev);
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c
index 15b56a15db15..9bc3512374c9 100644
--- a/drivers/s390/cio/device_status.c
+++ b/drivers/s390/cio/device_status.c
@@ -26,6 +26,7 @@
static void
ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
char dbf_text[15];
if (!scsw_is_valid_cstat(&irb->scsw) ||
@@ -36,10 +37,10 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
"received"
" ... device %04x on subchannel 0.%x.%04x, dev_stat "
": %02X sch_stat : %02X\n",
- cdev->private->dev_id.devno, cdev->private->schid.ssid,
- cdev->private->schid.sch_no,
+ cdev->private->dev_id.devno, sch->schid.ssid,
+ sch->schid.sch_no,
scsw_dstat(&irb->scsw), scsw_cstat(&irb->scsw));
- sprintf(dbf_text, "chk%x", cdev->private->schid.sch_no);
+ sprintf(dbf_text, "chk%x", sch->schid.sch_no);
CIO_TRACE_EVENT(0, dbf_text);
CIO_HEX_EVENT(0, irb, sizeof(struct irb));
}
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index 8975060af96c..220f49145b2f 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -120,7 +120,6 @@ struct ccw_device_private {
int state; /* device state */
atomic_t onoff;
struct ccw_dev_id dev_id; /* device id */
- struct subchannel_id schid; /* subchannel number */
struct ccw_request req; /* internal I/O request */
int iretry;
u8 pgid_valid_mask; /* mask of valid PGIDs */
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 4bb5262f7aee..71bf9bded485 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -686,6 +686,15 @@ static void qdio_kick_handler(struct qdio_q *q)
q->qdio_error = 0;
}
+static inline int qdio_tasklet_schedule(struct qdio_q *q)
+{
+ if (likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE)) {
+ tasklet_schedule(&q->tasklet);
+ return 0;
+ }
+ return -EPERM;
+}
+
static void __qdio_inbound_processing(struct qdio_q *q)
{
qperf_inc(q, tasklet_inbound);
@@ -698,10 +707,8 @@ static void __qdio_inbound_processing(struct qdio_q *q)
if (!qdio_inbound_q_done(q)) {
/* means poll time is not yet over */
qperf_inc(q, tasklet_inbound_resched);
- if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
- tasklet_schedule(&q->tasklet);
+ if (!qdio_tasklet_schedule(q))
return;
- }
}
qdio_stop_polling(q);
@@ -711,8 +718,7 @@ static void __qdio_inbound_processing(struct qdio_q *q)
*/
if (!qdio_inbound_q_done(q)) {
qperf_inc(q, tasklet_inbound_resched2);
- if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
}
}
@@ -869,16 +875,15 @@ static void __qdio_outbound_processing(struct qdio_q *q)
* is noticed and outbound_handler is called after some time.
*/
if (qdio_outbound_q_done(q))
- del_timer(&q->u.out.timer);
+ del_timer_sync(&q->u.out.timer);
else
- if (!timer_pending(&q->u.out.timer))
+ if (!timer_pending(&q->u.out.timer) &&
+ likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE))
mod_timer(&q->u.out.timer, jiffies + 10 * HZ);
return;
sched:
- if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
- return;
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
}
/* outbound tasklet */
@@ -892,9 +897,7 @@ void qdio_outbound_timer(unsigned long data)
{
struct qdio_q *q = (struct qdio_q *)data;
- if (unlikely(q->irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
- return;
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
}
static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
@@ -907,7 +910,7 @@ static inline void qdio_check_outbound_after_thinint(struct qdio_q *q)
for_each_output_queue(q->irq_ptr, out, i)
if (!qdio_outbound_q_done(out))
- tasklet_schedule(&out->tasklet);
+ qdio_tasklet_schedule(out);
}
static void __tiqdio_inbound_processing(struct qdio_q *q)
@@ -929,10 +932,8 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
if (!qdio_inbound_q_done(q)) {
qperf_inc(q, tasklet_inbound_resched);
- if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) {
- tasklet_schedule(&q->tasklet);
+ if (!qdio_tasklet_schedule(q))
return;
- }
}
qdio_stop_polling(q);
@@ -942,8 +943,7 @@ static void __tiqdio_inbound_processing(struct qdio_q *q)
*/
if (!qdio_inbound_q_done(q)) {
qperf_inc(q, tasklet_inbound_resched2);
- if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED))
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
}
}
@@ -977,7 +977,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
int i;
struct qdio_q *q;
- if (unlikely(irq_ptr->state == QDIO_IRQ_STATE_STOPPED))
+ if (unlikely(irq_ptr->state != QDIO_IRQ_STATE_ACTIVE))
return;
for_each_input_queue(irq_ptr, q, i) {
@@ -1003,7 +1003,7 @@ static void qdio_int_handler_pci(struct qdio_irq *irq_ptr)
continue;
if (need_siga_sync(q) && need_siga_sync_out_after_pci(q))
qdio_siga_sync_q(q);
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
}
}
@@ -1066,10 +1066,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
struct irb *irb)
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+ struct subchannel_id schid;
int cstat, dstat;
if (!intparm || !irq_ptr) {
- DBF_ERROR("qint:%4x", cdev->private->schid.sch_no);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_ERROR("qint:%4x", schid.sch_no);
return;
}
@@ -1122,12 +1124,14 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
int qdio_get_ssqd_desc(struct ccw_device *cdev,
struct qdio_ssqd_desc *data)
{
+ struct subchannel_id schid;
if (!cdev || !cdev->private)
return -EINVAL;
- DBF_EVENT("get ssqd:%4x", cdev->private->schid.sch_no);
- return qdio_setup_get_ssqd(NULL, &cdev->private->schid, data);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_EVENT("get ssqd:%4x", schid.sch_no);
+ return qdio_setup_get_ssqd(NULL, &schid, data);
}
EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc);
@@ -1141,7 +1145,7 @@ static void qdio_shutdown_queues(struct ccw_device *cdev)
tasklet_kill(&q->tasklet);
for_each_output_queue(irq_ptr, q, i) {
- del_timer(&q->u.out.timer);
+ del_timer_sync(&q->u.out.timer);
tasklet_kill(&q->tasklet);
}
}
@@ -1154,14 +1158,15 @@ static void qdio_shutdown_queues(struct ccw_device *cdev)
int qdio_shutdown(struct ccw_device *cdev, int how)
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+ struct subchannel_id schid;
int rc;
- unsigned long flags;
if (!irq_ptr)
return -ENODEV;
WARN_ON_ONCE(irqs_disabled());
- DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_EVENT("qshutdown:%4x", schid.sch_no);
mutex_lock(&irq_ptr->setup_mutex);
/*
@@ -1184,7 +1189,7 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
qdio_shutdown_debug_entries(irq_ptr);
/* cleanup subchannel */
- spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ spin_lock_irq(get_ccwdev_lock(cdev));
if (how & QDIO_FLAG_CLEANUP_USING_CLEAR)
rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP);
@@ -1198,12 +1203,12 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
}
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
wait_event_interruptible_timeout(cdev->private->wait_q,
irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
irq_ptr->state == QDIO_IRQ_STATE_ERR,
10 * HZ);
- spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ spin_lock_irq(get_ccwdev_lock(cdev));
no_cleanup:
qdio_shutdown_thinint(irq_ptr);
@@ -1211,7 +1216,7 @@ no_cleanup:
/* restore interrupt handler */
if ((void *)cdev->handler == (void *)qdio_int_handler)
cdev->handler = irq_ptr->orig_handler;
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
mutex_unlock(&irq_ptr->setup_mutex);
@@ -1228,11 +1233,13 @@ EXPORT_SYMBOL_GPL(qdio_shutdown);
int qdio_free(struct ccw_device *cdev)
{
struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+ struct subchannel_id schid;
if (!irq_ptr)
return -ENODEV;
- DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_EVENT("qfree:%4x", schid.sch_no);
DBF_DEV_EVENT(DBF_ERR, irq_ptr, "dbf abandoned");
mutex_lock(&irq_ptr->setup_mutex);
@@ -1251,9 +1258,11 @@ EXPORT_SYMBOL_GPL(qdio_free);
*/
int qdio_allocate(struct qdio_initialize *init_data)
{
+ struct subchannel_id schid;
struct qdio_irq *irq_ptr;
- DBF_EVENT("qallocate:%4x", init_data->cdev->private->schid.sch_no);
+ ccw_device_get_schid(init_data->cdev, &schid);
+ DBF_EVENT("qallocate:%4x", schid.sch_no);
if ((init_data->no_input_qs && !init_data->input_handler) ||
(init_data->no_output_qs && !init_data->output_handler))
@@ -1331,20 +1340,18 @@ static void qdio_detect_hsicq(struct qdio_irq *irq_ptr)
*/
int qdio_establish(struct qdio_initialize *init_data)
{
- struct qdio_irq *irq_ptr;
struct ccw_device *cdev = init_data->cdev;
- unsigned long saveflags;
+ struct subchannel_id schid;
+ struct qdio_irq *irq_ptr;
int rc;
- DBF_EVENT("qestablish:%4x", cdev->private->schid.sch_no);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_EVENT("qestablish:%4x", schid.sch_no);
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr)
return -ENODEV;
- if (cdev->private->state != DEV_STATE_ONLINE)
- return -EINVAL;
-
mutex_lock(&irq_ptr->setup_mutex);
qdio_setup_irq(init_data);
@@ -1361,17 +1368,14 @@ int qdio_establish(struct qdio_initialize *init_data)
irq_ptr->ccw.count = irq_ptr->equeue.count;
irq_ptr->ccw.cda = (u32)((addr_t)irq_ptr->qdr);
- spin_lock_irqsave(get_ccwdev_lock(cdev), saveflags);
+ spin_lock_irq(get_ccwdev_lock(cdev));
ccw_device_set_options_mask(cdev, 0);
rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
if (rc) {
DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no);
DBF_ERROR("rc:%4x", rc);
- }
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags);
-
- if (rc) {
mutex_unlock(&irq_ptr->setup_mutex);
qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
return rc;
@@ -1407,19 +1411,17 @@ EXPORT_SYMBOL_GPL(qdio_establish);
*/
int qdio_activate(struct ccw_device *cdev)
{
+ struct subchannel_id schid;
struct qdio_irq *irq_ptr;
int rc;
- unsigned long saveflags;
- DBF_EVENT("qactivate:%4x", cdev->private->schid.sch_no);
+ ccw_device_get_schid(cdev, &schid);
+ DBF_EVENT("qactivate:%4x", schid.sch_no);
irq_ptr = cdev->private->qdio_data;
if (!irq_ptr)
return -ENODEV;
- if (cdev->private->state != DEV_STATE_ONLINE)
- return -EINVAL;
-
mutex_lock(&irq_ptr->setup_mutex);
if (irq_ptr->state == QDIO_IRQ_STATE_INACTIVE) {
rc = -EBUSY;
@@ -1431,19 +1433,17 @@ int qdio_activate(struct ccw_device *cdev)
irq_ptr->ccw.count = irq_ptr->aqueue.count;
irq_ptr->ccw.cda = 0;
- spin_lock_irqsave(get_ccwdev_lock(cdev), saveflags);
+ spin_lock_irq(get_ccwdev_lock(cdev));
ccw_device_set_options(cdev, CCWDEV_REPORT_ALL);
rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE,
0, DOIO_DENY_PREFETCH);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
if (rc) {
DBF_ERROR("%4x act IO ERR", irq_ptr->schid.sch_no);
DBF_ERROR("rc:%4x", rc);
- }
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags);
-
- if (rc)
goto out;
+ }
if (is_thinint_irq(irq_ptr))
tiqdio_add_input_queues(irq_ptr);
@@ -1585,10 +1585,11 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
/* in case of SIGA errors we must process the error immediately */
if (used >= q->u.out.scan_threshold || rc)
- tasklet_schedule(&q->tasklet);
+ qdio_tasklet_schedule(q);
else
/* free the SBALs in case of no further traffic */
- if (!timer_pending(&q->u.out.timer))
+ if (!timer_pending(&q->u.out.timer) &&
+ likely(q->irq_ptr->state == QDIO_IRQ_STATE_ACTIVE))
mod_timer(&q->u.out.timer, jiffies + HZ);
return rc;
}
diff --git a/drivers/s390/virtio/Makefile b/drivers/s390/virtio/Makefile
index 241891a57caf..df40692a9011 100644
--- a/drivers/s390/virtio/Makefile
+++ b/drivers/s390/virtio/Makefile
@@ -6,4 +6,8 @@
# it under the terms of the GNU General Public License (version 2 only)
# as published by the Free Software Foundation.
-obj-$(CONFIG_S390_GUEST) += kvm_virtio.o virtio_ccw.o
+s390-virtio-objs := virtio_ccw.o
+ifdef CONFIG_S390_GUEST_OLD_TRANSPORT
+s390-virtio-objs += kvm_virtio.o
+endif
+obj-$(CONFIG_S390_GUEST) += $(s390-virtio-objs)
diff --git a/drivers/s390/virtio/kvm_virtio.c b/drivers/s390/virtio/kvm_virtio.c
index 1d060fd293a3..5e5c11f37b24 100644
--- a/drivers/s390/virtio/kvm_virtio.c
+++ b/drivers/s390/virtio/kvm_virtio.c
@@ -458,6 +458,8 @@ static int __init kvm_devices_init(void)
if (test_devices_support(total_memory_size) < 0)
return -ENODEV;
+ pr_warn("The s390-virtio transport is deprecated. Please switch to a modern host providing virtio-ccw.\n");
+
rc = vmem_add_mapping(total_memory_size, PAGE_SIZE);
if (rc)
return rc;
@@ -482,7 +484,7 @@ static int __init kvm_devices_init(void)
}
/* code for early console output with virtio_console */
-static __init int early_put_chars(u32 vtermno, const char *buf, int count)
+static int early_put_chars(u32 vtermno, const char *buf, int count)
{
char scratch[17];
unsigned int len = count;
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 1918f5483b23..7d1b4317eccc 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -838,6 +838,23 @@ config SCSI_IBMVSCSI
To compile this driver as a module, choose M here: the
module will be called ibmvscsi.
+config SCSI_IBMVSCSIS
+ tristate "IBM Virtual SCSI Server support"
+ depends on PPC_PSERIES && TARGET_CORE && SCSI && PCI
+ help
+ This is the IBM POWER Virtual SCSI Target Server
+ This driver uses the SRP protocol for communication betwen servers
+ guest and/or the host that run on the same server.
+ More information on VSCSI protocol can be found at www.power.org
+
+ The userspace configuration needed to initialize the driver can be
+ be found here:
+
+ https://github.com/powervm/ibmvscsis/wiki/Configuration
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmvscsis.
+
config SCSI_IBMVFC
tristate "IBM Virtual FC support"
depends on PPC_PSERIES && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 862ab4efad61..d5397987e731 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -128,6 +128,7 @@ obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
obj-$(CONFIG_SCSI_IPR) += ipr.o
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/
+obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi_tgt/
obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/
obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 860008d42466..661bb94e2548 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -778,7 +778,7 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
{
struct afu *afu = cfg->afu;
struct device *dev = &cfg->dev->dev;
- struct sisl_global_map __iomem *global = &afu->afu_map->global;
+ struct sisl_global_map __iomem *global;
struct dev_dependent_vals *ddv;
u64 reg, status;
int i, retry_cnt = 0;
@@ -787,6 +787,14 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait)
if (!(ddv->flags & CXLFLASH_NOTIFY_SHUTDOWN))
return;
+ if (!afu || !afu->afu_map) {
+ dev_dbg(dev, "%s: The problem state area is not mapped\n",
+ __func__);
+ return;
+ }
+
+ global = &afu->afu_map->global;
+
/* Notify AFU */
for (i = 0; i < NUM_FC_PORTS; i++) {
reg = readq_be(&global->fc_regs[i][FC_CONFIG2 / 8]);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index c8a4305c7662..9bd41a35a78a 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -92,6 +92,8 @@ static struct fcoe_interface
static int fcoe_fip_recv(struct sk_buff *, struct net_device *,
struct packet_type *, struct net_device *);
+static int fcoe_fip_vlan_recv(struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *);
static void fcoe_fip_send(struct fcoe_ctlr *, struct sk_buff *);
static void fcoe_update_src_mac(struct fc_lport *, u8 *);
@@ -363,6 +365,12 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
fcoe->fip_packet_type.dev = netdev;
dev_add_pack(&fcoe->fip_packet_type);
+ if (netdev != real_dev) {
+ fcoe->fip_vlan_packet_type.func = fcoe_fip_vlan_recv;
+ fcoe->fip_vlan_packet_type.type = htons(ETH_P_FIP);
+ fcoe->fip_vlan_packet_type.dev = real_dev;
+ dev_add_pack(&fcoe->fip_vlan_packet_type);
+ }
return 0;
}
@@ -450,6 +458,8 @@ static void fcoe_interface_remove(struct fcoe_interface *fcoe)
*/
__dev_remove_pack(&fcoe->fcoe_packet_type);
__dev_remove_pack(&fcoe->fip_packet_type);
+ if (netdev != fcoe->realdev)
+ __dev_remove_pack(&fcoe->fip_vlan_packet_type);
synchronize_net();
/* Delete secondary MAC addresses */
@@ -520,6 +530,29 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev,
}
/**
+ * fcoe_fip_vlan_recv() - Handler for received FIP VLAN discovery frames
+ * @skb: The receive skb
+ * @netdev: The associated net device
+ * @ptype: The packet_type structure which was used to register this handler
+ * @orig_dev: The original net_device the the skb was received on.
+ * (in case dev is a bond)
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_fip_vlan_recv(struct sk_buff *skb, struct net_device *netdev,
+ struct packet_type *ptype,
+ struct net_device *orig_dev)
+{
+ struct fcoe_interface *fcoe;
+ struct fcoe_ctlr *ctlr;
+
+ fcoe = container_of(ptype, struct fcoe_interface, fip_vlan_packet_type);
+ ctlr = fcoe_to_ctlr(fcoe);
+ fcoe_ctlr_recv(ctlr, skb);
+ return 0;
+}
+
+/**
* fcoe_port_send() - Send an Ethernet-encapsulated FIP/FCoE frame
* @port: The FCoE port
* @skb: The FIP/FCoE packet to be sent
@@ -539,7 +572,21 @@ static void fcoe_port_send(struct fcoe_port *port, struct sk_buff *skb)
*/
static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- skb->dev = fcoe_from_ctlr(fip)->netdev;
+ struct fcoe_interface *fcoe = fcoe_from_ctlr(fip);
+ struct fip_frame {
+ struct ethhdr eth;
+ struct fip_header fip;
+ } __packed *frame;
+
+ /*
+ * Use default VLAN for FIP VLAN discovery protocol
+ */
+ frame = (struct fip_frame *)skb->data;
+ if (frame->fip.fip_op == ntohs(FIP_OP_VLAN) &&
+ fcoe->realdev != fcoe->netdev)
+ skb->dev = fcoe->realdev;
+ else
+ skb->dev = fcoe->netdev;
fcoe_port_send(lport_priv(fip->lp), skb);
}
@@ -2448,7 +2495,7 @@ static int __init fcoe_init(void)
if (rc) {
printk(KERN_ERR "failed to register an fcoe transport, check "
"if libfcoe is loaded\n");
- return rc;
+ goto out_destroy;
}
mutex_lock(&fcoe_config_mutex);
@@ -2471,6 +2518,7 @@ static int __init fcoe_init(void)
out_free:
mutex_unlock(&fcoe_config_mutex);
+out_destroy:
destroy_workqueue(fcoe_wq);
return rc;
}
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index 2b53672bf932..6aa4820f6cc0 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -80,6 +80,7 @@ struct fcoe_interface {
struct net_device *realdev;
struct packet_type fcoe_packet_type;
struct packet_type fip_packet_type;
+ struct packet_type fip_vlan_packet_type;
struct fc_exch_mgr *oem;
u8 removed;
u8 priority;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 8fae03215a85..5c70a52ad346 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -26,7 +26,7 @@
#include <linux/list.h>
#include <linux/types.h>
-#include "viosrp.h"
+#include <scsi/viosrp.h>
#define IBMVFC_NAME "ibmvfc"
#define IBMVFC_DRIVER_VERSION "1.0.11"
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
index 1067367395cd..e0f6c3aeb4ee 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.h
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h
@@ -33,7 +33,7 @@
#include <linux/list.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
-#include "viosrp.h"
+#include <scsi/viosrp.h>
struct scsi_cmnd;
struct Scsi_Host;
diff --git a/drivers/scsi/ibmvscsi_tgt/Makefile b/drivers/scsi/ibmvscsi_tgt/Makefile
new file mode 100644
index 000000000000..0c060ce64cb0
--- /dev/null
+++ b/drivers/scsi/ibmvscsi_tgt/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsis.o
+
+ibmvscsis-y := libsrp.o ibmvscsi_tgt.o
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
new file mode 100644
index 000000000000..b29fef9d0f27
--- /dev/null
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -0,0 +1,4087 @@
+/*******************************************************************************
+ * IBM Virtual SCSI Target Driver
+ * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp.
+ * Santiago Leon (santil@us.ibm.com) IBM Corp.
+ * Linda Xie (lxie@us.ibm.com) IBM Corp.
+ *
+ * Copyright (C) 2005-2011 FUJITA Tomonori <tomof@acm.org>
+ * Copyright (C) 2010 Nicholas A. Bellinger <nab@kernel.org>
+ *
+ * Authors: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+ * Authors: Michael Cyr <mikecyr@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ ****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/string.h>
+
+#include <target/target_core_base.h>
+#include <target/target_core_fabric.h>
+
+#include <asm/hvcall.h>
+#include <asm/vio.h>
+
+#include <scsi/viosrp.h>
+
+#include "ibmvscsi_tgt.h"
+
+#define IBMVSCSIS_VERSION "v0.2"
+
+#define INITIAL_SRP_LIMIT 800
+#define DEFAULT_MAX_SECTORS 256
+
+static uint max_vdma_size = MAX_H_COPY_RDMA;
+
+static char system_id[SYS_ID_NAME_LEN] = "";
+static char partition_name[PARTITION_NAMELEN] = "UNKNOWN";
+static uint partition_number = -1;
+
+/* Adapter list and lock to control it */
+static DEFINE_SPINLOCK(ibmvscsis_dev_lock);
+static LIST_HEAD(ibmvscsis_dev_list);
+
+static long ibmvscsis_parse_command(struct scsi_info *vscsi,
+ struct viosrp_crq *crq);
+
+static void ibmvscsis_adapter_idle(struct scsi_info *vscsi);
+
+static void ibmvscsis_determine_resid(struct se_cmd *se_cmd,
+ struct srp_rsp *rsp)
+{
+ u32 residual_count = se_cmd->residual_count;
+
+ if (!residual_count)
+ return;
+
+ if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
+ if (se_cmd->data_direction == DMA_TO_DEVICE) {
+ /* residual data from an underflow write */
+ rsp->flags = SRP_RSP_FLAG_DOUNDER;
+ rsp->data_out_res_cnt = cpu_to_be32(residual_count);
+ } else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
+ /* residual data from an underflow read */
+ rsp->flags = SRP_RSP_FLAG_DIUNDER;
+ rsp->data_in_res_cnt = cpu_to_be32(residual_count);
+ }
+ } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+ if (se_cmd->data_direction == DMA_TO_DEVICE) {
+ /* residual data from an overflow write */
+ rsp->flags = SRP_RSP_FLAG_DOOVER;
+ rsp->data_out_res_cnt = cpu_to_be32(residual_count);
+ } else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
+ /* residual data from an overflow read */
+ rsp->flags = SRP_RSP_FLAG_DIOVER;
+ rsp->data_in_res_cnt = cpu_to_be32(residual_count);
+ }
+ }
+}
+
+/**
+ * connection_broken() - Determine if the connection to the client is good
+ * @vscsi: Pointer to our adapter structure
+ *
+ * This function attempts to send a ping MAD to the client. If the call to
+ * queue the request returns H_CLOSED then the connection has been broken
+ * and the function returns TRUE.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt or Process environment
+ */
+static bool connection_broken(struct scsi_info *vscsi)
+{
+ struct viosrp_crq *crq;
+ u64 buffer[2] = { 0, 0 };
+ long h_return_code;
+ bool rc = false;
+
+ /* create a PING crq */
+ crq = (struct viosrp_crq *)&buffer;
+ crq->valid = VALID_CMD_RESP_EL;
+ crq->format = MESSAGE_IN_CRQ;
+ crq->status = PING;
+
+ h_return_code = h_send_crq(vscsi->dds.unit_id,
+ cpu_to_be64(buffer[MSG_HI]),
+ cpu_to_be64(buffer[MSG_LOW]));
+
+ pr_debug("connection_broken: rc %ld\n", h_return_code);
+
+ if (h_return_code == H_CLOSED)
+ rc = true;
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_unregister_command_q() - Helper Function-Unregister Command Queue
+ * @vscsi: Pointer to our adapter structure
+ *
+ * This function calls h_free_q then frees the interrupt bit etc.
+ * It must release the lock before doing so because of the time it can take
+ * for h_free_crq in PHYP
+ * NOTE: the caller must make sure that state and or flags will prevent
+ * interrupt handler from scheduling work.
+ * NOTE: anyone calling this function may need to set the CRQ_CLOSED flag
+ * we can't do it here, because we don't have the lock
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level
+ */
+static long ibmvscsis_unregister_command_q(struct scsi_info *vscsi)
+{
+ long qrc;
+ long rc = ADAPT_SUCCESS;
+ int ticks = 0;
+
+ do {
+ qrc = h_free_crq(vscsi->dds.unit_id);
+ switch (qrc) {
+ case H_SUCCESS:
+ break;
+
+ case H_HARDWARE:
+ case H_PARAMETER:
+ dev_err(&vscsi->dev, "unregister_command_q: error from h_free_crq %ld\n",
+ qrc);
+ rc = ERROR;
+ break;
+
+ case H_BUSY:
+ case H_LONG_BUSY_ORDER_1_MSEC:
+ /* msleep not good for small values */
+ usleep_range(1000, 2000);
+ ticks += 1;
+ break;
+ case H_LONG_BUSY_ORDER_10_MSEC:
+ usleep_range(10000, 20000);
+ ticks += 10;
+ break;
+ case H_LONG_BUSY_ORDER_100_MSEC:
+ msleep(100);
+ ticks += 100;
+ break;
+ case H_LONG_BUSY_ORDER_1_SEC:
+ ssleep(1);
+ ticks += 1000;
+ break;
+ case H_LONG_BUSY_ORDER_10_SEC:
+ ssleep(10);
+ ticks += 10000;
+ break;
+ case H_LONG_BUSY_ORDER_100_SEC:
+ ssleep(100);
+ ticks += 100000;
+ break;
+ default:
+ dev_err(&vscsi->dev, "unregister_command_q: unknown error %ld from h_free_crq\n",
+ qrc);
+ rc = ERROR;
+ break;
+ }
+
+ /*
+ * dont wait more then 300 seconds
+ * ticks are in milliseconds more or less
+ */
+ if (ticks > 300000 && qrc != H_SUCCESS) {
+ rc = ERROR;
+ dev_err(&vscsi->dev, "Excessive wait for h_free_crq\n");
+ }
+ } while (qrc != H_SUCCESS && rc == ADAPT_SUCCESS);
+
+ pr_debug("Freeing CRQ: phyp rc %ld, rc %ld\n", qrc, rc);
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_delete_client_info() - Helper function to Delete Client Info
+ * @vscsi: Pointer to our adapter structure
+ * @client_closed: True if client closed its queue
+ *
+ * Deletes information specific to the client when the client goes away
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt or Process
+ */
+static void ibmvscsis_delete_client_info(struct scsi_info *vscsi,
+ bool client_closed)
+{
+ vscsi->client_cap = 0;
+
+ /*
+ * Some things we don't want to clear if we're closing the queue,
+ * because some clients don't resend the host handshake when they
+ * get a transport event.
+ */
+ if (client_closed)
+ vscsi->client_data.os_type = 0;
+}
+
+/**
+ * ibmvscsis_free_command_q() - Free Command Queue
+ * @vscsi: Pointer to our adapter structure
+ *
+ * This function calls unregister_command_q, then clears interrupts and
+ * any pending interrupt acknowledgments associated with the command q.
+ * It also clears memory if there is no error.
+ *
+ * PHYP did not meet the PAPR architecture so that we must give up the
+ * lock. This causes a timing hole regarding state change. To close the
+ * hole this routine does accounting on any change that occurred during
+ * the time the lock is not held.
+ * NOTE: must give up and then acquire the interrupt lock, the caller must
+ * make sure that state and or flags will prevent interrupt handler from
+ * scheduling work.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level, interrupt lock is held
+ */
+static long ibmvscsis_free_command_q(struct scsi_info *vscsi)
+{
+ int bytes;
+ u32 flags_under_lock;
+ u16 state_under_lock;
+ long rc = ADAPT_SUCCESS;
+
+ if (!(vscsi->flags & CRQ_CLOSED)) {
+ vio_disable_interrupts(vscsi->dma_dev);
+
+ state_under_lock = vscsi->new_state;
+ flags_under_lock = vscsi->flags;
+ vscsi->phyp_acr_state = 0;
+ vscsi->phyp_acr_flags = 0;
+
+ spin_unlock_bh(&vscsi->intr_lock);
+ rc = ibmvscsis_unregister_command_q(vscsi);
+ spin_lock_bh(&vscsi->intr_lock);
+
+ if (state_under_lock != vscsi->new_state)
+ vscsi->phyp_acr_state = vscsi->new_state;
+
+ vscsi->phyp_acr_flags = ((~flags_under_lock) & vscsi->flags);
+
+ if (rc == ADAPT_SUCCESS) {
+ bytes = vscsi->cmd_q.size * PAGE_SIZE;
+ memset(vscsi->cmd_q.base_addr, 0, bytes);
+ vscsi->cmd_q.index = 0;
+ vscsi->flags |= CRQ_CLOSED;
+
+ ibmvscsis_delete_client_info(vscsi, false);
+ }
+
+ pr_debug("free_command_q: flags 0x%x, state 0x%hx, acr_flags 0x%x, acr_state 0x%hx\n",
+ vscsi->flags, vscsi->state, vscsi->phyp_acr_flags,
+ vscsi->phyp_acr_state);
+ }
+ return rc;
+}
+
+/**
+ * ibmvscsis_cmd_q_dequeue() - Get valid Command element
+ * @mask: Mask to use in case index wraps
+ * @current_index: Current index into command queue
+ * @base_addr: Pointer to start of command queue
+ *
+ * Returns a pointer to a valid command element or NULL, if the command
+ * queue is empty
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt environment, interrupt lock held
+ */
+static struct viosrp_crq *ibmvscsis_cmd_q_dequeue(uint mask,
+ uint *current_index,
+ struct viosrp_crq *base_addr)
+{
+ struct viosrp_crq *ptr;
+
+ ptr = base_addr + *current_index;
+
+ if (ptr->valid) {
+ *current_index = (*current_index + 1) & mask;
+ dma_rmb();
+ } else {
+ ptr = NULL;
+ }
+
+ return ptr;
+}
+
+/**
+ * ibmvscsis_send_init_message() - send initialize message to the client
+ * @vscsi: Pointer to our adapter structure
+ * @format: Which Init Message format to send
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt environment interrupt lock held
+ */
+static long ibmvscsis_send_init_message(struct scsi_info *vscsi, u8 format)
+{
+ struct viosrp_crq *crq;
+ u64 buffer[2] = { 0, 0 };
+ long rc;
+
+ crq = (struct viosrp_crq *)&buffer;
+ crq->valid = VALID_INIT_MSG;
+ crq->format = format;
+ rc = h_send_crq(vscsi->dds.unit_id, cpu_to_be64(buffer[MSG_HI]),
+ cpu_to_be64(buffer[MSG_LOW]));
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_check_init_msg() - Check init message valid
+ * @vscsi: Pointer to our adapter structure
+ * @format: Pointer to return format of Init Message, if any.
+ * Set to UNUSED_FORMAT if no Init Message in queue.
+ *
+ * Checks if an initialize message was queued by the initiatior
+ * after the queue was created and before the interrupt was enabled.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level only, interrupt lock held
+ */
+static long ibmvscsis_check_init_msg(struct scsi_info *vscsi, uint *format)
+{
+ struct viosrp_crq *crq;
+ long rc = ADAPT_SUCCESS;
+
+ crq = ibmvscsis_cmd_q_dequeue(vscsi->cmd_q.mask, &vscsi->cmd_q.index,
+ vscsi->cmd_q.base_addr);
+ if (!crq) {
+ *format = (uint)UNUSED_FORMAT;
+ } else if (crq->valid == VALID_INIT_MSG && crq->format == INIT_MSG) {
+ *format = (uint)INIT_MSG;
+ crq->valid = INVALIDATE_CMD_RESP_EL;
+ dma_rmb();
+
+ /*
+ * the caller has ensured no initialize message was
+ * sent after the queue was
+ * created so there should be no other message on the queue.
+ */
+ crq = ibmvscsis_cmd_q_dequeue(vscsi->cmd_q.mask,
+ &vscsi->cmd_q.index,
+ vscsi->cmd_q.base_addr);
+ if (crq) {
+ *format = (uint)(crq->format);
+ rc = ERROR;
+ crq->valid = INVALIDATE_CMD_RESP_EL;
+ dma_rmb();
+ }
+ } else {
+ *format = (uint)(crq->format);
+ rc = ERROR;
+ crq->valid = INVALIDATE_CMD_RESP_EL;
+ dma_rmb();
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_establish_new_q() - Establish new CRQ queue
+ * @vscsi: Pointer to our adapter structure
+ * @new_state: New state being established after resetting the queue
+ *
+ * Must be called with interrupt lock held.
+ */
+static long ibmvscsis_establish_new_q(struct scsi_info *vscsi, uint new_state)
+{
+ long rc = ADAPT_SUCCESS;
+ uint format;
+
+ vscsi->flags &= PRESERVE_FLAG_FIELDS;
+ vscsi->rsp_q_timer.timer_pops = 0;
+ vscsi->debit = 0;
+ vscsi->credit = 0;
+
+ rc = vio_enable_interrupts(vscsi->dma_dev);
+ if (rc) {
+ pr_warn("reset_queue: failed to enable interrupts, rc %ld\n",
+ rc);
+ return rc;
+ }
+
+ rc = ibmvscsis_check_init_msg(vscsi, &format);
+ if (rc) {
+ dev_err(&vscsi->dev, "reset_queue: check_init_msg failed, rc %ld\n",
+ rc);
+ return rc;
+ }
+
+ if (format == UNUSED_FORMAT && new_state == WAIT_CONNECTION) {
+ rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
+ switch (rc) {
+ case H_SUCCESS:
+ case H_DROPPED:
+ case H_CLOSED:
+ rc = ADAPT_SUCCESS;
+ break;
+
+ case H_PARAMETER:
+ case H_HARDWARE:
+ break;
+
+ default:
+ vscsi->state = UNDEFINED;
+ rc = H_HARDWARE;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_reset_queue() - Reset CRQ Queue
+ * @vscsi: Pointer to our adapter structure
+ * @new_state: New state to establish after resetting the queue
+ *
+ * This function calls h_free_q and then calls h_reg_q and does all
+ * of the bookkeeping to get us back to where we can communicate.
+ *
+ * Actually, we don't always call h_free_crq. A problem was discovered
+ * where one partition would close and reopen his queue, which would
+ * cause his partner to get a transport event, which would cause him to
+ * close and reopen his queue, which would cause the original partition
+ * to get a transport event, etc., etc. To prevent this, we don't
+ * actually close our queue if the client initiated the reset, (i.e.
+ * either we got a transport event or we have detected that the client's
+ * queue is gone)
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process environment, called with interrupt lock held
+ */
+static void ibmvscsis_reset_queue(struct scsi_info *vscsi, uint new_state)
+{
+ int bytes;
+ long rc = ADAPT_SUCCESS;
+
+ pr_debug("reset_queue: flags 0x%x\n", vscsi->flags);
+
+ /* don't reset, the client did it for us */
+ if (vscsi->flags & (CLIENT_FAILED | TRANS_EVENT)) {
+ vscsi->flags &= PRESERVE_FLAG_FIELDS;
+ vscsi->rsp_q_timer.timer_pops = 0;
+ vscsi->debit = 0;
+ vscsi->credit = 0;
+ vscsi->state = new_state;
+ vio_enable_interrupts(vscsi->dma_dev);
+ } else {
+ rc = ibmvscsis_free_command_q(vscsi);
+ if (rc == ADAPT_SUCCESS) {
+ vscsi->state = new_state;
+
+ bytes = vscsi->cmd_q.size * PAGE_SIZE;
+ rc = h_reg_crq(vscsi->dds.unit_id,
+ vscsi->cmd_q.crq_token, bytes);
+ if (rc == H_CLOSED || rc == H_SUCCESS) {
+ rc = ibmvscsis_establish_new_q(vscsi,
+ new_state);
+ }
+
+ if (rc != ADAPT_SUCCESS) {
+ pr_debug("reset_queue: reg_crq rc %ld\n", rc);
+
+ vscsi->state = ERR_DISCONNECTED;
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ ibmvscsis_free_command_q(vscsi);
+ }
+ } else {
+ vscsi->state = ERR_DISCONNECTED;
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ }
+ }
+}
+
+/**
+ * ibmvscsis_free_cmd_resources() - Free command resources
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Command which is not longer in use
+ *
+ * Must be called with interrupt lock held.
+ */
+static void ibmvscsis_free_cmd_resources(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd)
+{
+ struct iu_entry *iue = cmd->iue;
+
+ switch (cmd->type) {
+ case TASK_MANAGEMENT:
+ case SCSI_CDB:
+ /*
+ * When the queue goes down this value is cleared, so it
+ * cannot be cleared in this general purpose function.
+ */
+ if (vscsi->debit)
+ vscsi->debit -= 1;
+ break;
+ case ADAPTER_MAD:
+ vscsi->flags &= ~PROCESSING_MAD;
+ break;
+ case UNSET_TYPE:
+ break;
+ default:
+ dev_err(&vscsi->dev, "free_cmd_resources unknown type %d\n",
+ cmd->type);
+ break;
+ }
+
+ cmd->iue = NULL;
+ list_add_tail(&cmd->list, &vscsi->free_cmd);
+ srp_iu_put(iue);
+
+ if (list_empty(&vscsi->active_q) && list_empty(&vscsi->schedule_q) &&
+ list_empty(&vscsi->waiting_rsp) && (vscsi->flags & WAIT_FOR_IDLE)) {
+ vscsi->flags &= ~WAIT_FOR_IDLE;
+ complete(&vscsi->wait_idle);
+ }
+}
+
+/**
+ * ibmvscsis_disconnect() - Helper function to disconnect
+ * @work: Pointer to work_struct, gives access to our adapter structure
+ *
+ * An error has occurred or the driver received a Transport event,
+ * and the driver is requesting that the command queue be de-registered
+ * in a safe manner. If there is no outstanding I/O then we can stop the
+ * queue. If we are restarting the queue it will be reflected in the
+ * the state of the adapter.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process environment
+ */
+static void ibmvscsis_disconnect(struct work_struct *work)
+{
+ struct scsi_info *vscsi = container_of(work, struct scsi_info,
+ proc_work);
+ u16 new_state;
+ bool wait_idle = false;
+ long rc = ADAPT_SUCCESS;
+
+ spin_lock_bh(&vscsi->intr_lock);
+ new_state = vscsi->new_state;
+ vscsi->new_state = 0;
+
+ pr_debug("disconnect: flags 0x%x, state 0x%hx\n", vscsi->flags,
+ vscsi->state);
+
+ /*
+ * check which state we are in and see if we
+ * should transitition to the new state
+ */
+ switch (vscsi->state) {
+ /* Should never be called while in this state. */
+ case NO_QUEUE:
+ /*
+ * Can never transition from this state;
+ * igonore errors and logout.
+ */
+ case UNCONFIGURING:
+ break;
+
+ /* can transition from this state to UNCONFIGURING */
+ case ERR_DISCONNECT:
+ if (new_state == UNCONFIGURING)
+ vscsi->state = new_state;
+ break;
+
+ /*
+ * Can transition from this state to to unconfiguring
+ * or err disconnect.
+ */
+ case ERR_DISCONNECT_RECONNECT:
+ switch (new_state) {
+ case UNCONFIGURING:
+ case ERR_DISCONNECT:
+ vscsi->state = new_state;
+ break;
+
+ case WAIT_IDLE:
+ break;
+ default:
+ break;
+ }
+ break;
+
+ /* can transition from this state to UNCONFIGURING */
+ case ERR_DISCONNECTED:
+ if (new_state == UNCONFIGURING)
+ vscsi->state = new_state;
+ break;
+
+ /*
+ * If this is a transition into an error state.
+ * a client is attempting to establish a connection
+ * and has violated the RPA protocol.
+ * There can be nothing pending on the adapter although
+ * there can be requests in the command queue.
+ */
+ case WAIT_ENABLED:
+ case PART_UP_WAIT_ENAB:
+ switch (new_state) {
+ case ERR_DISCONNECT:
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ vscsi->state = new_state;
+ vscsi->flags &= ~(SCHEDULE_DISCONNECT |
+ DISCONNECT_SCHEDULED);
+ ibmvscsis_free_command_q(vscsi);
+ break;
+ case ERR_DISCONNECT_RECONNECT:
+ ibmvscsis_reset_queue(vscsi, WAIT_ENABLED);
+ break;
+
+ /* should never happen */
+ case WAIT_IDLE:
+ rc = ERROR;
+ dev_err(&vscsi->dev, "disconnect: invalid state %d for WAIT_IDLE\n",
+ vscsi->state);
+ break;
+ }
+ break;
+
+ case WAIT_IDLE:
+ switch (new_state) {
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ vscsi->state = new_state;
+ break;
+ }
+ break;
+
+ /*
+ * Initiator has not done a successful srp login
+ * or has done a successful srp logout ( adapter was not
+ * busy). In the first case there can be responses queued
+ * waiting for space on the initiators response queue (MAD)
+ * The second case the adapter is idle. Assume the worse case,
+ * i.e. the second case.
+ */
+ case WAIT_CONNECTION:
+ case CONNECTED:
+ case SRP_PROCESSING:
+ wait_idle = true;
+ vscsi->state = new_state;
+ break;
+
+ /* can transition from this state to UNCONFIGURING */
+ case UNDEFINED:
+ if (new_state == UNCONFIGURING)
+ vscsi->state = new_state;
+ break;
+ default:
+ break;
+ }
+
+ if (wait_idle) {
+ pr_debug("disconnect start wait, active %d, sched %d\n",
+ (int)list_empty(&vscsi->active_q),
+ (int)list_empty(&vscsi->schedule_q));
+ if (!list_empty(&vscsi->active_q) ||
+ !list_empty(&vscsi->schedule_q)) {
+ vscsi->flags |= WAIT_FOR_IDLE;
+ pr_debug("disconnect flags 0x%x\n", vscsi->flags);
+ /*
+ * This routine is can not be called with the interrupt
+ * lock held.
+ */
+ spin_unlock_bh(&vscsi->intr_lock);
+ wait_for_completion(&vscsi->wait_idle);
+ spin_lock_bh(&vscsi->intr_lock);
+ }
+ pr_debug("disconnect stop wait\n");
+
+ ibmvscsis_adapter_idle(vscsi);
+ }
+
+ spin_unlock_bh(&vscsi->intr_lock);
+}
+
+/**
+ * ibmvscsis_post_disconnect() - Schedule the disconnect
+ * @vscsi: Pointer to our adapter structure
+ * @new_state: State to move to after disconnecting
+ * @flag_bits: Flags to turn on in adapter structure
+ *
+ * If it's already been scheduled, then see if we need to "upgrade"
+ * the new state (if the one passed in is more "severe" than the
+ * previous one).
+ *
+ * PRECONDITION:
+ * interrupt lock is held
+ */
+static void ibmvscsis_post_disconnect(struct scsi_info *vscsi, uint new_state,
+ uint flag_bits)
+{
+ uint state;
+
+ /* check the validity of the new state */
+ switch (new_state) {
+ case UNCONFIGURING:
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ case WAIT_IDLE:
+ break;
+
+ default:
+ dev_err(&vscsi->dev, "post_disconnect: Invalid new state %d\n",
+ new_state);
+ return;
+ }
+
+ vscsi->flags |= flag_bits;
+
+ pr_debug("post_disconnect: new_state 0x%x, flag_bits 0x%x, vscsi->flags 0x%x, state %hx\n",
+ new_state, flag_bits, vscsi->flags, vscsi->state);
+
+ if (!(vscsi->flags & (DISCONNECT_SCHEDULED | SCHEDULE_DISCONNECT))) {
+ vscsi->flags |= SCHEDULE_DISCONNECT;
+ vscsi->new_state = new_state;
+
+ INIT_WORK(&vscsi->proc_work, ibmvscsis_disconnect);
+ (void)queue_work(vscsi->work_q, &vscsi->proc_work);
+ } else {
+ if (vscsi->new_state)
+ state = vscsi->new_state;
+ else
+ state = vscsi->state;
+
+ switch (state) {
+ case NO_QUEUE:
+ case UNCONFIGURING:
+ break;
+
+ case ERR_DISCONNECTED:
+ case ERR_DISCONNECT:
+ case UNDEFINED:
+ if (new_state == UNCONFIGURING)
+ vscsi->new_state = new_state;
+ break;
+
+ case ERR_DISCONNECT_RECONNECT:
+ switch (new_state) {
+ case UNCONFIGURING:
+ case ERR_DISCONNECT:
+ vscsi->new_state = new_state;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case WAIT_ENABLED:
+ case PART_UP_WAIT_ENAB:
+ case WAIT_IDLE:
+ case WAIT_CONNECTION:
+ case CONNECTED:
+ case SRP_PROCESSING:
+ vscsi->new_state = new_state;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pr_debug("Leaving post_disconnect: flags 0x%x, new_state 0x%x\n",
+ vscsi->flags, vscsi->new_state);
+}
+
+/**
+ * ibmvscsis_trans_event() - Handle a Transport Event
+ * @vscsi: Pointer to our adapter structure
+ * @crq: Pointer to CRQ entry containing the Transport Event
+ *
+ * Do the logic to close the I_T nexus. This function may not
+ * behave to specification.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_trans_event(struct scsi_info *vscsi,
+ struct viosrp_crq *crq)
+{
+ long rc = ADAPT_SUCCESS;
+
+ pr_debug("trans_event: format %d, flags 0x%x, state 0x%hx\n",
+ (int)crq->format, vscsi->flags, vscsi->state);
+
+ switch (crq->format) {
+ case MIGRATED:
+ case PARTNER_FAILED:
+ case PARTNER_DEREGISTER:
+ ibmvscsis_delete_client_info(vscsi, true);
+ break;
+
+ default:
+ rc = ERROR;
+ dev_err(&vscsi->dev, "trans_event: invalid format %d\n",
+ (uint)crq->format);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT,
+ RESPONSE_Q_DOWN);
+ break;
+ }
+
+ if (rc == ADAPT_SUCCESS) {
+ switch (vscsi->state) {
+ case NO_QUEUE:
+ case ERR_DISCONNECTED:
+ case UNDEFINED:
+ break;
+
+ case UNCONFIGURING:
+ vscsi->flags |= (RESPONSE_Q_DOWN | TRANS_EVENT);
+ break;
+
+ case WAIT_ENABLED:
+ break;
+
+ case WAIT_CONNECTION:
+ break;
+
+ case CONNECTED:
+ ibmvscsis_post_disconnect(vscsi, WAIT_IDLE,
+ (RESPONSE_Q_DOWN |
+ TRANS_EVENT));
+ break;
+
+ case PART_UP_WAIT_ENAB:
+ vscsi->state = WAIT_ENABLED;
+ break;
+
+ case SRP_PROCESSING:
+ if ((vscsi->debit > 0) ||
+ !list_empty(&vscsi->schedule_q) ||
+ !list_empty(&vscsi->waiting_rsp) ||
+ !list_empty(&vscsi->active_q)) {
+ pr_debug("debit %d, sched %d, wait %d, active %d\n",
+ vscsi->debit,
+ (int)list_empty(&vscsi->schedule_q),
+ (int)list_empty(&vscsi->waiting_rsp),
+ (int)list_empty(&vscsi->active_q));
+ pr_warn("connection lost with outstanding work\n");
+ } else {
+ pr_debug("trans_event: SRP Processing, but no outstanding work\n");
+ }
+
+ ibmvscsis_post_disconnect(vscsi, WAIT_IDLE,
+ (RESPONSE_Q_DOWN |
+ TRANS_EVENT));
+ break;
+
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ case WAIT_IDLE:
+ vscsi->flags |= (RESPONSE_Q_DOWN | TRANS_EVENT);
+ break;
+ }
+ }
+
+ rc = vscsi->flags & SCHEDULE_DISCONNECT;
+
+ pr_debug("Leaving trans_event: flags 0x%x, state 0x%hx, rc %ld\n",
+ vscsi->flags, vscsi->state, rc);
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_poll_cmd_q() - Poll Command Queue
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Called to handle command elements that may have arrived while
+ * interrupts were disabled.
+ *
+ * EXECUTION ENVIRONMENT:
+ * intr_lock must be held
+ */
+static void ibmvscsis_poll_cmd_q(struct scsi_info *vscsi)
+{
+ struct viosrp_crq *crq;
+ long rc;
+ bool ack = true;
+ volatile u8 valid;
+
+ pr_debug("poll_cmd_q: flags 0x%x, state 0x%hx, q index %ud\n",
+ vscsi->flags, vscsi->state, vscsi->cmd_q.index);
+
+ rc = vscsi->flags & SCHEDULE_DISCONNECT;
+ crq = vscsi->cmd_q.base_addr + vscsi->cmd_q.index;
+ valid = crq->valid;
+ dma_rmb();
+
+ while (valid) {
+poll_work:
+ vscsi->cmd_q.index =
+ (vscsi->cmd_q.index + 1) & vscsi->cmd_q.mask;
+
+ if (!rc) {
+ rc = ibmvscsis_parse_command(vscsi, crq);
+ } else {
+ if ((uint)crq->valid == VALID_TRANS_EVENT) {
+ /*
+ * must service the transport layer events even
+ * in an error state, dont break out until all
+ * the consecutive transport events have been
+ * processed
+ */
+ rc = ibmvscsis_trans_event(vscsi, crq);
+ } else if (vscsi->flags & TRANS_EVENT) {
+ /*
+ * if a tranport event has occurred leave
+ * everything but transport events on the queue
+ */
+ pr_debug("poll_cmd_q, ignoring\n");
+
+ /*
+ * need to decrement the queue index so we can
+ * look at the elment again
+ */
+ if (vscsi->cmd_q.index)
+ vscsi->cmd_q.index -= 1;
+ else
+ /*
+ * index is at 0 it just wrapped.
+ * have it index last element in q
+ */
+ vscsi->cmd_q.index = vscsi->cmd_q.mask;
+ break;
+ }
+ }
+
+ crq->valid = INVALIDATE_CMD_RESP_EL;
+
+ crq = vscsi->cmd_q.base_addr + vscsi->cmd_q.index;
+ valid = crq->valid;
+ dma_rmb();
+ }
+
+ if (!rc) {
+ if (ack) {
+ vio_enable_interrupts(vscsi->dma_dev);
+ ack = false;
+ pr_debug("poll_cmd_q, reenabling interrupts\n");
+ }
+ valid = crq->valid;
+ dma_rmb();
+ if (valid)
+ goto poll_work;
+ }
+
+ pr_debug("Leaving poll_cmd_q: rc %ld\n", rc);
+}
+
+/**
+ * ibmvscsis_free_cmd_qs() - Free elements in queue
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Free all of the elements on all queues that are waiting for
+ * whatever reason.
+ *
+ * PRECONDITION:
+ * Called with interrupt lock held
+ */
+static void ibmvscsis_free_cmd_qs(struct scsi_info *vscsi)
+{
+ struct ibmvscsis_cmd *cmd, *nxt;
+
+ pr_debug("free_cmd_qs: waiting_rsp empty %d, timer starter %d\n",
+ (int)list_empty(&vscsi->waiting_rsp),
+ vscsi->rsp_q_timer.started);
+
+ list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) {
+ list_del(&cmd->list);
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ }
+}
+
+/**
+ * ibmvscsis_get_free_cmd() - Get free command from list
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Must be called with interrupt lock held.
+ */
+static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
+{
+ struct ibmvscsis_cmd *cmd = NULL;
+ struct iu_entry *iue;
+
+ iue = srp_iu_get(&vscsi->target);
+ if (iue) {
+ cmd = list_first_entry_or_null(&vscsi->free_cmd,
+ struct ibmvscsis_cmd, list);
+ if (cmd) {
+ list_del(&cmd->list);
+ cmd->iue = iue;
+ cmd->type = UNSET_TYPE;
+ memset(&cmd->se_cmd, 0, sizeof(cmd->se_cmd));
+ } else {
+ srp_iu_put(iue);
+ }
+ }
+
+ return cmd;
+}
+
+/**
+ * ibmvscsis_adapter_idle() - Helper function to handle idle adapter
+ * @vscsi: Pointer to our adapter structure
+ *
+ * This function is called when the adapter is idle when the driver
+ * is attempting to clear an error condition.
+ * The adapter is considered busy if any of its cmd queues
+ * are non-empty. This function can be invoked
+ * from the off level disconnect function.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process environment called with interrupt lock held
+ */
+static void ibmvscsis_adapter_idle(struct scsi_info *vscsi)
+{
+ int free_qs = false;
+
+ pr_debug("adapter_idle: flags 0x%x, state 0x%hx\n", vscsi->flags,
+ vscsi->state);
+
+ /* Only need to free qs if we're disconnecting from client */
+ if (vscsi->state != WAIT_CONNECTION || vscsi->flags & TRANS_EVENT)
+ free_qs = true;
+
+ switch (vscsi->state) {
+ case ERR_DISCONNECT_RECONNECT:
+ ibmvscsis_reset_queue(vscsi, WAIT_CONNECTION);
+ pr_debug("adapter_idle, disc_rec: flags 0x%x\n", vscsi->flags);
+ break;
+
+ case ERR_DISCONNECT:
+ ibmvscsis_free_command_q(vscsi);
+ vscsi->flags &= ~DISCONNECT_SCHEDULED;
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ vscsi->state = ERR_DISCONNECTED;
+ pr_debug("adapter_idle, disc: flags 0x%x, state 0x%hx\n",
+ vscsi->flags, vscsi->state);
+ break;
+
+ case WAIT_IDLE:
+ vscsi->rsp_q_timer.timer_pops = 0;
+ vscsi->debit = 0;
+ vscsi->credit = 0;
+ if (vscsi->flags & TRANS_EVENT) {
+ vscsi->state = WAIT_CONNECTION;
+ vscsi->flags &= PRESERVE_FLAG_FIELDS;
+ } else {
+ vscsi->state = CONNECTED;
+ vscsi->flags &= ~DISCONNECT_SCHEDULED;
+ }
+
+ pr_debug("adapter_idle, wait: flags 0x%x, state 0x%hx\n",
+ vscsi->flags, vscsi->state);
+ ibmvscsis_poll_cmd_q(vscsi);
+ break;
+
+ case ERR_DISCONNECTED:
+ vscsi->flags &= ~DISCONNECT_SCHEDULED;
+ pr_debug("adapter_idle, disconnected: flags 0x%x, state 0x%hx\n",
+ vscsi->flags, vscsi->state);
+ break;
+
+ default:
+ dev_err(&vscsi->dev, "adapter_idle: in invalid state %d\n",
+ vscsi->state);
+ break;
+ }
+
+ if (free_qs)
+ ibmvscsis_free_cmd_qs(vscsi);
+
+ /*
+ * There is a timing window where we could lose a disconnect request.
+ * The known path to this window occurs during the DISCONNECT_RECONNECT
+ * case above: reset_queue calls free_command_q, which will release the
+ * interrupt lock. During that time, a new post_disconnect call can be
+ * made with a "more severe" state (DISCONNECT or UNCONFIGURING).
+ * Because the DISCONNECT_SCHEDULED flag is already set, post_disconnect
+ * will only set the new_state. Now free_command_q reacquires the intr
+ * lock and clears the DISCONNECT_SCHEDULED flag (using PRESERVE_FLAG_
+ * FIELDS), and the disconnect is lost. This is particularly bad when
+ * the new disconnect was for UNCONFIGURING, since the unconfigure hangs
+ * forever.
+ * Fix is that free command queue sets acr state and acr flags if there
+ * is a change under the lock
+ * note free command queue writes to this state it clears it
+ * before releasing the lock, different drivers call the free command
+ * queue different times so dont initialize above
+ */
+ if (vscsi->phyp_acr_state != 0) {
+ /*
+ * set any bits in flags that may have been cleared by
+ * a call to free command queue in switch statement
+ * or reset queue
+ */
+ vscsi->flags |= vscsi->phyp_acr_flags;
+ ibmvscsis_post_disconnect(vscsi, vscsi->phyp_acr_state, 0);
+ vscsi->phyp_acr_state = 0;
+ vscsi->phyp_acr_flags = 0;
+
+ pr_debug("adapter_idle: flags 0x%x, state 0x%hx, acr_flags 0x%x, acr_state 0x%hx\n",
+ vscsi->flags, vscsi->state, vscsi->phyp_acr_flags,
+ vscsi->phyp_acr_state);
+ }
+
+ pr_debug("Leaving adapter_idle: flags 0x%x, state 0x%hx, new_state 0x%x\n",
+ vscsi->flags, vscsi->state, vscsi->new_state);
+}
+
+/**
+ * ibmvscsis_copy_crq_packet() - Copy CRQ Packet
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to command element to use to process the request
+ * @crq: Pointer to CRQ entry containing the request
+ *
+ * Copy the srp information unit from the hosted
+ * partition using remote dma
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_copy_crq_packet(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd,
+ struct viosrp_crq *crq)
+{
+ struct iu_entry *iue = cmd->iue;
+ long rc = 0;
+ u16 len;
+
+ len = be16_to_cpu(crq->IU_length);
+ if ((len > SRP_MAX_IU_LEN) || (len == 0)) {
+ dev_err(&vscsi->dev, "copy_crq: Invalid len %d passed", len);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ return SRP_VIOLATION;
+ }
+
+ rc = h_copy_rdma(len, vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(crq->IU_data_ptr),
+ vscsi->dds.window[LOCAL].liobn, iue->sbuf->dma);
+
+ switch (rc) {
+ case H_SUCCESS:
+ cmd->init_time = mftb();
+ iue->remote_token = crq->IU_data_ptr;
+ iue->iu_len = len;
+ pr_debug("copy_crq: ioba 0x%llx, init_time 0x%llx\n",
+ be64_to_cpu(crq->IU_data_ptr), cmd->init_time);
+ break;
+ case H_PERMISSION:
+ if (connection_broken(vscsi))
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT,
+ (RESPONSE_Q_DOWN |
+ CLIENT_FAILED));
+ else
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+
+ dev_err(&vscsi->dev, "copy_crq: h_copy_rdma failed, rc %ld\n",
+ rc);
+ break;
+ case H_DEST_PARM:
+ case H_SOURCE_PARM:
+ default:
+ dev_err(&vscsi->dev, "copy_crq: h_copy_rdma failed, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_adapter_info - Service an Adapter Info MAnagement Data gram
+ * @vscsi: Pointer to our adapter structure
+ * @iue: Information Unit containing the Adapter Info MAD request
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt adpater lock is held
+ */
+static long ibmvscsis_adapter_info(struct scsi_info *vscsi,
+ struct iu_entry *iue)
+{
+ struct viosrp_adapter_info *mad = &vio_iu(iue)->mad.adapter_info;
+ struct mad_adapter_info_data *info;
+ uint flag_bits = 0;
+ dma_addr_t token;
+ long rc;
+
+ mad->common.status = cpu_to_be16(VIOSRP_MAD_SUCCESS);
+
+ if (be16_to_cpu(mad->common.length) > sizeof(*info)) {
+ mad->common.status = cpu_to_be16(VIOSRP_MAD_FAILED);
+ return 0;
+ }
+
+ info = dma_alloc_coherent(&vscsi->dma_dev->dev, sizeof(*info), &token,
+ GFP_KERNEL);
+ if (!info) {
+ dev_err(&vscsi->dev, "bad dma_alloc_coherent %p\n",
+ iue->target);
+ mad->common.status = cpu_to_be16(VIOSRP_MAD_FAILED);
+ return 0;
+ }
+
+ /* Get remote info */
+ rc = h_copy_rdma(be16_to_cpu(mad->common.length),
+ vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(mad->buffer),
+ vscsi->dds.window[LOCAL].liobn, token);
+
+ if (rc != H_SUCCESS) {
+ if (rc == H_PERMISSION) {
+ if (connection_broken(vscsi))
+ flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED);
+ }
+ pr_warn("adapter_info: h_copy_rdma from client failed, rc %ld\n",
+ rc);
+ pr_debug("adapter_info: ioba 0x%llx, flags 0x%x, flag_bits 0x%x\n",
+ be64_to_cpu(mad->buffer), vscsi->flags, flag_bits);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ goto free_dma;
+ }
+
+ /*
+ * Copy client info, but ignore partition number, which we
+ * already got from phyp - unless we failed to get it from
+ * phyp (e.g. if we're running on a p5 system).
+ */
+ if (vscsi->client_data.partition_number == 0)
+ vscsi->client_data.partition_number =
+ be32_to_cpu(info->partition_number);
+ strncpy(vscsi->client_data.srp_version, info->srp_version,
+ sizeof(vscsi->client_data.srp_version));
+ strncpy(vscsi->client_data.partition_name, info->partition_name,
+ sizeof(vscsi->client_data.partition_name));
+ vscsi->client_data.mad_version = be32_to_cpu(info->mad_version);
+ vscsi->client_data.os_type = be32_to_cpu(info->os_type);
+
+ /* Copy our info */
+ strncpy(info->srp_version, SRP_VERSION,
+ sizeof(info->srp_version));
+ strncpy(info->partition_name, vscsi->dds.partition_name,
+ sizeof(info->partition_name));
+ info->partition_number = cpu_to_be32(vscsi->dds.partition_num);
+ info->mad_version = cpu_to_be32(MAD_VERSION_1);
+ info->os_type = cpu_to_be32(LINUX);
+ memset(&info->port_max_txu[0], 0, sizeof(info->port_max_txu));
+ info->port_max_txu[0] = cpu_to_be32(128 * PAGE_SIZE);
+
+ dma_wmb();
+ rc = h_copy_rdma(sizeof(*info), vscsi->dds.window[LOCAL].liobn,
+ token, vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(mad->buffer));
+ switch (rc) {
+ case H_SUCCESS:
+ break;
+
+ case H_SOURCE_PARM:
+ case H_DEST_PARM:
+ case H_PERMISSION:
+ if (connection_broken(vscsi))
+ flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED);
+ default:
+ dev_err(&vscsi->dev, "adapter_info: h_copy_rdma to client failed, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ break;
+ }
+
+free_dma:
+ dma_free_coherent(&vscsi->dma_dev->dev, sizeof(*info), info, token);
+ pr_debug("Leaving adapter_info, rc %ld\n", rc);
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_cap_mad() - Service a Capabilities MAnagement Data gram
+ * @vscsi: Pointer to our adapter structure
+ * @iue: Information Unit containing the Capabilities MAD request
+ *
+ * NOTE: if you return an error from this routine you must be
+ * disconnecting or you will cause a hang
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt called with adapter lock held
+ */
+static int ibmvscsis_cap_mad(struct scsi_info *vscsi, struct iu_entry *iue)
+{
+ struct viosrp_capabilities *mad = &vio_iu(iue)->mad.capabilities;
+ struct capabilities *cap;
+ struct mad_capability_common *common;
+ dma_addr_t token;
+ u16 olen, len, status, min_len, cap_len;
+ u32 flag;
+ uint flag_bits = 0;
+ long rc = 0;
+
+ olen = be16_to_cpu(mad->common.length);
+ /*
+ * struct capabilities hardcodes a couple capabilities after the
+ * header, but the capabilities can actually be in any order.
+ */
+ min_len = offsetof(struct capabilities, migration);
+ if ((olen < min_len) || (olen > PAGE_SIZE)) {
+ pr_warn("cap_mad: invalid len %d\n", olen);
+ mad->common.status = cpu_to_be16(VIOSRP_MAD_FAILED);
+ return 0;
+ }
+
+ cap = dma_alloc_coherent(&vscsi->dma_dev->dev, olen, &token,
+ GFP_KERNEL);
+ if (!cap) {
+ dev_err(&vscsi->dev, "bad dma_alloc_coherent %p\n",
+ iue->target);
+ mad->common.status = cpu_to_be16(VIOSRP_MAD_FAILED);
+ return 0;
+ }
+ rc = h_copy_rdma(olen, vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(mad->buffer),
+ vscsi->dds.window[LOCAL].liobn, token);
+ if (rc == H_SUCCESS) {
+ strncpy(cap->name, dev_name(&vscsi->dma_dev->dev),
+ SRP_MAX_LOC_LEN);
+
+ len = olen - min_len;
+ status = VIOSRP_MAD_SUCCESS;
+ common = (struct mad_capability_common *)&cap->migration;
+
+ while ((len > 0) && (status == VIOSRP_MAD_SUCCESS) && !rc) {
+ pr_debug("cap_mad: len left %hd, cap type %d, cap len %hd\n",
+ len, be32_to_cpu(common->cap_type),
+ be16_to_cpu(common->length));
+
+ cap_len = be16_to_cpu(common->length);
+ if (cap_len > len) {
+ dev_err(&vscsi->dev, "cap_mad: cap len mismatch with total len\n");
+ status = VIOSRP_MAD_FAILED;
+ break;
+ }
+
+ if (cap_len == 0) {
+ dev_err(&vscsi->dev, "cap_mad: cap len is 0\n");
+ status = VIOSRP_MAD_FAILED;
+ break;
+ }
+
+ switch (common->cap_type) {
+ default:
+ pr_debug("cap_mad: unsupported capability\n");
+ common->server_support = 0;
+ flag = cpu_to_be32((u32)CAP_LIST_SUPPORTED);
+ cap->flags &= ~flag;
+ break;
+ }
+
+ len = len - cap_len;
+ common = (struct mad_capability_common *)
+ ((char *)common + cap_len);
+ }
+
+ mad->common.status = cpu_to_be16(status);
+
+ dma_wmb();
+ rc = h_copy_rdma(olen, vscsi->dds.window[LOCAL].liobn, token,
+ vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(mad->buffer));
+
+ if (rc != H_SUCCESS) {
+ pr_debug("cap_mad: failed to copy to client, rc %ld\n",
+ rc);
+
+ if (rc == H_PERMISSION) {
+ if (connection_broken(vscsi))
+ flag_bits = (RESPONSE_Q_DOWN |
+ CLIENT_FAILED);
+ }
+
+ pr_warn("cap_mad: error copying data to client, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ }
+ }
+
+ dma_free_coherent(&vscsi->dma_dev->dev, olen, cap, token);
+
+ pr_debug("Leaving cap_mad, rc %ld, client_cap 0x%x\n",
+ rc, vscsi->client_cap);
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_process_mad() - Service a MAnagement Data gram
+ * @vscsi: Pointer to our adapter structure
+ * @iue: Information Unit containing the MAD request
+ *
+ * Must be called with interrupt lock held.
+ */
+static long ibmvscsis_process_mad(struct scsi_info *vscsi, struct iu_entry *iue)
+{
+ struct mad_common *mad = (struct mad_common *)&vio_iu(iue)->mad;
+ struct viosrp_empty_iu *empty;
+ long rc = ADAPT_SUCCESS;
+
+ switch (be32_to_cpu(mad->type)) {
+ case VIOSRP_EMPTY_IU_TYPE:
+ empty = &vio_iu(iue)->mad.empty_iu;
+ vscsi->empty_iu_id = be64_to_cpu(empty->buffer);
+ vscsi->empty_iu_tag = be64_to_cpu(empty->common.tag);
+ mad->status = cpu_to_be16(VIOSRP_MAD_SUCCESS);
+ break;
+ case VIOSRP_ADAPTER_INFO_TYPE:
+ rc = ibmvscsis_adapter_info(vscsi, iue);
+ break;
+ case VIOSRP_CAPABILITIES_TYPE:
+ rc = ibmvscsis_cap_mad(vscsi, iue);
+ break;
+ case VIOSRP_ENABLE_FAST_FAIL:
+ if (vscsi->state == CONNECTED) {
+ vscsi->fast_fail = true;
+ mad->status = cpu_to_be16(VIOSRP_MAD_SUCCESS);
+ } else {
+ pr_warn("fast fail mad sent after login\n");
+ mad->status = cpu_to_be16(VIOSRP_MAD_FAILED);
+ }
+ break;
+ default:
+ mad->status = cpu_to_be16(VIOSRP_MAD_NOT_SUPPORTED);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * srp_snd_msg_failed() - Handle an error when sending a response
+ * @vscsi: Pointer to our adapter structure
+ * @rc: The return code from the h_send_crq command
+ *
+ * Must be called with interrupt lock held.
+ */
+static void srp_snd_msg_failed(struct scsi_info *vscsi, long rc)
+{
+ ktime_t kt;
+
+ if (rc != H_DROPPED) {
+ ibmvscsis_free_cmd_qs(vscsi);
+
+ if (rc == H_CLOSED)
+ vscsi->flags |= CLIENT_FAILED;
+
+ /* don't flag the same problem multiple times */
+ if (!(vscsi->flags & RESPONSE_Q_DOWN)) {
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ if (!(vscsi->state & (ERR_DISCONNECT |
+ ERR_DISCONNECT_RECONNECT |
+ ERR_DISCONNECTED | UNDEFINED))) {
+ dev_err(&vscsi->dev, "snd_msg_failed: setting RESPONSE_Q_DOWN, state 0x%hx, flags 0x%x, rc %ld\n",
+ vscsi->state, vscsi->flags, rc);
+ }
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+ }
+ return;
+ }
+
+ /*
+ * The response queue is full.
+ * If the server is processing SRP requests, i.e.
+ * the client has successfully done an
+ * SRP_LOGIN, then it will wait forever for room in
+ * the queue. However if the system admin
+ * is attempting to unconfigure the server then one
+ * or more children will be in a state where
+ * they are being removed. So if there is even one
+ * child being removed then the driver assumes
+ * the system admin is attempting to break the
+ * connection with the client and MAX_TIMER_POPS
+ * is honored.
+ */
+ if ((vscsi->rsp_q_timer.timer_pops < MAX_TIMER_POPS) ||
+ (vscsi->state == SRP_PROCESSING)) {
+ pr_debug("snd_msg_failed: response queue full, flags 0x%x, timer started %d, pops %d\n",
+ vscsi->flags, (int)vscsi->rsp_q_timer.started,
+ vscsi->rsp_q_timer.timer_pops);
+
+ /*
+ * Check if the timer is running; if it
+ * is not then start it up.
+ */
+ if (!vscsi->rsp_q_timer.started) {
+ if (vscsi->rsp_q_timer.timer_pops <
+ MAX_TIMER_POPS) {
+ kt = ktime_set(0, WAIT_NANO_SECONDS);
+ } else {
+ /*
+ * slide the timeslice if the maximum
+ * timer pops have already happened
+ */
+ kt = ktime_set(WAIT_SECONDS, 0);
+ }
+
+ vscsi->rsp_q_timer.started = true;
+ hrtimer_start(&vscsi->rsp_q_timer.timer, kt,
+ HRTIMER_MODE_REL);
+ }
+ } else {
+ /*
+ * TBD: Do we need to worry about this? Need to get
+ * remove working.
+ */
+ /*
+ * waited a long time and it appears the system admin
+ * is bring this driver down
+ */
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ ibmvscsis_free_cmd_qs(vscsi);
+ /*
+ * if the driver is already attempting to disconnect
+ * from the client and has already logged an error
+ * trace this event but don't put it in the error log
+ */
+ if (!(vscsi->state & (ERR_DISCONNECT |
+ ERR_DISCONNECT_RECONNECT |
+ ERR_DISCONNECTED | UNDEFINED))) {
+ dev_err(&vscsi->dev, "client crq full too long\n");
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT,
+ 0);
+ }
+ }
+}
+
+/**
+ * ibmvscsis_send_messages() - Send a Response
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Send a response, first checking the waiting queue. Responses are
+ * sent in order they are received. If the response cannot be sent,
+ * because the client queue is full, it stays on the waiting queue.
+ *
+ * PRECONDITION:
+ * Called with interrupt lock held
+ */
+static void ibmvscsis_send_messages(struct scsi_info *vscsi)
+{
+ u64 msg_hi = 0;
+ /* note do not attmempt to access the IU_data_ptr with this pointer
+ * it is not valid
+ */
+ struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi;
+ struct ibmvscsis_cmd *cmd, *nxt;
+ struct iu_entry *iue;
+ long rc = ADAPT_SUCCESS;
+
+ if (!(vscsi->flags & RESPONSE_Q_DOWN)) {
+ list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) {
+ pr_debug("send_messages cmd %p\n", cmd);
+
+ iue = cmd->iue;
+
+ crq->valid = VALID_CMD_RESP_EL;
+ crq->format = cmd->rsp.format;
+
+ if (cmd->flags & CMD_FAST_FAIL)
+ crq->status = VIOSRP_ADAPTER_FAIL;
+
+ crq->IU_length = cpu_to_be16(cmd->rsp.len);
+
+ rc = h_send_crq(vscsi->dma_dev->unit_address,
+ be64_to_cpu(msg_hi),
+ be64_to_cpu(cmd->rsp.tag));
+
+ pr_debug("send_messages: tag 0x%llx, rc %ld\n",
+ be64_to_cpu(cmd->rsp.tag), rc);
+
+ /* if all ok free up the command element resources */
+ if (rc == H_SUCCESS) {
+ /* some movement has occurred */
+ vscsi->rsp_q_timer.timer_pops = 0;
+ list_del(&cmd->list);
+
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ } else {
+ srp_snd_msg_failed(vscsi, rc);
+ break;
+ }
+ }
+
+ if (!rc) {
+ /*
+ * The timer could pop with the queue empty. If
+ * this happens, rc will always indicate a
+ * success; clear the pop count.
+ */
+ vscsi->rsp_q_timer.timer_pops = 0;
+ }
+ } else {
+ ibmvscsis_free_cmd_qs(vscsi);
+ }
+}
+
+/* Called with intr lock held */
+static void ibmvscsis_send_mad_resp(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd,
+ struct viosrp_crq *crq)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct mad_common *mad = (struct mad_common *)&vio_iu(iue)->mad;
+ uint flag_bits = 0;
+ long rc;
+
+ dma_wmb();
+ rc = h_copy_rdma(sizeof(struct mad_common),
+ vscsi->dds.window[LOCAL].liobn, iue->sbuf->dma,
+ vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(crq->IU_data_ptr));
+ if (!rc) {
+ cmd->rsp.format = VIOSRP_MAD_FORMAT;
+ cmd->rsp.len = sizeof(struct mad_common);
+ cmd->rsp.tag = mad->tag;
+ list_add_tail(&cmd->list, &vscsi->waiting_rsp);
+ ibmvscsis_send_messages(vscsi);
+ } else {
+ pr_debug("Error sending mad response, rc %ld\n", rc);
+ if (rc == H_PERMISSION) {
+ if (connection_broken(vscsi))
+ flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED);
+ }
+ dev_err(&vscsi->dev, "mad: failed to copy to client, rc %ld\n",
+ rc);
+
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ }
+}
+
+/**
+ * ibmvscsis_mad() - Service a MAnagement Data gram.
+ * @vscsi: Pointer to our adapter structure
+ * @crq: Pointer to the CRQ entry containing the MAD request
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt called with adapter lock held
+ */
+static long ibmvscsis_mad(struct scsi_info *vscsi, struct viosrp_crq *crq)
+{
+ struct iu_entry *iue;
+ struct ibmvscsis_cmd *cmd;
+ struct mad_common *mad;
+ long rc = ADAPT_SUCCESS;
+
+ switch (vscsi->state) {
+ /*
+ * We have not exchanged Init Msgs yet, so this MAD was sent
+ * before the last Transport Event; client will not be
+ * expecting a response.
+ */
+ case WAIT_CONNECTION:
+ pr_debug("mad: in Wait Connection state, ignoring MAD, flags %d\n",
+ vscsi->flags);
+ return ADAPT_SUCCESS;
+
+ case SRP_PROCESSING:
+ case CONNECTED:
+ break;
+
+ /*
+ * We should never get here while we're in these states.
+ * Just log an error and get out.
+ */
+ case UNCONFIGURING:
+ case WAIT_IDLE:
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ default:
+ dev_err(&vscsi->dev, "mad: invalid adapter state %d for mad\n",
+ vscsi->state);
+ return ADAPT_SUCCESS;
+ }
+
+ cmd = ibmvscsis_get_free_cmd(vscsi);
+ if (!cmd) {
+ dev_err(&vscsi->dev, "mad: failed to get cmd, debit %d\n",
+ vscsi->debit);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ return ERROR;
+ }
+ iue = cmd->iue;
+ cmd->type = ADAPTER_MAD;
+
+ rc = ibmvscsis_copy_crq_packet(vscsi, cmd, crq);
+ if (!rc) {
+ mad = (struct mad_common *)&vio_iu(iue)->mad;
+
+ pr_debug("mad: type %d\n", be32_to_cpu(mad->type));
+
+ if (be16_to_cpu(mad->length) < 0) {
+ dev_err(&vscsi->dev, "mad: length is < 0\n");
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+ rc = SRP_VIOLATION;
+ } else {
+ rc = ibmvscsis_process_mad(vscsi, iue);
+ }
+
+ pr_debug("mad: status %hd, rc %ld\n", be16_to_cpu(mad->status),
+ rc);
+
+ if (!rc)
+ ibmvscsis_send_mad_resp(vscsi, cmd, crq);
+ } else {
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ }
+
+ pr_debug("Leaving mad, rc %ld\n", rc);
+ return rc;
+}
+
+/**
+ * ibmvscsis_login_rsp() - Create/copy a login response notice to the client
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to the command for the SRP Login request
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_login_rsp(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_login_rsp *rsp = &vio_iu(iue)->srp.login_rsp;
+ struct format_code *fmt;
+ uint flag_bits = 0;
+ long rc = ADAPT_SUCCESS;
+
+ memset(rsp, 0, sizeof(struct srp_login_rsp));
+
+ rsp->opcode = SRP_LOGIN_RSP;
+ rsp->req_lim_delta = cpu_to_be32(vscsi->request_limit);
+ rsp->tag = cmd->rsp.tag;
+ rsp->max_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+ rsp->max_ti_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+ fmt = (struct format_code *)&rsp->buf_fmt;
+ fmt->buffers = SUPPORTED_FORMATS;
+ vscsi->credit = 0;
+
+ cmd->rsp.len = sizeof(struct srp_login_rsp);
+
+ dma_wmb();
+ rc = h_copy_rdma(cmd->rsp.len, vscsi->dds.window[LOCAL].liobn,
+ iue->sbuf->dma, vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(iue->remote_token));
+
+ switch (rc) {
+ case H_SUCCESS:
+ break;
+
+ case H_PERMISSION:
+ if (connection_broken(vscsi))
+ flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED;
+ dev_err(&vscsi->dev, "login_rsp: error copying to client, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ break;
+ case H_SOURCE_PARM:
+ case H_DEST_PARM:
+ default:
+ dev_err(&vscsi->dev, "login_rsp: error copying to client, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_srp_login_rej() - Create/copy a login rejection notice to client
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to the command for the SRP Login request
+ * @reason: The reason the SRP Login is being rejected, per SRP protocol
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_srp_login_rej(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd, u32 reason)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_login_rej *rej = &vio_iu(iue)->srp.login_rej;
+ struct format_code *fmt;
+ uint flag_bits = 0;
+ long rc = ADAPT_SUCCESS;
+
+ memset(rej, 0, sizeof(*rej));
+
+ rej->opcode = SRP_LOGIN_REJ;
+ rej->reason = cpu_to_be32(reason);
+ rej->tag = cmd->rsp.tag;
+ fmt = (struct format_code *)&rej->buf_fmt;
+ fmt->buffers = SUPPORTED_FORMATS;
+
+ cmd->rsp.len = sizeof(*rej);
+
+ dma_wmb();
+ rc = h_copy_rdma(cmd->rsp.len, vscsi->dds.window[LOCAL].liobn,
+ iue->sbuf->dma, vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(iue->remote_token));
+
+ switch (rc) {
+ case H_SUCCESS:
+ break;
+ case H_PERMISSION:
+ if (connection_broken(vscsi))
+ flag_bits = RESPONSE_Q_DOWN | CLIENT_FAILED;
+ dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT,
+ flag_bits);
+ break;
+ case H_SOURCE_PARM:
+ case H_DEST_PARM:
+ default:
+ dev_err(&vscsi->dev, "login_rej: error copying to client, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+static int ibmvscsis_make_nexus(struct ibmvscsis_tport *tport)
+{
+ char *name = tport->tport_name;
+ struct ibmvscsis_nexus *nexus;
+ int rc;
+
+ if (tport->ibmv_nexus) {
+ pr_debug("tport->ibmv_nexus already exists\n");
+ return 0;
+ }
+
+ nexus = kzalloc(sizeof(*nexus), GFP_KERNEL);
+ if (!nexus) {
+ pr_err("Unable to allocate struct ibmvscsis_nexus\n");
+ return -ENOMEM;
+ }
+
+ nexus->se_sess = target_alloc_session(&tport->se_tpg, 0, 0,
+ TARGET_PROT_NORMAL, name, nexus,
+ NULL);
+ if (IS_ERR(nexus->se_sess)) {
+ rc = PTR_ERR(nexus->se_sess);
+ goto transport_init_fail;
+ }
+
+ tport->ibmv_nexus = nexus;
+
+ return 0;
+
+transport_init_fail:
+ kfree(nexus);
+ return rc;
+}
+
+static int ibmvscsis_drop_nexus(struct ibmvscsis_tport *tport)
+{
+ struct se_session *se_sess;
+ struct ibmvscsis_nexus *nexus;
+
+ nexus = tport->ibmv_nexus;
+ if (!nexus)
+ return -ENODEV;
+
+ se_sess = nexus->se_sess;
+ if (!se_sess)
+ return -ENODEV;
+
+ /*
+ * Release the SCSI I_T Nexus to the emulated ibmvscsis Target Port
+ */
+ transport_deregister_session(se_sess);
+ tport->ibmv_nexus = NULL;
+ kfree(nexus);
+
+ return 0;
+}
+
+/**
+ * ibmvscsis_srp_login() - Process an SRP Login Request
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Command element to use to process the SRP Login request
+ * @crq: Pointer to CRQ entry containing the SRP Login request
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, called with interrupt lock held
+ */
+static long ibmvscsis_srp_login(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd,
+ struct viosrp_crq *crq)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_login_req *req = &vio_iu(iue)->srp.login_req;
+ struct port_id {
+ __be64 id_extension;
+ __be64 io_guid;
+ } *iport, *tport;
+ struct format_code *fmt;
+ u32 reason = 0x0;
+ long rc = ADAPT_SUCCESS;
+
+ iport = (struct port_id *)req->initiator_port_id;
+ tport = (struct port_id *)req->target_port_id;
+ fmt = (struct format_code *)&req->req_buf_fmt;
+ if (be32_to_cpu(req->req_it_iu_len) > SRP_MAX_IU_LEN)
+ reason = SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE;
+ else if (be32_to_cpu(req->req_it_iu_len) < 64)
+ reason = SRP_LOGIN_REJ_UNABLE_ESTABLISH_CHANNEL;
+ else if ((be64_to_cpu(iport->id_extension) > (MAX_NUM_PORTS - 1)) ||
+ (be64_to_cpu(tport->id_extension) > (MAX_NUM_PORTS - 1)))
+ reason = SRP_LOGIN_REJ_UNABLE_ASSOCIATE_CHANNEL;
+ else if (req->req_flags & SRP_MULTICHAN_MULTI)
+ reason = SRP_LOGIN_REJ_MULTI_CHANNEL_UNSUPPORTED;
+ else if (fmt->buffers & (~SUPPORTED_FORMATS))
+ reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT;
+ else if ((fmt->buffers | SUPPORTED_FORMATS) == 0)
+ reason = SRP_LOGIN_REJ_UNSUPPORTED_DESCRIPTOR_FMT;
+
+ if (vscsi->state == SRP_PROCESSING)
+ reason = SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED;
+
+ rc = ibmvscsis_make_nexus(&vscsi->tport);
+ if (rc)
+ reason = SRP_LOGIN_REJ_UNABLE_ESTABLISH_CHANNEL;
+
+ cmd->rsp.format = VIOSRP_SRP_FORMAT;
+ cmd->rsp.tag = req->tag;
+
+ pr_debug("srp_login: reason 0x%x\n", reason);
+
+ if (reason)
+ rc = ibmvscsis_srp_login_rej(vscsi, cmd, reason);
+ else
+ rc = ibmvscsis_login_rsp(vscsi, cmd);
+
+ if (!rc) {
+ if (!reason)
+ vscsi->state = SRP_PROCESSING;
+
+ list_add_tail(&cmd->list, &vscsi->waiting_rsp);
+ ibmvscsis_send_messages(vscsi);
+ } else {
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ }
+
+ pr_debug("Leaving srp_login, rc %ld\n", rc);
+ return rc;
+}
+
+/**
+ * ibmvscsis_srp_i_logout() - Helper Function to close I_T Nexus
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Command element to use to process the Implicit Logout request
+ * @crq: Pointer to CRQ entry containing the Implicit Logout request
+ *
+ * Do the logic to close the I_T nexus. This function may not
+ * behave to specification.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_srp_i_logout(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd,
+ struct viosrp_crq *crq)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_i_logout *log_out = &vio_iu(iue)->srp.i_logout;
+ long rc = ADAPT_SUCCESS;
+
+ if ((vscsi->debit > 0) || !list_empty(&vscsi->schedule_q) ||
+ !list_empty(&vscsi->waiting_rsp)) {
+ dev_err(&vscsi->dev, "i_logout: outstanding work\n");
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
+ } else {
+ cmd->rsp.format = SRP_FORMAT;
+ cmd->rsp.tag = log_out->tag;
+ cmd->rsp.len = sizeof(struct mad_common);
+ list_add_tail(&cmd->list, &vscsi->waiting_rsp);
+ ibmvscsis_send_messages(vscsi);
+
+ ibmvscsis_post_disconnect(vscsi, WAIT_IDLE, 0);
+ }
+
+ return rc;
+}
+
+/* Called with intr lock held */
+static void ibmvscsis_srp_cmd(struct scsi_info *vscsi, struct viosrp_crq *crq)
+{
+ struct ibmvscsis_cmd *cmd;
+ struct iu_entry *iue;
+ struct srp_cmd *srp;
+ struct srp_tsk_mgmt *tsk;
+ long rc;
+
+ if (vscsi->request_limit - vscsi->debit <= 0) {
+ /* Client has exceeded request limit */
+ dev_err(&vscsi->dev, "Client exceeded the request limit (%d), debit %d\n",
+ vscsi->request_limit, vscsi->debit);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ return;
+ }
+
+ cmd = ibmvscsis_get_free_cmd(vscsi);
+ if (!cmd) {
+ dev_err(&vscsi->dev, "srp_cmd failed to get cmd, debit %d\n",
+ vscsi->debit);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ return;
+ }
+ iue = cmd->iue;
+ srp = &vio_iu(iue)->srp.cmd;
+
+ rc = ibmvscsis_copy_crq_packet(vscsi, cmd, crq);
+ if (rc) {
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ return;
+ }
+
+ if (vscsi->state == SRP_PROCESSING) {
+ switch (srp->opcode) {
+ case SRP_LOGIN_REQ:
+ rc = ibmvscsis_srp_login(vscsi, cmd, crq);
+ break;
+
+ case SRP_TSK_MGMT:
+ tsk = &vio_iu(iue)->srp.tsk_mgmt;
+ pr_debug("tsk_mgmt tag: %llu (0x%llx)\n", tsk->tag,
+ tsk->tag);
+ cmd->rsp.tag = tsk->tag;
+ vscsi->debit += 1;
+ cmd->type = TASK_MANAGEMENT;
+ list_add_tail(&cmd->list, &vscsi->schedule_q);
+ queue_work(vscsi->work_q, &cmd->work);
+ break;
+
+ case SRP_CMD:
+ pr_debug("srp_cmd tag: %llu (0x%llx)\n", srp->tag,
+ srp->tag);
+ cmd->rsp.tag = srp->tag;
+ vscsi->debit += 1;
+ cmd->type = SCSI_CDB;
+ /*
+ * We want to keep track of work waiting for
+ * the workqueue.
+ */
+ list_add_tail(&cmd->list, &vscsi->schedule_q);
+ queue_work(vscsi->work_q, &cmd->work);
+ break;
+
+ case SRP_I_LOGOUT:
+ rc = ibmvscsis_srp_i_logout(vscsi, cmd, crq);
+ break;
+
+ case SRP_CRED_RSP:
+ case SRP_AER_RSP:
+ default:
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ dev_err(&vscsi->dev, "invalid srp cmd, opcode %d\n",
+ (uint)srp->opcode);
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+ } else if (srp->opcode == SRP_LOGIN_REQ && vscsi->state == CONNECTED) {
+ rc = ibmvscsis_srp_login(vscsi, cmd, crq);
+ } else {
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ dev_err(&vscsi->dev, "Invalid state %d to handle srp cmd\n",
+ vscsi->state);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ }
+}
+
+/**
+ * ibmvscsis_ping_response() - Respond to a ping request
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Let the client know that the server is alive and waiting on
+ * its native I/O stack.
+ * If any type of error occurs from the call to queue a ping
+ * response then the client is either not accepting or receiving
+ * interrupts. Disconnect with an error.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_ping_response(struct scsi_info *vscsi)
+{
+ struct viosrp_crq *crq;
+ u64 buffer[2] = { 0, 0 };
+ long rc;
+
+ crq = (struct viosrp_crq *)&buffer;
+ crq->valid = VALID_CMD_RESP_EL;
+ crq->format = (u8)MESSAGE_IN_CRQ;
+ crq->status = PING_RESPONSE;
+
+ rc = h_send_crq(vscsi->dds.unit_id, cpu_to_be64(buffer[MSG_HI]),
+ cpu_to_be64(buffer[MSG_LOW]));
+
+ switch (rc) {
+ case H_SUCCESS:
+ break;
+ case H_CLOSED:
+ vscsi->flags |= CLIENT_FAILED;
+ case H_DROPPED:
+ vscsi->flags |= RESPONSE_Q_DOWN;
+ case H_REMOTE_PARM:
+ dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ default:
+ dev_err(&vscsi->dev, "ping_response: h_send_crq returned unknown rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_handle_init_compl_msg() - Respond to an Init Complete Message
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Must be called with interrupt lock held.
+ */
+static long ibmvscsis_handle_init_compl_msg(struct scsi_info *vscsi)
+{
+ long rc = ADAPT_SUCCESS;
+
+ switch (vscsi->state) {
+ case NO_QUEUE:
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ case ERR_DISCONNECTED:
+ case UNCONFIGURING:
+ case UNDEFINED:
+ rc = ERROR;
+ break;
+
+ case WAIT_CONNECTION:
+ vscsi->state = CONNECTED;
+ break;
+
+ case WAIT_IDLE:
+ case SRP_PROCESSING:
+ case CONNECTED:
+ case WAIT_ENABLED:
+ case PART_UP_WAIT_ENAB:
+ default:
+ rc = ERROR;
+ dev_err(&vscsi->dev, "init_msg: invalid state %d to get init compl msg\n",
+ vscsi->state);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_handle_init_msg() - Respond to an Init Message
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Must be called with interrupt lock held.
+ */
+static long ibmvscsis_handle_init_msg(struct scsi_info *vscsi)
+{
+ long rc = ADAPT_SUCCESS;
+
+ switch (vscsi->state) {
+ case WAIT_ENABLED:
+ vscsi->state = PART_UP_WAIT_ENAB;
+ break;
+
+ case WAIT_CONNECTION:
+ rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
+ switch (rc) {
+ case H_SUCCESS:
+ vscsi->state = CONNECTED;
+ break;
+
+ case H_PARAMETER:
+ dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
+ rc);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT, 0);
+ break;
+
+ case H_DROPPED:
+ dev_err(&vscsi->dev, "init_msg: failed to send, rc %ld\n",
+ rc);
+ rc = ERROR;
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+ break;
+
+ case H_CLOSED:
+ pr_warn("init_msg: failed to send, rc %ld\n", rc);
+ rc = 0;
+ break;
+ }
+ break;
+
+ case UNDEFINED:
+ rc = ERROR;
+ break;
+
+ case UNCONFIGURING:
+ break;
+
+ case PART_UP_WAIT_ENAB:
+ case CONNECTED:
+ case SRP_PROCESSING:
+ case WAIT_IDLE:
+ case NO_QUEUE:
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ case ERR_DISCONNECTED:
+ default:
+ rc = ERROR;
+ dev_err(&vscsi->dev, "init_msg: invalid state %d to get init msg\n",
+ vscsi->state);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_init_msg() - Respond to an init message
+ * @vscsi: Pointer to our adapter structure
+ * @crq: Pointer to CRQ element containing the Init Message
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, interrupt lock held
+ */
+static long ibmvscsis_init_msg(struct scsi_info *vscsi, struct viosrp_crq *crq)
+{
+ long rc = ADAPT_SUCCESS;
+
+ pr_debug("init_msg: state 0x%hx\n", vscsi->state);
+
+ rc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
+ (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
+ 0);
+ if (rc == H_SUCCESS) {
+ vscsi->client_data.partition_number =
+ be64_to_cpu(*(u64 *)vscsi->map_buf);
+ pr_debug("init_msg, part num %d\n",
+ vscsi->client_data.partition_number);
+ } else {
+ pr_debug("init_msg h_vioctl rc %ld\n", rc);
+ rc = ADAPT_SUCCESS;
+ }
+
+ if (crq->format == INIT_MSG) {
+ rc = ibmvscsis_handle_init_msg(vscsi);
+ } else if (crq->format == INIT_COMPLETE_MSG) {
+ rc = ibmvscsis_handle_init_compl_msg(vscsi);
+ } else {
+ rc = ERROR;
+ dev_err(&vscsi->dev, "init_msg: invalid format %d\n",
+ (uint)crq->format);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_parse_command() - Parse an element taken from the cmd rsp queue.
+ * @vscsi: Pointer to our adapter structure
+ * @crq: Pointer to CRQ element containing the SRP request
+ *
+ * This function will return success if the command queue element is valid
+ * and the srp iu or MAD request it pointed to was also valid. That does
+ * not mean that an error was not returned to the client.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Interrupt, intr lock held
+ */
+static long ibmvscsis_parse_command(struct scsi_info *vscsi,
+ struct viosrp_crq *crq)
+{
+ long rc = ADAPT_SUCCESS;
+
+ switch (crq->valid) {
+ case VALID_CMD_RESP_EL:
+ switch (crq->format) {
+ case OS400_FORMAT:
+ case AIX_FORMAT:
+ case LINUX_FORMAT:
+ case MAD_FORMAT:
+ if (vscsi->flags & PROCESSING_MAD) {
+ rc = ERROR;
+ dev_err(&vscsi->dev, "parse_command: already processing mad\n");
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT,
+ 0);
+ } else {
+ vscsi->flags |= PROCESSING_MAD;
+ rc = ibmvscsis_mad(vscsi, crq);
+ }
+ break;
+
+ case SRP_FORMAT:
+ ibmvscsis_srp_cmd(vscsi, crq);
+ break;
+
+ case MESSAGE_IN_CRQ:
+ if (crq->status == PING)
+ ibmvscsis_ping_response(vscsi);
+ break;
+
+ default:
+ dev_err(&vscsi->dev, "parse_command: invalid format %d\n",
+ (uint)crq->format);
+ ibmvscsis_post_disconnect(vscsi,
+ ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+ break;
+
+ case VALID_TRANS_EVENT:
+ rc = ibmvscsis_trans_event(vscsi, crq);
+ break;
+
+ case VALID_INIT_MSG:
+ rc = ibmvscsis_init_msg(vscsi, crq);
+ break;
+
+ default:
+ dev_err(&vscsi->dev, "parse_command: invalid valid field %d\n",
+ (uint)crq->valid);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ break;
+ }
+
+ /*
+ * Return only what the interrupt handler cares
+ * about. Most errors we keep right on trucking.
+ */
+ rc = vscsi->flags & SCHEDULE_DISCONNECT;
+
+ return rc;
+}
+
+static int read_dma_window(struct scsi_info *vscsi)
+{
+ struct vio_dev *vdev = vscsi->dma_dev;
+ const __be32 *dma_window;
+ const __be32 *prop;
+
+ /* TODO Using of_parse_dma_window would be better, but it doesn't give
+ * a way to read multiple windows without already knowing the size of
+ * a window or the number of windows.
+ */
+ dma_window = (const __be32 *)vio_get_attribute(vdev,
+ "ibm,my-dma-window",
+ NULL);
+ if (!dma_window) {
+ pr_err("Couldn't find ibm,my-dma-window property\n");
+ return -1;
+ }
+
+ vscsi->dds.window[LOCAL].liobn = be32_to_cpu(*dma_window);
+ dma_window++;
+
+ prop = (const __be32 *)vio_get_attribute(vdev, "ibm,#dma-address-cells",
+ NULL);
+ if (!prop) {
+ pr_warn("Couldn't find ibm,#dma-address-cells property\n");
+ dma_window++;
+ } else {
+ dma_window += be32_to_cpu(*prop);
+ }
+
+ prop = (const __be32 *)vio_get_attribute(vdev, "ibm,#dma-size-cells",
+ NULL);
+ if (!prop) {
+ pr_warn("Couldn't find ibm,#dma-size-cells property\n");
+ dma_window++;
+ } else {
+ dma_window += be32_to_cpu(*prop);
+ }
+
+ /* dma_window should point to the second window now */
+ vscsi->dds.window[REMOTE].liobn = be32_to_cpu(*dma_window);
+
+ return 0;
+}
+
+static struct ibmvscsis_tport *ibmvscsis_lookup_port(const char *name)
+{
+ struct ibmvscsis_tport *tport = NULL;
+ struct vio_dev *vdev;
+ struct scsi_info *vscsi;
+
+ spin_lock_bh(&ibmvscsis_dev_lock);
+ list_for_each_entry(vscsi, &ibmvscsis_dev_list, list) {
+ vdev = vscsi->dma_dev;
+ if (!strcmp(dev_name(&vdev->dev), name)) {
+ tport = &vscsi->tport;
+ break;
+ }
+ }
+ spin_unlock_bh(&ibmvscsis_dev_lock);
+
+ return tport;
+}
+
+/**
+ * ibmvscsis_parse_cmd() - Parse SRP Command
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to command element with SRP command
+ *
+ * Parse the srp command; if it is valid then submit it to tcm.
+ * Note: The return code does not reflect the status of the SCSI CDB.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level
+ */
+static void ibmvscsis_parse_cmd(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_cmd *srp = (struct srp_cmd *)iue->sbuf->buf;
+ struct ibmvscsis_nexus *nexus;
+ u64 data_len = 0;
+ enum dma_data_direction dir;
+ int attr = 0;
+ int rc = 0;
+
+ nexus = vscsi->tport.ibmv_nexus;
+ /*
+ * additional length in bytes. Note that the SRP spec says that
+ * additional length is in 4-byte words, but technically the
+ * additional length field is only the upper 6 bits of the byte.
+ * The lower 2 bits are reserved. If the lower 2 bits are 0 (as
+ * all reserved fields should be), then interpreting the byte as
+ * an int will yield the length in bytes.
+ */
+ if (srp->add_cdb_len & 0x03) {
+ dev_err(&vscsi->dev, "parse_cmd: reserved bits set in IU\n");
+ spin_lock_bh(&vscsi->intr_lock);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ spin_unlock_bh(&vscsi->intr_lock);
+ return;
+ }
+
+ if (srp_get_desc_table(srp, &dir, &data_len)) {
+ dev_err(&vscsi->dev, "0x%llx: parsing SRP descriptor table failed.\n",
+ srp->tag);
+ goto fail;
+ return;
+ }
+
+ cmd->rsp.sol_not = srp->sol_not;
+
+ switch (srp->task_attr) {
+ case SRP_SIMPLE_TASK:
+ attr = TCM_SIMPLE_TAG;
+ break;
+ case SRP_ORDERED_TASK:
+ attr = TCM_ORDERED_TAG;
+ break;
+ case SRP_HEAD_TASK:
+ attr = TCM_HEAD_TAG;
+ break;
+ case SRP_ACA_TASK:
+ attr = TCM_ACA_TAG;
+ break;
+ default:
+ dev_err(&vscsi->dev, "Invalid task attribute %d\n",
+ srp->task_attr);
+ goto fail;
+ }
+
+ cmd->se_cmd.tag = be64_to_cpu(srp->tag);
+
+ spin_lock_bh(&vscsi->intr_lock);
+ list_add_tail(&cmd->list, &vscsi->active_q);
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ srp->lun.scsi_lun[0] &= 0x3f;
+
+ pr_debug("calling submit_cmd, se_cmd %p, lun 0x%llx, cdb 0x%x, attr:%d\n",
+ &cmd->se_cmd, scsilun_to_int(&srp->lun), (int)srp->cdb[0],
+ attr);
+
+ rc = target_submit_cmd(&cmd->se_cmd, nexus->se_sess, srp->cdb,
+ cmd->sense_buf, scsilun_to_int(&srp->lun),
+ data_len, attr, dir, 0);
+ if (rc) {
+ dev_err(&vscsi->dev, "target_submit_cmd failed, rc %d\n", rc);
+ goto fail;
+ }
+ return;
+
+fail:
+ spin_lock_bh(&vscsi->intr_lock);
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ spin_unlock_bh(&vscsi->intr_lock);
+}
+
+/**
+ * ibmvscsis_parse_task() - Parse SRP Task Management Request
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to command element with SRP task management request
+ *
+ * Parse the srp task management request; if it is valid then submit it to tcm.
+ * Note: The return code does not reflect the status of the task management
+ * request.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Processor level
+ */
+static void ibmvscsis_parse_task(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_tsk_mgmt *srp_tsk = &vio_iu(iue)->srp.tsk_mgmt;
+ int tcm_type;
+ u64 tag_to_abort = 0;
+ int rc = 0;
+ struct ibmvscsis_nexus *nexus;
+
+ nexus = vscsi->tport.ibmv_nexus;
+
+ cmd->rsp.sol_not = srp_tsk->sol_not;
+
+ switch (srp_tsk->tsk_mgmt_func) {
+ case SRP_TSK_ABORT_TASK:
+ tcm_type = TMR_ABORT_TASK;
+ tag_to_abort = be64_to_cpu(srp_tsk->task_tag);
+ break;
+ case SRP_TSK_ABORT_TASK_SET:
+ tcm_type = TMR_ABORT_TASK_SET;
+ break;
+ case SRP_TSK_CLEAR_TASK_SET:
+ tcm_type = TMR_CLEAR_TASK_SET;
+ break;
+ case SRP_TSK_LUN_RESET:
+ tcm_type = TMR_LUN_RESET;
+ break;
+ case SRP_TSK_CLEAR_ACA:
+ tcm_type = TMR_CLEAR_ACA;
+ break;
+ default:
+ dev_err(&vscsi->dev, "unknown task mgmt func %d\n",
+ srp_tsk->tsk_mgmt_func);
+ cmd->se_cmd.se_tmr_req->response =
+ TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED;
+ rc = -1;
+ break;
+ }
+
+ if (!rc) {
+ cmd->se_cmd.tag = be64_to_cpu(srp_tsk->tag);
+
+ spin_lock_bh(&vscsi->intr_lock);
+ list_add_tail(&cmd->list, &vscsi->active_q);
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ srp_tsk->lun.scsi_lun[0] &= 0x3f;
+
+ pr_debug("calling submit_tmr, func %d\n",
+ srp_tsk->tsk_mgmt_func);
+ rc = target_submit_tmr(&cmd->se_cmd, nexus->se_sess, NULL,
+ scsilun_to_int(&srp_tsk->lun), srp_tsk,
+ tcm_type, GFP_KERNEL, tag_to_abort, 0);
+ if (rc) {
+ dev_err(&vscsi->dev, "target_submit_tmr failed, rc %d\n",
+ rc);
+ cmd->se_cmd.se_tmr_req->response =
+ TMR_FUNCTION_REJECTED;
+ }
+ }
+
+ if (rc)
+ transport_send_check_condition_and_sense(&cmd->se_cmd, 0, 0);
+}
+
+static void ibmvscsis_scheduler(struct work_struct *work)
+{
+ struct ibmvscsis_cmd *cmd = container_of(work, struct ibmvscsis_cmd,
+ work);
+ struct scsi_info *vscsi = cmd->adapter;
+
+ spin_lock_bh(&vscsi->intr_lock);
+
+ /* Remove from schedule_q */
+ list_del(&cmd->list);
+
+ /* Don't submit cmd if we're disconnecting */
+ if (vscsi->flags & (SCHEDULE_DISCONNECT | DISCONNECT_SCHEDULED)) {
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+
+ /* ibmvscsis_disconnect might be waiting for us */
+ if (list_empty(&vscsi->active_q) &&
+ list_empty(&vscsi->schedule_q) &&
+ (vscsi->flags & WAIT_FOR_IDLE)) {
+ vscsi->flags &= ~WAIT_FOR_IDLE;
+ complete(&vscsi->wait_idle);
+ }
+
+ spin_unlock_bh(&vscsi->intr_lock);
+ return;
+ }
+
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ switch (cmd->type) {
+ case SCSI_CDB:
+ ibmvscsis_parse_cmd(vscsi, cmd);
+ break;
+ case TASK_MANAGEMENT:
+ ibmvscsis_parse_task(vscsi, cmd);
+ break;
+ default:
+ dev_err(&vscsi->dev, "scheduler, invalid cmd type %d\n",
+ cmd->type);
+ spin_lock_bh(&vscsi->intr_lock);
+ ibmvscsis_free_cmd_resources(vscsi, cmd);
+ spin_unlock_bh(&vscsi->intr_lock);
+ break;
+ }
+}
+
+static int ibmvscsis_alloc_cmds(struct scsi_info *vscsi, int num)
+{
+ struct ibmvscsis_cmd *cmd;
+ int i;
+
+ INIT_LIST_HEAD(&vscsi->free_cmd);
+ vscsi->cmd_pool = kcalloc(num, sizeof(struct ibmvscsis_cmd),
+ GFP_KERNEL);
+ if (!vscsi->cmd_pool)
+ return -ENOMEM;
+
+ for (i = 0, cmd = (struct ibmvscsis_cmd *)vscsi->cmd_pool; i < num;
+ i++, cmd++) {
+ cmd->adapter = vscsi;
+ INIT_WORK(&cmd->work, ibmvscsis_scheduler);
+ list_add_tail(&cmd->list, &vscsi->free_cmd);
+ }
+
+ return 0;
+}
+
+static void ibmvscsis_free_cmds(struct scsi_info *vscsi)
+{
+ kfree(vscsi->cmd_pool);
+ vscsi->cmd_pool = NULL;
+ INIT_LIST_HEAD(&vscsi->free_cmd);
+}
+
+/**
+ * ibmvscsis_service_wait_q() - Service Waiting Queue
+ * @timer: Pointer to timer which has expired
+ *
+ * This routine is called when the timer pops to service the waiting
+ * queue. Elements on the queue have completed, their responses have been
+ * copied to the client, but the client's response queue was full so
+ * the queue message could not be sent. The routine grabs the proper locks
+ * and calls send messages.
+ *
+ * EXECUTION ENVIRONMENT:
+ * called at interrupt level
+ */
+static enum hrtimer_restart ibmvscsis_service_wait_q(struct hrtimer *timer)
+{
+ struct timer_cb *p_timer = container_of(timer, struct timer_cb, timer);
+ struct scsi_info *vscsi = container_of(p_timer, struct scsi_info,
+ rsp_q_timer);
+
+ spin_lock_bh(&vscsi->intr_lock);
+ p_timer->timer_pops += 1;
+ p_timer->started = false;
+ ibmvscsis_send_messages(vscsi);
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ return HRTIMER_NORESTART;
+}
+
+static long ibmvscsis_alloctimer(struct scsi_info *vscsi)
+{
+ struct timer_cb *p_timer;
+
+ p_timer = &vscsi->rsp_q_timer;
+ hrtimer_init(&p_timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+
+ p_timer->timer.function = ibmvscsis_service_wait_q;
+ p_timer->started = false;
+ p_timer->timer_pops = 0;
+
+ return ADAPT_SUCCESS;
+}
+
+static void ibmvscsis_freetimer(struct scsi_info *vscsi)
+{
+ struct timer_cb *p_timer;
+
+ p_timer = &vscsi->rsp_q_timer;
+
+ (void)hrtimer_cancel(&p_timer->timer);
+
+ p_timer->started = false;
+ p_timer->timer_pops = 0;
+}
+
+static irqreturn_t ibmvscsis_interrupt(int dummy, void *data)
+{
+ struct scsi_info *vscsi = data;
+
+ vio_disable_interrupts(vscsi->dma_dev);
+ tasklet_schedule(&vscsi->work_task);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ibmvscsis_check_q() - Helper function to Check Init Message Valid
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Checks if a initialize message was queued by the initiatior
+ * while the timing window was open. This function is called from
+ * probe after the CRQ is created and interrupts are enabled.
+ * It would only be used by adapters who wait for some event before
+ * completing the init handshake with the client. For ibmvscsi, this
+ * event is waiting for the port to be enabled.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level only, interrupt lock held
+ */
+static long ibmvscsis_check_q(struct scsi_info *vscsi)
+{
+ uint format;
+ long rc;
+
+ rc = ibmvscsis_check_init_msg(vscsi, &format);
+ if (rc)
+ ibmvscsis_post_disconnect(vscsi, ERR_DISCONNECT_RECONNECT, 0);
+ else if (format == UNUSED_FORMAT)
+ vscsi->state = WAIT_ENABLED;
+ else
+ vscsi->state = PART_UP_WAIT_ENAB;
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_enable_change_state() - Set new state based on enabled status
+ * @vscsi: Pointer to our adapter structure
+ *
+ * This function determines our new state now that we are enabled. This
+ * may involve sending an Init Complete message to the client.
+ *
+ * Must be called with interrupt lock held.
+ */
+static long ibmvscsis_enable_change_state(struct scsi_info *vscsi)
+{
+ long rc = ADAPT_SUCCESS;
+
+handle_state_change:
+ switch (vscsi->state) {
+ case WAIT_ENABLED:
+ rc = ibmvscsis_send_init_message(vscsi, INIT_MSG);
+ switch (rc) {
+ case H_SUCCESS:
+ case H_DROPPED:
+ case H_CLOSED:
+ vscsi->state = WAIT_CONNECTION;
+ rc = ADAPT_SUCCESS;
+ break;
+
+ case H_PARAMETER:
+ break;
+
+ case H_HARDWARE:
+ break;
+
+ default:
+ vscsi->state = UNDEFINED;
+ rc = H_HARDWARE;
+ break;
+ }
+ break;
+ case PART_UP_WAIT_ENAB:
+ rc = ibmvscsis_send_init_message(vscsi, INIT_COMPLETE_MSG);
+ switch (rc) {
+ case H_SUCCESS:
+ vscsi->state = CONNECTED;
+ rc = ADAPT_SUCCESS;
+ break;
+
+ case H_DROPPED:
+ case H_CLOSED:
+ vscsi->state = WAIT_ENABLED;
+ goto handle_state_change;
+
+ case H_PARAMETER:
+ break;
+
+ case H_HARDWARE:
+ break;
+
+ default:
+ rc = H_HARDWARE;
+ break;
+ }
+ break;
+
+ case WAIT_CONNECTION:
+ case WAIT_IDLE:
+ case SRP_PROCESSING:
+ case CONNECTED:
+ rc = ADAPT_SUCCESS;
+ break;
+ /* should not be able to get here */
+ case UNCONFIGURING:
+ rc = ERROR;
+ vscsi->state = UNDEFINED;
+ break;
+
+ /* driver should never allow this to happen */
+ case ERR_DISCONNECT:
+ case ERR_DISCONNECT_RECONNECT:
+ default:
+ dev_err(&vscsi->dev, "in invalid state %d during enable_change_state\n",
+ vscsi->state);
+ rc = ADAPT_SUCCESS;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_create_command_q() - Create Command Queue
+ * @vscsi: Pointer to our adapter structure
+ * @num_cmds: Currently unused. In the future, may be used to determine
+ * the size of the CRQ.
+ *
+ * Allocates memory for command queue maps remote memory into an ioba
+ * initializes the command response queue
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level only
+ */
+static long ibmvscsis_create_command_q(struct scsi_info *vscsi, int num_cmds)
+{
+ long rc = 0;
+ int pages;
+ struct vio_dev *vdev = vscsi->dma_dev;
+
+ /* We might support multiple pages in the future, but just 1 for now */
+ pages = 1;
+
+ vscsi->cmd_q.size = pages;
+
+ vscsi->cmd_q.base_addr =
+ (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
+ if (!vscsi->cmd_q.base_addr)
+ return -ENOMEM;
+
+ vscsi->cmd_q.mask = ((uint)pages * CRQ_PER_PAGE) - 1;
+
+ vscsi->cmd_q.crq_token = dma_map_single(&vdev->dev,
+ vscsi->cmd_q.base_addr,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&vdev->dev, vscsi->cmd_q.crq_token)) {
+ free_page((unsigned long)vscsi->cmd_q.base_addr);
+ return -ENOMEM;
+ }
+
+ rc = h_reg_crq(vscsi->dds.unit_id, vscsi->cmd_q.crq_token, PAGE_SIZE);
+ if (rc) {
+ if (rc == H_CLOSED) {
+ vscsi->state = WAIT_ENABLED;
+ rc = 0;
+ } else {
+ dma_unmap_single(&vdev->dev, vscsi->cmd_q.crq_token,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ free_page((unsigned long)vscsi->cmd_q.base_addr);
+ rc = -ENODEV;
+ }
+ } else {
+ vscsi->state = WAIT_ENABLED;
+ }
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_destroy_command_q - Destroy Command Queue
+ * @vscsi: Pointer to our adapter structure
+ *
+ * Releases memory for command queue and unmaps mapped remote memory.
+ *
+ * EXECUTION ENVIRONMENT:
+ * Process level only
+ */
+static void ibmvscsis_destroy_command_q(struct scsi_info *vscsi)
+{
+ dma_unmap_single(&vscsi->dma_dev->dev, vscsi->cmd_q.crq_token,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ free_page((unsigned long)vscsi->cmd_q.base_addr);
+ vscsi->cmd_q.base_addr = NULL;
+ vscsi->state = NO_QUEUE;
+}
+
+static u8 ibmvscsis_fast_fail(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct srp_cmd *srp = (struct srp_cmd *)iue->sbuf->buf;
+ struct scsi_sense_hdr sshdr;
+ u8 rc = se_cmd->scsi_status;
+
+ if (vscsi->fast_fail && (READ_CMD(srp->cdb) || WRITE_CMD(srp->cdb)))
+ if (scsi_normalize_sense(se_cmd->sense_buffer,
+ se_cmd->scsi_sense_length, &sshdr))
+ if (sshdr.sense_key == HARDWARE_ERROR &&
+ (se_cmd->residual_count == 0 ||
+ se_cmd->residual_count == se_cmd->data_length)) {
+ rc = NO_SENSE;
+ cmd->flags |= CMD_FAST_FAIL;
+ }
+
+ return rc;
+}
+
+/**
+ * srp_build_response() - Build an SRP response buffer
+ * @vscsi: Pointer to our adapter structure
+ * @cmd: Pointer to command for which to send the response
+ * @len_p: Where to return the length of the IU response sent. This
+ * is needed to construct the CRQ response.
+ *
+ * Build the SRP response buffer and copy it to the client's memory space.
+ */
+static long srp_build_response(struct scsi_info *vscsi,
+ struct ibmvscsis_cmd *cmd, uint *len_p)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+ struct srp_rsp *rsp;
+ uint len;
+ u32 rsp_code;
+ char *data;
+ u32 *tsk_status;
+ long rc = ADAPT_SUCCESS;
+
+ spin_lock_bh(&vscsi->intr_lock);
+
+ rsp = &vio_iu(iue)->srp.rsp;
+ len = sizeof(*rsp);
+ memset(rsp, 0, len);
+ data = rsp->data;
+
+ rsp->opcode = SRP_RSP;
+
+ if (vscsi->credit > 0 && vscsi->state == SRP_PROCESSING)
+ rsp->req_lim_delta = cpu_to_be32(vscsi->credit);
+ else
+ rsp->req_lim_delta = cpu_to_be32(1 + vscsi->credit);
+ rsp->tag = cmd->rsp.tag;
+ rsp->flags = 0;
+
+ if (cmd->type == SCSI_CDB) {
+ rsp->status = ibmvscsis_fast_fail(vscsi, cmd);
+ if (rsp->status) {
+ pr_debug("build_resp: cmd %p, scsi status %d\n", cmd,
+ (int)rsp->status);
+ ibmvscsis_determine_resid(se_cmd, rsp);
+ if (se_cmd->scsi_sense_length && se_cmd->sense_buffer) {
+ rsp->sense_data_len =
+ cpu_to_be32(se_cmd->scsi_sense_length);
+ rsp->flags |= SRP_RSP_FLAG_SNSVALID;
+ len += se_cmd->scsi_sense_length;
+ memcpy(data, se_cmd->sense_buffer,
+ se_cmd->scsi_sense_length);
+ }
+ rsp->sol_not = (cmd->rsp.sol_not & UCSOLNT) >>
+ UCSOLNT_RESP_SHIFT;
+ } else if (cmd->flags & CMD_FAST_FAIL) {
+ pr_debug("build_resp: cmd %p, fast fail\n", cmd);
+ rsp->sol_not = (cmd->rsp.sol_not & UCSOLNT) >>
+ UCSOLNT_RESP_SHIFT;
+ } else {
+ rsp->sol_not = (cmd->rsp.sol_not & SCSOLNT) >>
+ SCSOLNT_RESP_SHIFT;
+ }
+ } else {
+ /* this is task management */
+ rsp->status = 0;
+ rsp->resp_data_len = cpu_to_be32(4);
+ rsp->flags |= SRP_RSP_FLAG_RSPVALID;
+
+ switch (se_cmd->se_tmr_req->response) {
+ case TMR_FUNCTION_COMPLETE:
+ case TMR_TASK_DOES_NOT_EXIST:
+ rsp_code = SRP_TASK_MANAGEMENT_FUNCTION_COMPLETE;
+ rsp->sol_not = (cmd->rsp.sol_not & SCSOLNT) >>
+ SCSOLNT_RESP_SHIFT;
+ break;
+ case TMR_TASK_MGMT_FUNCTION_NOT_SUPPORTED:
+ case TMR_LUN_DOES_NOT_EXIST:
+ rsp_code = SRP_TASK_MANAGEMENT_FUNCTION_NOT_SUPPORTED;
+ rsp->sol_not = (cmd->rsp.sol_not & UCSOLNT) >>
+ UCSOLNT_RESP_SHIFT;
+ break;
+ case TMR_FUNCTION_FAILED:
+ case TMR_FUNCTION_REJECTED:
+ default:
+ rsp_code = SRP_TASK_MANAGEMENT_FUNCTION_FAILED;
+ rsp->sol_not = (cmd->rsp.sol_not & UCSOLNT) >>
+ UCSOLNT_RESP_SHIFT;
+ break;
+ }
+
+ tsk_status = (u32 *)data;
+ *tsk_status = cpu_to_be32(rsp_code);
+ data = (char *)(tsk_status + 1);
+ len += 4;
+ }
+
+ dma_wmb();
+ rc = h_copy_rdma(len, vscsi->dds.window[LOCAL].liobn, iue->sbuf->dma,
+ vscsi->dds.window[REMOTE].liobn,
+ be64_to_cpu(iue->remote_token));
+
+ switch (rc) {
+ case H_SUCCESS:
+ vscsi->credit = 0;
+ *len_p = len;
+ break;
+ case H_PERMISSION:
+ if (connection_broken(vscsi))
+ vscsi->flags |= RESPONSE_Q_DOWN | CLIENT_FAILED;
+
+ dev_err(&vscsi->dev, "build_response: error copying to client, rc %ld, flags 0x%x, state 0x%hx\n",
+ rc, vscsi->flags, vscsi->state);
+ break;
+ case H_SOURCE_PARM:
+ case H_DEST_PARM:
+ default:
+ dev_err(&vscsi->dev, "build_response: error copying to client, rc %ld\n",
+ rc);
+ break;
+ }
+
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ return rc;
+}
+
+static int ibmvscsis_rdma(struct ibmvscsis_cmd *cmd, struct scatterlist *sg,
+ int nsg, struct srp_direct_buf *md, int nmd,
+ enum dma_data_direction dir, unsigned int bytes)
+{
+ struct iu_entry *iue = cmd->iue;
+ struct srp_target *target = iue->target;
+ struct scsi_info *vscsi = target->ldata;
+ struct scatterlist *sgp;
+ dma_addr_t client_ioba, server_ioba;
+ ulong buf_len;
+ ulong client_len, server_len;
+ int md_idx;
+ long tx_len;
+ long rc = 0;
+
+ pr_debug("rdma: dir %d, bytes 0x%x\n", dir, bytes);
+
+ if (bytes == 0)
+ return 0;
+
+ sgp = sg;
+ client_len = 0;
+ server_len = 0;
+ md_idx = 0;
+ tx_len = bytes;
+
+ do {
+ if (client_len == 0) {
+ if (md_idx >= nmd) {
+ dev_err(&vscsi->dev, "rdma: ran out of client memory descriptors\n");
+ rc = -EIO;
+ break;
+ }
+ client_ioba = be64_to_cpu(md[md_idx].va);
+ client_len = be32_to_cpu(md[md_idx].len);
+ }
+ if (server_len == 0) {
+ if (!sgp) {
+ dev_err(&vscsi->dev, "rdma: ran out of scatter/gather list\n");
+ rc = -EIO;
+ break;
+ }
+ server_ioba = sg_dma_address(sgp);
+ server_len = sg_dma_len(sgp);
+ }
+
+ buf_len = tx_len;
+
+ if (buf_len > client_len)
+ buf_len = client_len;
+
+ if (buf_len > server_len)
+ buf_len = server_len;
+
+ if (buf_len > max_vdma_size)
+ buf_len = max_vdma_size;
+
+ if (dir == DMA_TO_DEVICE) {
+ /* read from client */
+ rc = h_copy_rdma(buf_len,
+ vscsi->dds.window[REMOTE].liobn,
+ client_ioba,
+ vscsi->dds.window[LOCAL].liobn,
+ server_ioba);
+ } else {
+ /* write to client */
+ struct srp_cmd *srp = (struct srp_cmd *)iue->sbuf->buf;
+
+ if (!READ_CMD(srp->cdb))
+ print_hex_dump_bytes(" data:", DUMP_PREFIX_NONE,
+ sg_virt(sgp), buf_len);
+ /* The h_copy_rdma will cause phyp, running in another
+ * partition, to read memory, so we need to make sure
+ * the data has been written out, hence these syncs.
+ */
+ /* ensure that everything is in memory */
+ isync();
+ /* ensure that memory has been made visible */
+ dma_wmb();
+ rc = h_copy_rdma(buf_len,
+ vscsi->dds.window[LOCAL].liobn,
+ server_ioba,
+ vscsi->dds.window[REMOTE].liobn,
+ client_ioba);
+ }
+ switch (rc) {
+ case H_SUCCESS:
+ break;
+ case H_PERMISSION:
+ case H_SOURCE_PARM:
+ case H_DEST_PARM:
+ if (connection_broken(vscsi)) {
+ spin_lock_bh(&vscsi->intr_lock);
+ vscsi->flags |=
+ (RESPONSE_Q_DOWN | CLIENT_FAILED);
+ spin_unlock_bh(&vscsi->intr_lock);
+ }
+ dev_err(&vscsi->dev, "rdma: h_copy_rdma failed, rc %ld\n",
+ rc);
+ break;
+
+ default:
+ dev_err(&vscsi->dev, "rdma: unknown error %ld from h_copy_rdma\n",
+ rc);
+ break;
+ }
+
+ if (!rc) {
+ tx_len -= buf_len;
+ if (tx_len) {
+ client_len -= buf_len;
+ if (client_len == 0)
+ md_idx++;
+ else
+ client_ioba += buf_len;
+
+ server_len -= buf_len;
+ if (server_len == 0)
+ sgp = sg_next(sgp);
+ else
+ server_ioba += buf_len;
+ } else {
+ break;
+ }
+ }
+ } while (!rc);
+
+ return rc;
+}
+
+/**
+ * ibmvscsis_handle_crq() - Handle CRQ
+ * @data: Pointer to our adapter structure
+ *
+ * Read the command elements from the command queue and copy the payloads
+ * associated with the command elements to local memory and execute the
+ * SRP requests.
+ *
+ * Note: this is an edge triggered interrupt. It can not be shared.
+ */
+static void ibmvscsis_handle_crq(unsigned long data)
+{
+ struct scsi_info *vscsi = (struct scsi_info *)data;
+ struct viosrp_crq *crq;
+ long rc;
+ bool ack = true;
+ volatile u8 valid;
+
+ spin_lock_bh(&vscsi->intr_lock);
+
+ pr_debug("got interrupt\n");
+
+ /*
+ * if we are in a path where we are waiting for all pending commands
+ * to complete because we received a transport event and anything in
+ * the command queue is for a new connection, do nothing
+ */
+ if (TARGET_STOP(vscsi)) {
+ vio_enable_interrupts(vscsi->dma_dev);
+
+ pr_debug("handle_crq, don't process: flags 0x%x, state 0x%hx\n",
+ vscsi->flags, vscsi->state);
+ spin_unlock_bh(&vscsi->intr_lock);
+ return;
+ }
+
+ rc = vscsi->flags & SCHEDULE_DISCONNECT;
+ crq = vscsi->cmd_q.base_addr + vscsi->cmd_q.index;
+ valid = crq->valid;
+ dma_rmb();
+
+ while (valid) {
+ /*
+ * These are edege triggered interrupts. After dropping out of
+ * the while loop, the code must check for work since an
+ * interrupt could be lost, and an elment be left on the queue,
+ * hence the label.
+ */
+cmd_work:
+ vscsi->cmd_q.index =
+ (vscsi->cmd_q.index + 1) & vscsi->cmd_q.mask;
+
+ if (!rc) {
+ rc = ibmvscsis_parse_command(vscsi, crq);
+ } else {
+ if ((uint)crq->valid == VALID_TRANS_EVENT) {
+ /*
+ * must service the transport layer events even
+ * in an error state, dont break out until all
+ * the consecutive transport events have been
+ * processed
+ */
+ rc = ibmvscsis_trans_event(vscsi, crq);
+ } else if (vscsi->flags & TRANS_EVENT) {
+ /*
+ * if a tranport event has occurred leave
+ * everything but transport events on the queue
+ */
+ pr_debug("handle_crq, ignoring\n");
+
+ /*
+ * need to decrement the queue index so we can
+ * look at the elment again
+ */
+ if (vscsi->cmd_q.index)
+ vscsi->cmd_q.index -= 1;
+ else
+ /*
+ * index is at 0 it just wrapped.
+ * have it index last element in q
+ */
+ vscsi->cmd_q.index = vscsi->cmd_q.mask;
+ break;
+ }
+ }
+
+ crq->valid = INVALIDATE_CMD_RESP_EL;
+
+ crq = vscsi->cmd_q.base_addr + vscsi->cmd_q.index;
+ valid = crq->valid;
+ dma_rmb();
+ }
+
+ if (!rc) {
+ if (ack) {
+ vio_enable_interrupts(vscsi->dma_dev);
+ ack = false;
+ pr_debug("handle_crq, reenabling interrupts\n");
+ }
+ valid = crq->valid;
+ dma_rmb();
+ if (valid)
+ goto cmd_work;
+ } else {
+ pr_debug("handle_crq, error: flags 0x%x, state 0x%hx, crq index 0x%x\n",
+ vscsi->flags, vscsi->state, vscsi->cmd_q.index);
+ }
+
+ pr_debug("Leaving handle_crq: schedule_q empty %d, flags 0x%x, state 0x%hx\n",
+ (int)list_empty(&vscsi->schedule_q), vscsi->flags,
+ vscsi->state);
+
+ spin_unlock_bh(&vscsi->intr_lock);
+}
+
+static int ibmvscsis_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct scsi_info *vscsi;
+ int rc = 0;
+ long hrc = 0;
+ char wq_name[24];
+
+ vscsi = kzalloc(sizeof(*vscsi), GFP_KERNEL);
+ if (!vscsi) {
+ rc = -ENOMEM;
+ pr_err("probe: allocation of adapter failed\n");
+ return rc;
+ }
+
+ vscsi->dma_dev = vdev;
+ vscsi->dev = vdev->dev;
+ INIT_LIST_HEAD(&vscsi->schedule_q);
+ INIT_LIST_HEAD(&vscsi->waiting_rsp);
+ INIT_LIST_HEAD(&vscsi->active_q);
+
+ snprintf(vscsi->tport.tport_name, 256, "%s", dev_name(&vdev->dev));
+
+ pr_debug("probe tport_name: %s\n", vscsi->tport.tport_name);
+
+ rc = read_dma_window(vscsi);
+ if (rc)
+ goto free_adapter;
+ pr_debug("Probe: liobn 0x%x, riobn 0x%x\n",
+ vscsi->dds.window[LOCAL].liobn,
+ vscsi->dds.window[REMOTE].liobn);
+
+ strcpy(vscsi->eye, "VSCSI ");
+ strncat(vscsi->eye, vdev->name, MAX_EYE);
+
+ vscsi->dds.unit_id = vdev->unit_address;
+
+ spin_lock_bh(&ibmvscsis_dev_lock);
+ list_add_tail(&vscsi->list, &ibmvscsis_dev_list);
+ spin_unlock_bh(&ibmvscsis_dev_lock);
+
+ /*
+ * TBD: How do we determine # of cmds to request? Do we know how
+ * many "children" we have?
+ */
+ vscsi->request_limit = INITIAL_SRP_LIMIT;
+ rc = srp_target_alloc(&vscsi->target, &vdev->dev, vscsi->request_limit,
+ SRP_MAX_IU_LEN);
+ if (rc)
+ goto rem_list;
+
+ vscsi->target.ldata = vscsi;
+
+ rc = ibmvscsis_alloc_cmds(vscsi, vscsi->request_limit);
+ if (rc) {
+ dev_err(&vscsi->dev, "alloc_cmds failed, rc %d, num %d\n",
+ rc, vscsi->request_limit);
+ goto free_target;
+ }
+
+ /*
+ * Note: the lock is used in freeing timers, so must initialize
+ * first so that ordering in case of error is correct.
+ */
+ spin_lock_init(&vscsi->intr_lock);
+
+ rc = ibmvscsis_alloctimer(vscsi);
+ if (rc) {
+ dev_err(&vscsi->dev, "probe: alloctimer failed, rc %d\n", rc);
+ goto free_cmds;
+ }
+
+ rc = ibmvscsis_create_command_q(vscsi, 256);
+ if (rc) {
+ dev_err(&vscsi->dev, "probe: create_command_q failed, rc %d\n",
+ rc);
+ goto free_timer;
+ }
+
+ vscsi->map_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!vscsi->map_buf) {
+ rc = -ENOMEM;
+ dev_err(&vscsi->dev, "probe: allocating cmd buffer failed\n");
+ goto destroy_queue;
+ }
+
+ vscsi->map_ioba = dma_map_single(&vdev->dev, vscsi->map_buf, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(&vdev->dev, vscsi->map_ioba)) {
+ dev_err(&vscsi->dev, "probe: error mapping command buffer\n");
+ goto free_buf;
+ }
+
+ hrc = h_vioctl(vscsi->dds.unit_id, H_GET_PARTNER_INFO,
+ (u64)vscsi->map_ioba | ((u64)PAGE_SIZE << 32), 0, 0, 0,
+ 0);
+ if (hrc == H_SUCCESS)
+ vscsi->client_data.partition_number =
+ be64_to_cpu(*(u64 *)vscsi->map_buf);
+ /*
+ * We expect the VIOCTL to fail if we're configured as "any
+ * client can connect" and the client isn't activated yet.
+ * We'll make the call again when he sends an init msg.
+ */
+ pr_debug("probe hrc %ld, client partition num %d\n",
+ hrc, vscsi->client_data.partition_number);
+
+ tasklet_init(&vscsi->work_task, ibmvscsis_handle_crq,
+ (unsigned long)vscsi);
+
+ init_completion(&vscsi->wait_idle);
+
+ snprintf(wq_name, 24, "ibmvscsis%s", dev_name(&vdev->dev));
+ vscsi->work_q = create_workqueue(wq_name);
+ if (!vscsi->work_q) {
+ rc = -ENOMEM;
+ dev_err(&vscsi->dev, "create_workqueue failed\n");
+ goto unmap_buf;
+ }
+
+ rc = request_irq(vdev->irq, ibmvscsis_interrupt, 0, "ibmvscsis", vscsi);
+ if (rc) {
+ rc = -EPERM;
+ dev_err(&vscsi->dev, "probe: request_irq failed, rc %d\n", rc);
+ goto destroy_WQ;
+ }
+
+ spin_lock_bh(&vscsi->intr_lock);
+ vio_enable_interrupts(vdev);
+ if (rc) {
+ dev_err(&vscsi->dev, "enabling interrupts failed, rc %d\n", rc);
+ rc = -ENODEV;
+ spin_unlock_bh(&vscsi->intr_lock);
+ goto free_irq;
+ }
+
+ if (ibmvscsis_check_q(vscsi)) {
+ rc = ERROR;
+ dev_err(&vscsi->dev, "probe: check_q failed, rc %d\n", rc);
+ spin_unlock_bh(&vscsi->intr_lock);
+ goto disable_interrupt;
+ }
+ spin_unlock_bh(&vscsi->intr_lock);
+
+ dev_set_drvdata(&vdev->dev, vscsi);
+
+ return 0;
+
+disable_interrupt:
+ vio_disable_interrupts(vdev);
+free_irq:
+ free_irq(vdev->irq, vscsi);
+destroy_WQ:
+ destroy_workqueue(vscsi->work_q);
+unmap_buf:
+ dma_unmap_single(&vdev->dev, vscsi->map_ioba, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+free_buf:
+ kfree(vscsi->map_buf);
+destroy_queue:
+ tasklet_kill(&vscsi->work_task);
+ ibmvscsis_unregister_command_q(vscsi);
+ ibmvscsis_destroy_command_q(vscsi);
+free_timer:
+ ibmvscsis_freetimer(vscsi);
+free_cmds:
+ ibmvscsis_free_cmds(vscsi);
+free_target:
+ srp_target_free(&vscsi->target);
+rem_list:
+ spin_lock_bh(&ibmvscsis_dev_lock);
+ list_del(&vscsi->list);
+ spin_unlock_bh(&ibmvscsis_dev_lock);
+free_adapter:
+ kfree(vscsi);
+
+ return rc;
+}
+
+static int ibmvscsis_remove(struct vio_dev *vdev)
+{
+ struct scsi_info *vscsi = dev_get_drvdata(&vdev->dev);
+
+ pr_debug("remove (%s)\n", dev_name(&vscsi->dma_dev->dev));
+
+ /*
+ * TBD: Need to handle if there are commands on the waiting_rsp q
+ * Actually, can there still be cmds outstanding to tcm?
+ */
+
+ vio_disable_interrupts(vdev);
+ free_irq(vdev->irq, vscsi);
+ destroy_workqueue(vscsi->work_q);
+ dma_unmap_single(&vdev->dev, vscsi->map_ioba, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+ kfree(vscsi->map_buf);
+ tasklet_kill(&vscsi->work_task);
+ ibmvscsis_unregister_command_q(vscsi);
+ ibmvscsis_destroy_command_q(vscsi);
+ ibmvscsis_freetimer(vscsi);
+ ibmvscsis_free_cmds(vscsi);
+ srp_target_free(&vscsi->target);
+ spin_lock_bh(&ibmvscsis_dev_lock);
+ list_del(&vscsi->list);
+ spin_unlock_bh(&ibmvscsis_dev_lock);
+ kfree(vscsi);
+
+ return 0;
+}
+
+static ssize_t system_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
+}
+
+static ssize_t partition_number_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
+}
+
+static ssize_t unit_address_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct scsi_info *vscsi = container_of(dev, struct scsi_info, dev);
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", vscsi->dma_dev->unit_address);
+}
+
+static int ibmvscsis_get_system_info(void)
+{
+ struct device_node *rootdn, *vdevdn;
+ const char *id, *model, *name;
+ const uint *num;
+
+ rootdn = of_find_node_by_path("/");
+ if (!rootdn)
+ return -ENOENT;
+
+ model = of_get_property(rootdn, "model", NULL);
+ id = of_get_property(rootdn, "system-id", NULL);
+ if (model && id)
+ snprintf(system_id, sizeof(system_id), "%s-%s", model, id);
+
+ name = of_get_property(rootdn, "ibm,partition-name", NULL);
+ if (name)
+ strncpy(partition_name, name, sizeof(partition_name));
+
+ num = of_get_property(rootdn, "ibm,partition-no", NULL);
+ if (num)
+ partition_number = *num;
+
+ of_node_put(rootdn);
+
+ vdevdn = of_find_node_by_path("/vdevice");
+ if (vdevdn) {
+ const uint *mvds;
+
+ mvds = of_get_property(vdevdn, "ibm,max-virtual-dma-size",
+ NULL);
+ if (mvds)
+ max_vdma_size = *mvds;
+ of_node_put(vdevdn);
+ }
+
+ return 0;
+}
+
+static char *ibmvscsis_get_fabric_name(void)
+{
+ return "ibmvscsis";
+}
+
+static char *ibmvscsis_get_fabric_wwn(struct se_portal_group *se_tpg)
+{
+ struct ibmvscsis_tport *tport =
+ container_of(se_tpg, struct ibmvscsis_tport, se_tpg);
+
+ return tport->tport_name;
+}
+
+static u16 ibmvscsis_get_tag(struct se_portal_group *se_tpg)
+{
+ struct ibmvscsis_tport *tport =
+ container_of(se_tpg, struct ibmvscsis_tport, se_tpg);
+
+ return tport->tport_tpgt;
+}
+
+static u32 ibmvscsis_get_default_depth(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int ibmvscsis_check_true(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int ibmvscsis_check_false(struct se_portal_group *se_tpg)
+{
+ return 0;
+}
+
+static u32 ibmvscsis_tpg_get_inst_index(struct se_portal_group *se_tpg)
+{
+ return 1;
+}
+
+static int ibmvscsis_check_stop_free(struct se_cmd *se_cmd)
+{
+ return target_put_sess_cmd(se_cmd);
+}
+
+static void ibmvscsis_release_cmd(struct se_cmd *se_cmd)
+{
+ struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
+ se_cmd);
+ struct scsi_info *vscsi = cmd->adapter;
+
+ pr_debug("release_cmd %p, flags %d\n", se_cmd, cmd->flags);
+
+ spin_lock_bh(&vscsi->intr_lock);
+ /* Remove from active_q */
+ list_del(&cmd->list);
+ list_add_tail(&cmd->list, &vscsi->waiting_rsp);
+ ibmvscsis_send_messages(vscsi);
+ spin_unlock_bh(&vscsi->intr_lock);
+}
+
+static u32 ibmvscsis_sess_get_index(struct se_session *se_sess)
+{
+ return 0;
+}
+
+static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
+{
+ struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
+ se_cmd);
+ struct iu_entry *iue = cmd->iue;
+ int rc;
+
+ pr_debug("write_pending, se_cmd %p, length 0x%x\n",
+ se_cmd, se_cmd->data_length);
+
+ rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma,
+ 1, 1);
+ if (rc) {
+ pr_err("srp_transfer_data() failed: %d\n", rc);
+ return -EAGAIN;
+ }
+ /*
+ * We now tell TCM to add this WRITE CDB directly into the TCM storage
+ * object execution queue.
+ */
+ target_execute_cmd(se_cmd);
+ return 0;
+}
+
+static int ibmvscsis_write_pending_status(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static void ibmvscsis_set_default_node_attrs(struct se_node_acl *nacl)
+{
+}
+
+static int ibmvscsis_get_cmd_state(struct se_cmd *se_cmd)
+{
+ return 0;
+}
+
+static int ibmvscsis_queue_data_in(struct se_cmd *se_cmd)
+{
+ struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
+ se_cmd);
+ struct iu_entry *iue = cmd->iue;
+ struct scsi_info *vscsi = cmd->adapter;
+ char *sd;
+ uint len = 0;
+ int rc;
+
+ pr_debug("queue_data_in, se_cmd %p, length 0x%x\n",
+ se_cmd, se_cmd->data_length);
+
+ rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, 1,
+ 1);
+ if (rc) {
+ pr_err("srp_transfer_data failed: %d\n", rc);
+ sd = se_cmd->sense_buffer;
+ se_cmd->scsi_sense_length = 18;
+ memset(se_cmd->sense_buffer, 0, se_cmd->scsi_sense_length);
+ /* Logical Unit Communication Time-out asc/ascq = 0x0801 */
+ scsi_build_sense_buffer(0, se_cmd->sense_buffer, MEDIUM_ERROR,
+ 0x08, 0x01);
+ }
+
+ srp_build_response(vscsi, cmd, &len);
+ cmd->rsp.format = SRP_FORMAT;
+ cmd->rsp.len = len;
+
+ return 0;
+}
+
+static int ibmvscsis_queue_status(struct se_cmd *se_cmd)
+{
+ struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
+ se_cmd);
+ struct scsi_info *vscsi = cmd->adapter;
+ uint len;
+
+ pr_debug("queue_status %p\n", se_cmd);
+
+ srp_build_response(vscsi, cmd, &len);
+ cmd->rsp.format = SRP_FORMAT;
+ cmd->rsp.len = len;
+
+ return 0;
+}
+
+static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd)
+{
+ struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
+ se_cmd);
+ struct scsi_info *vscsi = cmd->adapter;
+ uint len;
+
+ pr_debug("queue_tm_rsp %p, status %d\n",
+ se_cmd, (int)se_cmd->se_tmr_req->response);
+
+ srp_build_response(vscsi, cmd, &len);
+ cmd->rsp.format = SRP_FORMAT;
+ cmd->rsp.len = len;
+}
+
+static void ibmvscsis_aborted_task(struct se_cmd *se_cmd)
+{
+ /* TBD: What (if anything) should we do here? */
+ pr_debug("ibmvscsis_aborted_task %p\n", se_cmd);
+}
+
+static struct se_wwn *ibmvscsis_make_tport(struct target_fabric_configfs *tf,
+ struct config_group *group,
+ const char *name)
+{
+ struct ibmvscsis_tport *tport;
+
+ tport = ibmvscsis_lookup_port(name);
+ if (tport) {
+ tport->tport_proto_id = SCSI_PROTOCOL_SRP;
+ pr_debug("make_tport(%s), pointer:%p, tport_id:%x\n",
+ name, tport, tport->tport_proto_id);
+ return &tport->tport_wwn;
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+static void ibmvscsis_drop_tport(struct se_wwn *wwn)
+{
+ struct ibmvscsis_tport *tport = container_of(wwn,
+ struct ibmvscsis_tport,
+ tport_wwn);
+
+ pr_debug("drop_tport(%s)\n",
+ config_item_name(&tport->tport_wwn.wwn_group.cg_item));
+}
+
+static struct se_portal_group *ibmvscsis_make_tpg(struct se_wwn *wwn,
+ struct config_group *group,
+ const char *name)
+{
+ struct ibmvscsis_tport *tport =
+ container_of(wwn, struct ibmvscsis_tport, tport_wwn);
+ int rc;
+
+ tport->releasing = false;
+
+ rc = core_tpg_register(&tport->tport_wwn, &tport->se_tpg,
+ tport->tport_proto_id);
+ if (rc)
+ return ERR_PTR(rc);
+
+ return &tport->se_tpg;
+}
+
+static void ibmvscsis_drop_tpg(struct se_portal_group *se_tpg)
+{
+ struct ibmvscsis_tport *tport = container_of(se_tpg,
+ struct ibmvscsis_tport,
+ se_tpg);
+
+ tport->releasing = true;
+ tport->enabled = false;
+
+ /*
+ * Release the virtual I_T Nexus for this ibmvscsis TPG
+ */
+ ibmvscsis_drop_nexus(tport);
+ /*
+ * Deregister the se_tpg from TCM..
+ */
+ core_tpg_deregister(se_tpg);
+}
+
+static ssize_t ibmvscsis_wwn_version_show(struct config_item *item,
+ char *page)
+{
+ return scnprintf(page, PAGE_SIZE, "%s\n", IBMVSCSIS_VERSION);
+}
+CONFIGFS_ATTR_RO(ibmvscsis_wwn_, version);
+
+static struct configfs_attribute *ibmvscsis_wwn_attrs[] = {
+ &ibmvscsis_wwn_attr_version,
+ NULL,
+};
+
+static ssize_t ibmvscsis_tpg_enable_show(struct config_item *item,
+ char *page)
+{
+ struct se_portal_group *se_tpg = to_tpg(item);
+ struct ibmvscsis_tport *tport = container_of(se_tpg,
+ struct ibmvscsis_tport,
+ se_tpg);
+
+ return snprintf(page, PAGE_SIZE, "%d\n", (tport->enabled) ? 1 : 0);
+}
+
+static ssize_t ibmvscsis_tpg_enable_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct se_portal_group *se_tpg = to_tpg(item);
+ struct ibmvscsis_tport *tport = container_of(se_tpg,
+ struct ibmvscsis_tport,
+ se_tpg);
+ struct scsi_info *vscsi = container_of(tport, struct scsi_info, tport);
+ unsigned long tmp;
+ int rc;
+ long lrc;
+
+ rc = kstrtoul(page, 0, &tmp);
+ if (rc < 0) {
+ pr_err("Unable to extract srpt_tpg_store_enable\n");
+ return -EINVAL;
+ }
+
+ if ((tmp != 0) && (tmp != 1)) {
+ pr_err("Illegal value for srpt_tpg_store_enable\n");
+ return -EINVAL;
+ }
+
+ if (tmp) {
+ tport->enabled = true;
+ spin_lock_bh(&vscsi->intr_lock);
+ lrc = ibmvscsis_enable_change_state(vscsi);
+ if (lrc)
+ pr_err("enable_change_state failed, rc %ld state %d\n",
+ lrc, vscsi->state);
+ spin_unlock_bh(&vscsi->intr_lock);
+ } else {
+ tport->enabled = false;
+ }
+
+ pr_debug("tpg_enable_store, state %d\n", vscsi->state);
+
+ return count;
+}
+CONFIGFS_ATTR(ibmvscsis_tpg_, enable);
+
+static struct configfs_attribute *ibmvscsis_tpg_attrs[] = {
+ &ibmvscsis_tpg_attr_enable,
+ NULL,
+};
+
+static const struct target_core_fabric_ops ibmvscsis_ops = {
+ .module = THIS_MODULE,
+ .name = "ibmvscsis",
+ .get_fabric_name = ibmvscsis_get_fabric_name,
+ .tpg_get_wwn = ibmvscsis_get_fabric_wwn,
+ .tpg_get_tag = ibmvscsis_get_tag,
+ .tpg_get_default_depth = ibmvscsis_get_default_depth,
+ .tpg_check_demo_mode = ibmvscsis_check_true,
+ .tpg_check_demo_mode_cache = ibmvscsis_check_true,
+ .tpg_check_demo_mode_write_protect = ibmvscsis_check_false,
+ .tpg_check_prod_mode_write_protect = ibmvscsis_check_false,
+ .tpg_get_inst_index = ibmvscsis_tpg_get_inst_index,
+ .check_stop_free = ibmvscsis_check_stop_free,
+ .release_cmd = ibmvscsis_release_cmd,
+ .sess_get_index = ibmvscsis_sess_get_index,
+ .write_pending = ibmvscsis_write_pending,
+ .write_pending_status = ibmvscsis_write_pending_status,
+ .set_default_node_attributes = ibmvscsis_set_default_node_attrs,
+ .get_cmd_state = ibmvscsis_get_cmd_state,
+ .queue_data_in = ibmvscsis_queue_data_in,
+ .queue_status = ibmvscsis_queue_status,
+ .queue_tm_rsp = ibmvscsis_queue_tm_rsp,
+ .aborted_task = ibmvscsis_aborted_task,
+ /*
+ * Setup function pointers for logic in target_core_fabric_configfs.c
+ */
+ .fabric_make_wwn = ibmvscsis_make_tport,
+ .fabric_drop_wwn = ibmvscsis_drop_tport,
+ .fabric_make_tpg = ibmvscsis_make_tpg,
+ .fabric_drop_tpg = ibmvscsis_drop_tpg,
+
+ .tfc_wwn_attrs = ibmvscsis_wwn_attrs,
+ .tfc_tpg_base_attrs = ibmvscsis_tpg_attrs,
+};
+
+static void ibmvscsis_dev_release(struct device *dev) {};
+
+static struct class_attribute ibmvscsis_class_attrs[] = {
+ __ATTR_NULL,
+};
+
+static struct device_attribute dev_attr_system_id =
+ __ATTR(system_id, S_IRUGO, system_id_show, NULL);
+
+static struct device_attribute dev_attr_partition_number =
+ __ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
+
+static struct device_attribute dev_attr_unit_address =
+ __ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
+
+static struct attribute *ibmvscsis_dev_attrs[] = {
+ &dev_attr_system_id.attr,
+ &dev_attr_partition_number.attr,
+ &dev_attr_unit_address.attr,
+};
+ATTRIBUTE_GROUPS(ibmvscsis_dev);
+
+static struct class ibmvscsis_class = {
+ .name = "ibmvscsis",
+ .dev_release = ibmvscsis_dev_release,
+ .class_attrs = ibmvscsis_class_attrs,
+ .dev_groups = ibmvscsis_dev_groups,
+};
+
+static struct vio_device_id ibmvscsis_device_table[] = {
+ { "v-scsi-host", "IBM,v-scsi-host" },
+ { "", "" }
+};
+MODULE_DEVICE_TABLE(vio, ibmvscsis_device_table);
+
+static struct vio_driver ibmvscsis_driver = {
+ .name = "ibmvscsis",
+ .id_table = ibmvscsis_device_table,
+ .probe = ibmvscsis_probe,
+ .remove = ibmvscsis_remove,
+};
+
+/*
+ * ibmvscsis_init() - Kernel Module initialization
+ *
+ * Note: vio_register_driver() registers callback functions, and at least one
+ * of those callback functions calls TCM - Linux IO Target Subsystem, thus
+ * the SCSI Target template must be registered before vio_register_driver()
+ * is called.
+ */
+static int __init ibmvscsis_init(void)
+{
+ int rc = 0;
+
+ rc = ibmvscsis_get_system_info();
+ if (rc) {
+ pr_err("rc %d from get_system_info\n", rc);
+ goto out;
+ }
+
+ rc = class_register(&ibmvscsis_class);
+ if (rc) {
+ pr_err("failed class register\n");
+ goto out;
+ }
+
+ rc = target_register_template(&ibmvscsis_ops);
+ if (rc) {
+ pr_err("rc %d from target_register_template\n", rc);
+ goto unregister_class;
+ }
+
+ rc = vio_register_driver(&ibmvscsis_driver);
+ if (rc) {
+ pr_err("rc %d from vio_register_driver\n", rc);
+ goto unregister_target;
+ }
+
+ return 0;
+
+unregister_target:
+ target_unregister_template(&ibmvscsis_ops);
+unregister_class:
+ class_unregister(&ibmvscsis_class);
+out:
+ return rc;
+}
+
+static void __exit ibmvscsis_exit(void)
+{
+ pr_info("Unregister IBM virtual SCSI host driver\n");
+ vio_unregister_driver(&ibmvscsis_driver);
+ target_unregister_template(&ibmvscsis_ops);
+ class_unregister(&ibmvscsis_class);
+}
+
+MODULE_DESCRIPTION("IBMVSCSIS fabric driver");
+MODULE_AUTHOR("Bryant G. Ly and Michael Cyr");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(IBMVSCSIS_VERSION);
+module_init(ibmvscsis_init);
+module_exit(ibmvscsis_exit);
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
new file mode 100644
index 000000000000..981a0c992b6c
--- /dev/null
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * IBM Virtual SCSI Target Driver
+ * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp.
+ * Santiago Leon (santil@us.ibm.com) IBM Corp.
+ * Linda Xie (lxie@us.ibm.com) IBM Corp.
+ *
+ * Copyright (C) 2005-2011 FUJITA Tomonori <tomof@acm.org>
+ * Copyright (C) 2010 Nicholas A. Bellinger <nab@kernel.org>
+ * Copyright (C) 2016 Bryant G. Ly <bryantly@linux.vnet.ibm.com> IBM Corp.
+ *
+ * Authors: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+ * Authors: Michael Cyr <mikecyr@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ ****************************************************************************/
+
+#ifndef __H_IBMVSCSI_TGT
+#define __H_IBMVSCSI_TGT
+
+#include "libsrp.h"
+
+#define SYS_ID_NAME_LEN 64
+#define PARTITION_NAMELEN 96
+#define IBMVSCSIS_NAMELEN 32
+
+#define MSG_HI 0
+#define MSG_LOW 1
+
+#define MAX_CMD_Q_PAGES 4
+#define CRQ_PER_PAGE (PAGE_SIZE / sizeof(struct viosrp_crq))
+/* in terms of number of elements */
+#define DEFAULT_CMD_Q_SIZE CRQ_PER_PAGE
+#define MAX_CMD_Q_SIZE (DEFAULT_CMD_Q_SIZE * MAX_CMD_Q_PAGES)
+
+#define SRP_VIOLATION 0x102 /* general error code */
+
+/*
+ * SRP buffer formats defined as of 16.a supported by this driver.
+ */
+#define SUPPORTED_FORMATS ((SRP_DATA_DESC_DIRECT << 1) | \
+ (SRP_DATA_DESC_INDIRECT << 1))
+
+#define SCSI_LUN_ADDR_METHOD_FLAT 1
+
+struct dma_window {
+ u32 liobn; /* Unique per vdevice */
+ u64 tce_base; /* Physical location of the TCE table */
+ u64 tce_size; /* Size of the TCE table in bytes */
+};
+
+struct target_dds {
+ u64 unit_id; /* 64 bit will force alignment */
+#define NUM_DMA_WINDOWS 2
+#define LOCAL 0
+#define REMOTE 1
+ struct dma_window window[NUM_DMA_WINDOWS];
+
+ /* root node property "ibm,partition-no" */
+ uint partition_num;
+ char partition_name[PARTITION_NAMELEN];
+};
+
+#define MAX_NUM_PORTS 1
+#define MAX_H_COPY_RDMA (128 * 1024)
+
+#define MAX_EYE 64
+
+/* Return codes */
+#define ADAPT_SUCCESS 0L
+/* choose error codes that do not conflict with PHYP */
+#define ERROR -40L
+
+struct format_code {
+ u8 reserved;
+ u8 buffers;
+};
+
+struct client_info {
+#define SRP_VERSION "16.a"
+ char srp_version[8];
+ /* root node property ibm,partition-name */
+ char partition_name[PARTITION_NAMELEN];
+ /* root node property ibm,partition-no */
+ u32 partition_number;
+ /* initially 1 */
+ u32 mad_version;
+ u32 os_type;
+};
+
+/*
+ * Changing this constant changes the number of seconds to wait before
+ * considering the client will never service its queue again.
+ */
+#define SECONDS_TO_CONSIDER_FAILED 30
+/*
+ * These constants set the polling period used to determine if the client
+ * has freed at least one element in the response queue.
+ */
+#define WAIT_SECONDS 1
+#define WAIT_NANO_SECONDS 5000
+#define MAX_TIMER_POPS ((1000000 / WAIT_NANO_SECONDS) * \
+ SECONDS_TO_CONSIDER_FAILED)
+/*
+ * general purpose timer control block
+ * which can be used for multiple functions
+ */
+struct timer_cb {
+ struct hrtimer timer;
+ /*
+ * how long has it been since the client
+ * serviced the queue. The variable is incrmented
+ * in the service_wait_q routine and cleared
+ * in send messages
+ */
+ int timer_pops;
+ /* the timer is started */
+ bool started;
+};
+
+struct cmd_queue {
+ /* kva */
+ struct viosrp_crq *base_addr;
+ dma_addr_t crq_token;
+ /* used to maintain index */
+ uint mask;
+ /* current element */
+ uint index;
+ int size;
+};
+
+#define SCSOLNT_RESP_SHIFT 1
+#define UCSOLNT_RESP_SHIFT 2
+
+#define SCSOLNT BIT(SCSOLNT_RESP_SHIFT)
+#define UCSOLNT BIT(UCSOLNT_RESP_SHIFT)
+
+enum cmd_type {
+ SCSI_CDB = 0x01,
+ TASK_MANAGEMENT = 0x02,
+ /* MAD or addressed to port 0 */
+ ADAPTER_MAD = 0x04,
+ UNSET_TYPE = 0x08,
+};
+
+struct iu_rsp {
+ u8 format;
+ u8 sol_not;
+ u16 len;
+ /* tag is just to help client identify cmd, so don't translate be/le */
+ u64 tag;
+};
+
+struct ibmvscsis_cmd {
+ struct list_head list;
+ /* Used for TCM Core operations */
+ struct se_cmd se_cmd;
+ struct iu_entry *iue;
+ struct iu_rsp rsp;
+ struct work_struct work;
+ struct scsi_info *adapter;
+ /* Sense buffer that will be mapped into outgoing status */
+ unsigned char sense_buf[TRANSPORT_SENSE_BUFFER];
+ u64 init_time;
+#define CMD_FAST_FAIL BIT(0)
+ u32 flags;
+ char type;
+};
+
+struct ibmvscsis_nexus {
+ struct se_session *se_sess;
+};
+
+struct ibmvscsis_tport {
+ /* SCSI protocol the tport is providing */
+ u8 tport_proto_id;
+ /* ASCII formatted WWPN for SRP Target port */
+ char tport_name[IBMVSCSIS_NAMELEN];
+ /* Returned by ibmvscsis_make_tport() */
+ struct se_wwn tport_wwn;
+ /* Returned by ibmvscsis_make_tpg() */
+ struct se_portal_group se_tpg;
+ /* ibmvscsis port target portal group tag for TCM */
+ u16 tport_tpgt;
+ /* Pointer to TCM session for I_T Nexus */
+ struct ibmvscsis_nexus *ibmv_nexus;
+ bool enabled;
+ bool releasing;
+};
+
+struct scsi_info {
+ struct list_head list;
+ char eye[MAX_EYE];
+
+ /* commands waiting for space on repsonse queue */
+ struct list_head waiting_rsp;
+#define NO_QUEUE 0x00
+#define WAIT_ENABLED 0X01
+ /* driver has received an initialize command */
+#define PART_UP_WAIT_ENAB 0x02
+#define WAIT_CONNECTION 0x04
+ /* have established a connection */
+#define CONNECTED 0x08
+ /* at least one port is processing SRP IU */
+#define SRP_PROCESSING 0x10
+ /* remove request received */
+#define UNCONFIGURING 0x20
+ /* disconnect by letting adapter go idle, no error */
+#define WAIT_IDLE 0x40
+ /* disconnecting to clear an error */
+#define ERR_DISCONNECT 0x80
+ /* disconnect to clear error state, then come back up */
+#define ERR_DISCONNECT_RECONNECT 0x100
+ /* disconnected after clearing an error */
+#define ERR_DISCONNECTED 0x200
+ /* A series of errors caused unexpected errors */
+#define UNDEFINED 0x400
+ u16 state;
+ int fast_fail;
+ struct target_dds dds;
+ char *cmd_pool;
+ /* list of free commands */
+ struct list_head free_cmd;
+ /* command elements ready for scheduler */
+ struct list_head schedule_q;
+ /* commands sent to TCM */
+ struct list_head active_q;
+ caddr_t *map_buf;
+ /* ioba of map buffer */
+ dma_addr_t map_ioba;
+ /* allowable number of outstanding SRP requests */
+ int request_limit;
+ /* extra credit */
+ int credit;
+ /* outstanding transactions against credit limit */
+ int debit;
+
+ /* allow only one outstanding mad request */
+#define PROCESSING_MAD 0x00002
+ /* Waiting to go idle */
+#define WAIT_FOR_IDLE 0x00004
+ /* H_REG_CRQ called */
+#define CRQ_CLOSED 0x00010
+ /* detected that client has failed */
+#define CLIENT_FAILED 0x00040
+ /* detected that transport event occurred */
+#define TRANS_EVENT 0x00080
+ /* don't attempt to send anything to the client */
+#define RESPONSE_Q_DOWN 0x00100
+ /* request made to schedule disconnect handler */
+#define SCHEDULE_DISCONNECT 0x00400
+ /* disconnect handler is scheduled */
+#define DISCONNECT_SCHEDULED 0x00800
+ u32 flags;
+ /* adapter lock */
+ spinlock_t intr_lock;
+ /* information needed to manage command queue */
+ struct cmd_queue cmd_q;
+ /* used in hcall to copy response back into srp buffer */
+ u64 empty_iu_id;
+ /* used in crq, to tag what iu the response is for */
+ u64 empty_iu_tag;
+ uint new_state;
+ /* control block for the response queue timer */
+ struct timer_cb rsp_q_timer;
+ /* keep last client to enable proper accounting */
+ struct client_info client_data;
+ /* what can this client do */
+ u32 client_cap;
+ /*
+ * The following two fields capture state and flag changes that
+ * can occur when the lock is given up. In the orginal design,
+ * the lock was held during calls into phyp;
+ * however, phyp did not meet PAPR architecture. This is
+ * a work around.
+ */
+ u16 phyp_acr_state;
+ u32 phyp_acr_flags;
+
+ struct workqueue_struct *work_q;
+ struct completion wait_idle;
+ struct device dev;
+ struct vio_dev *dma_dev;
+ struct srp_target target;
+ struct ibmvscsis_tport tport;
+ struct tasklet_struct work_task;
+ struct work_struct proc_work;
+};
+
+/*
+ * Provide a constant that allows software to detect the adapter is
+ * disconnecting from the client from one of several states.
+ */
+#define IS_DISCONNECTING (UNCONFIGURING | ERR_DISCONNECT_RECONNECT | \
+ ERR_DISCONNECT)
+
+/*
+ * Provide a constant that can be used with interrupt handling that
+ * essentially lets the interrupt handler know that all requests should
+ * be thrown out,
+ */
+#define DONT_PROCESS_STATE (IS_DISCONNECTING | UNDEFINED | \
+ ERR_DISCONNECTED | WAIT_IDLE)
+
+/*
+ * If any of these flag bits are set then do not allow the interrupt
+ * handler to schedule the off level handler.
+ */
+#define BLOCK (DISCONNECT_SCHEDULED)
+
+/* State and transition events that stop the interrupt handler */
+#define TARGET_STOP(VSCSI) (long)(((VSCSI)->state & DONT_PROCESS_STATE) | \
+ ((VSCSI)->flags & BLOCK))
+
+/* flag bit that are not reset during disconnect */
+#define PRESERVE_FLAG_FIELDS 0
+
+#define vio_iu(IUE) ((union viosrp_iu *)((IUE)->sbuf->buf))
+
+#define READ_CMD(cdb) (((cdb)[0] & 0x1F) == 8)
+#define WRITE_CMD(cdb) (((cdb)[0] & 0x1F) == 0xA)
+
+#ifndef H_GET_PARTNER_INFO
+#define H_GET_PARTNER_INFO 0x0000000000000008LL
+#endif
+
+#define h_copy_rdma(l, sa, sb, da, db) \
+ plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db)
+#define h_vioctl(u, o, a, u1, u2, u3, u4) \
+ plpar_hcall_norets(H_VIOCTL, u, o, a, u1, u2)
+#define h_reg_crq(ua, tok, sz) \
+ plpar_hcall_norets(H_REG_CRQ, ua, tok, sz)
+#define h_free_crq(ua) \
+ plpar_hcall_norets(H_FREE_CRQ, ua)
+#define h_send_crq(ua, d1, d2) \
+ plpar_hcall_norets(H_SEND_CRQ, ua, d1, d2)
+
+#endif
diff --git a/drivers/scsi/ibmvscsi_tgt/libsrp.c b/drivers/scsi/ibmvscsi_tgt/libsrp.c
new file mode 100644
index 000000000000..5a4cc28ca5ff
--- /dev/null
+++ b/drivers/scsi/ibmvscsi_tgt/libsrp.c
@@ -0,0 +1,427 @@
+/*******************************************************************************
+ * SCSI RDMA Protocol lib functions
+ *
+ * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org>
+ * Copyright (C) 2016 Bryant G. Ly <bryantly@linux.vnet.ibm.com> IBM Corp.
+ *
+ * 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.
+ *
+ ***********************************************************************/
+
+#define pr_fmt(fmt) "libsrp: " fmt
+
+#include <linux/printk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <scsi/srp.h>
+#include <target/target_core_base.h>
+#include "libsrp.h"
+#include "ibmvscsi_tgt.h"
+
+static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
+ struct srp_buf **ring)
+{
+ struct iu_entry *iue;
+ int i;
+
+ q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL);
+ if (!q->pool)
+ return -ENOMEM;
+ q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL);
+ if (!q->items)
+ goto free_pool;
+
+ spin_lock_init(&q->lock);
+ kfifo_init(&q->queue, (void *)q->pool, max * sizeof(void *));
+
+ for (i = 0, iue = q->items; i < max; i++) {
+ kfifo_in(&q->queue, (void *)&iue, sizeof(void *));
+ iue->sbuf = ring[i];
+ iue++;
+ }
+ return 0;
+
+free_pool:
+ kfree(q->pool);
+ return -ENOMEM;
+}
+
+static void srp_iu_pool_free(struct srp_queue *q)
+{
+ kfree(q->items);
+ kfree(q->pool);
+}
+
+static struct srp_buf **srp_ring_alloc(struct device *dev,
+ size_t max, size_t size)
+{
+ struct srp_buf **ring;
+ int i;
+
+ ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL);
+ if (!ring)
+ return NULL;
+
+ for (i = 0; i < max; i++) {
+ ring[i] = kzalloc(sizeof(*ring[i]), GFP_KERNEL);
+ if (!ring[i])
+ goto out;
+ ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma,
+ GFP_KERNEL);
+ if (!ring[i]->buf)
+ goto out;
+ }
+ return ring;
+
+out:
+ for (i = 0; i < max && ring[i]; i++) {
+ if (ring[i]->buf) {
+ dma_free_coherent(dev, size, ring[i]->buf,
+ ring[i]->dma);
+ }
+ kfree(ring[i]);
+ }
+ kfree(ring);
+
+ return NULL;
+}
+
+static void srp_ring_free(struct device *dev, struct srp_buf **ring,
+ size_t max, size_t size)
+{
+ int i;
+
+ for (i = 0; i < max; i++) {
+ dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
+ kfree(ring[i]);
+ }
+ kfree(ring);
+}
+
+int srp_target_alloc(struct srp_target *target, struct device *dev,
+ size_t nr, size_t iu_size)
+{
+ int err;
+
+ spin_lock_init(&target->lock);
+
+ target->dev = dev;
+
+ target->srp_iu_size = iu_size;
+ target->rx_ring_size = nr;
+ target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size);
+ if (!target->rx_ring)
+ return -ENOMEM;
+ err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring);
+ if (err)
+ goto free_ring;
+
+ dev_set_drvdata(target->dev, target);
+ return 0;
+
+free_ring:
+ srp_ring_free(target->dev, target->rx_ring, nr, iu_size);
+ return -ENOMEM;
+}
+
+void srp_target_free(struct srp_target *target)
+{
+ dev_set_drvdata(target->dev, NULL);
+ srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size,
+ target->srp_iu_size);
+ srp_iu_pool_free(&target->iu_queue);
+}
+
+struct iu_entry *srp_iu_get(struct srp_target *target)
+{
+ struct iu_entry *iue = NULL;
+
+ if (kfifo_out_locked(&target->iu_queue.queue, (void *)&iue,
+ sizeof(void *),
+ &target->iu_queue.lock) != sizeof(void *)) {
+ WARN_ONCE(1, "unexpected fifo state");
+ return NULL;
+ }
+ if (!iue)
+ return iue;
+ iue->target = target;
+ iue->flags = 0;
+ return iue;
+}
+
+void srp_iu_put(struct iu_entry *iue)
+{
+ kfifo_in_locked(&iue->target->iu_queue.queue, (void *)&iue,
+ sizeof(void *), &iue->target->iu_queue.lock);
+}
+
+static int srp_direct_data(struct ibmvscsis_cmd *cmd, struct srp_direct_buf *md,
+ enum dma_data_direction dir, srp_rdma_t rdma_io,
+ int dma_map, int ext_desc)
+{
+ struct iu_entry *iue = NULL;
+ struct scatterlist *sg = NULL;
+ int err, nsg = 0, len;
+
+ if (dma_map) {
+ iue = cmd->iue;
+ sg = cmd->se_cmd.t_data_sg;
+ nsg = dma_map_sg(iue->target->dev, sg, cmd->se_cmd.t_data_nents,
+ DMA_BIDIRECTIONAL);
+ if (!nsg) {
+ pr_err("fail to map %p %d\n", iue,
+ cmd->se_cmd.t_data_nents);
+ return 0;
+ }
+ len = min(cmd->se_cmd.data_length, be32_to_cpu(md->len));
+ } else {
+ len = be32_to_cpu(md->len);
+ }
+
+ err = rdma_io(cmd, sg, nsg, md, 1, dir, len);
+
+ if (dma_map)
+ dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
+
+ return err;
+}
+
+static int srp_indirect_data(struct ibmvscsis_cmd *cmd, struct srp_cmd *srp_cmd,
+ struct srp_indirect_buf *id,
+ enum dma_data_direction dir, srp_rdma_t rdma_io,
+ int dma_map, int ext_desc)
+{
+ struct iu_entry *iue = NULL;
+ struct srp_direct_buf *md = NULL;
+ struct scatterlist dummy, *sg = NULL;
+ dma_addr_t token = 0;
+ int err = 0;
+ int nmd, nsg = 0, len;
+
+ if (dma_map || ext_desc) {
+ iue = cmd->iue;
+ sg = cmd->se_cmd.t_data_sg;
+ }
+
+ nmd = be32_to_cpu(id->table_desc.len) / sizeof(struct srp_direct_buf);
+
+ if ((dir == DMA_FROM_DEVICE && nmd == srp_cmd->data_in_desc_cnt) ||
+ (dir == DMA_TO_DEVICE && nmd == srp_cmd->data_out_desc_cnt)) {
+ md = &id->desc_list[0];
+ goto rdma;
+ }
+
+ if (ext_desc && dma_map) {
+ md = dma_alloc_coherent(iue->target->dev,
+ be32_to_cpu(id->table_desc.len),
+ &token, GFP_KERNEL);
+ if (!md) {
+ pr_err("Can't get dma memory %u\n",
+ be32_to_cpu(id->table_desc.len));
+ return -ENOMEM;
+ }
+
+ sg_init_one(&dummy, md, be32_to_cpu(id->table_desc.len));
+ sg_dma_address(&dummy) = token;
+ sg_dma_len(&dummy) = be32_to_cpu(id->table_desc.len);
+ err = rdma_io(cmd, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
+ be32_to_cpu(id->table_desc.len));
+ if (err) {
+ pr_err("Error copying indirect table %d\n", err);
+ goto free_mem;
+ }
+ } else {
+ pr_err("This command uses external indirect buffer\n");
+ return -EINVAL;
+ }
+
+rdma:
+ if (dma_map) {
+ nsg = dma_map_sg(iue->target->dev, sg, cmd->se_cmd.t_data_nents,
+ DMA_BIDIRECTIONAL);
+ if (!nsg) {
+ pr_err("fail to map %p %d\n", iue,
+ cmd->se_cmd.t_data_nents);
+ err = -EIO;
+ goto free_mem;
+ }
+ len = min(cmd->se_cmd.data_length, be32_to_cpu(id->len));
+ } else {
+ len = be32_to_cpu(id->len);
+ }
+
+ err = rdma_io(cmd, sg, nsg, md, nmd, dir, len);
+
+ if (dma_map)
+ dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
+
+free_mem:
+ if (token && dma_map) {
+ dma_free_coherent(iue->target->dev,
+ be32_to_cpu(id->table_desc.len), md, token);
+ }
+ return err;
+}
+
+static int data_out_desc_size(struct srp_cmd *cmd)
+{
+ int size = 0;
+ u8 fmt = cmd->buf_fmt >> 4;
+
+ switch (fmt) {
+ case SRP_NO_DATA_DESC:
+ break;
+ case SRP_DATA_DESC_DIRECT:
+ size = sizeof(struct srp_direct_buf);
+ break;
+ case SRP_DATA_DESC_INDIRECT:
+ size = sizeof(struct srp_indirect_buf) +
+ sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt;
+ break;
+ default:
+ pr_err("client error. Invalid data_out_format %x\n", fmt);
+ break;
+ }
+ return size;
+}
+
+/*
+ * TODO: this can be called multiple times for a single command if it
+ * has very long data.
+ */
+int srp_transfer_data(struct ibmvscsis_cmd *cmd, struct srp_cmd *srp_cmd,
+ srp_rdma_t rdma_io, int dma_map, int ext_desc)
+{
+ struct srp_direct_buf *md;
+ struct srp_indirect_buf *id;
+ enum dma_data_direction dir;
+ int offset, err = 0;
+ u8 format;
+
+ if (!cmd->se_cmd.t_data_nents)
+ return 0;
+
+ offset = srp_cmd->add_cdb_len & ~3;
+
+ dir = srp_cmd_direction(srp_cmd);
+ if (dir == DMA_FROM_DEVICE)
+ offset += data_out_desc_size(srp_cmd);
+
+ if (dir == DMA_TO_DEVICE)
+ format = srp_cmd->buf_fmt >> 4;
+ else
+ format = srp_cmd->buf_fmt & ((1U << 4) - 1);
+
+ switch (format) {
+ case SRP_NO_DATA_DESC:
+ break;
+ case SRP_DATA_DESC_DIRECT:
+ md = (struct srp_direct_buf *)(srp_cmd->add_data + offset);
+ err = srp_direct_data(cmd, md, dir, rdma_io, dma_map, ext_desc);
+ break;
+ case SRP_DATA_DESC_INDIRECT:
+ id = (struct srp_indirect_buf *)(srp_cmd->add_data + offset);
+ err = srp_indirect_data(cmd, srp_cmd, id, dir, rdma_io, dma_map,
+ ext_desc);
+ break;
+ default:
+ pr_err("Unknown format %d %x\n", dir, format);
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+u64 srp_data_length(struct srp_cmd *cmd, enum dma_data_direction dir)
+{
+ struct srp_direct_buf *md;
+ struct srp_indirect_buf *id;
+ u64 len = 0;
+ uint offset = cmd->add_cdb_len & ~3;
+ u8 fmt;
+
+ if (dir == DMA_TO_DEVICE) {
+ fmt = cmd->buf_fmt >> 4;
+ } else {
+ fmt = cmd->buf_fmt & ((1U << 4) - 1);
+ offset += data_out_desc_size(cmd);
+ }
+
+ switch (fmt) {
+ case SRP_NO_DATA_DESC:
+ break;
+ case SRP_DATA_DESC_DIRECT:
+ md = (struct srp_direct_buf *)(cmd->add_data + offset);
+ len = be32_to_cpu(md->len);
+ break;
+ case SRP_DATA_DESC_INDIRECT:
+ id = (struct srp_indirect_buf *)(cmd->add_data + offset);
+ len = be32_to_cpu(id->len);
+ break;
+ default:
+ pr_err("invalid data format %x\n", fmt);
+ break;
+ }
+ return len;
+}
+
+int srp_get_desc_table(struct srp_cmd *srp_cmd, enum dma_data_direction *dir,
+ u64 *data_len)
+{
+ struct srp_indirect_buf *idb;
+ struct srp_direct_buf *db;
+ uint add_cdb_offset;
+ int rc;
+
+ /*
+ * The pointer computations below will only be compiled correctly
+ * if srp_cmd::add_data is declared as s8*, u8*, s8[] or u8[], so check
+ * whether srp_cmd::add_data has been declared as a byte pointer.
+ */
+ BUILD_BUG_ON(!__same_type(srp_cmd->add_data[0], (s8)0)
+ && !__same_type(srp_cmd->add_data[0], (u8)0));
+
+ BUG_ON(!dir);
+ BUG_ON(!data_len);
+
+ rc = 0;
+ *data_len = 0;
+
+ *dir = DMA_NONE;
+
+ if (srp_cmd->buf_fmt & 0xf)
+ *dir = DMA_FROM_DEVICE;
+ else if (srp_cmd->buf_fmt >> 4)
+ *dir = DMA_TO_DEVICE;
+
+ add_cdb_offset = srp_cmd->add_cdb_len & ~3;
+ if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_DIRECT) ||
+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_DIRECT)) {
+ db = (struct srp_direct_buf *)(srp_cmd->add_data
+ + add_cdb_offset);
+ *data_len = be32_to_cpu(db->len);
+ } else if (((srp_cmd->buf_fmt & 0xf) == SRP_DATA_DESC_INDIRECT) ||
+ ((srp_cmd->buf_fmt >> 4) == SRP_DATA_DESC_INDIRECT)) {
+ idb = (struct srp_indirect_buf *)(srp_cmd->add_data
+ + add_cdb_offset);
+
+ *data_len = be32_to_cpu(idb->len);
+ }
+ return rc;
+}
+
+MODULE_DESCRIPTION("SCSI RDMA Protocol lib functions");
+MODULE_AUTHOR("FUJITA Tomonori");
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/ibmvscsi_tgt/libsrp.h b/drivers/scsi/ibmvscsi_tgt/libsrp.h
new file mode 100644
index 000000000000..4696f331453e
--- /dev/null
+++ b/drivers/scsi/ibmvscsi_tgt/libsrp.h
@@ -0,0 +1,123 @@
+#ifndef __LIBSRP_H__
+#define __LIBSRP_H__
+
+#include <linux/list.h>
+#include <linux/kfifo.h>
+#include <scsi/srp.h>
+
+enum srp_valid {
+ INVALIDATE_CMD_RESP_EL = 0,
+ VALID_CMD_RESP_EL = 0x80,
+ VALID_INIT_MSG = 0xC0,
+ VALID_TRANS_EVENT = 0xFF
+};
+
+enum srp_format {
+ SRP_FORMAT = 1,
+ MAD_FORMAT = 2,
+ OS400_FORMAT = 3,
+ AIX_FORMAT = 4,
+ LINUX_FORMAT = 5,
+ MESSAGE_IN_CRQ = 6
+};
+
+enum srp_init_msg {
+ INIT_MSG = 1,
+ INIT_COMPLETE_MSG = 2
+};
+
+enum srp_trans_event {
+ UNUSED_FORMAT = 0,
+ PARTNER_FAILED = 1,
+ PARTNER_DEREGISTER = 2,
+ MIGRATED = 6
+};
+
+enum srp_status {
+ HEADER_DESCRIPTOR = 0xF1,
+ PING = 0xF5,
+ PING_RESPONSE = 0xF6
+};
+
+enum srp_mad_version {
+ MAD_VERSION_1 = 1
+};
+
+enum srp_os_type {
+ OS400 = 1,
+ LINUX = 2,
+ AIX = 3,
+ OFW = 4
+};
+
+enum srp_task_attributes {
+ SRP_SIMPLE_TASK = 0,
+ SRP_HEAD_TASK = 1,
+ SRP_ORDERED_TASK = 2,
+ SRP_ACA_TASK = 4
+};
+
+enum {
+ SRP_TASK_MANAGEMENT_FUNCTION_COMPLETE = 0,
+ SRP_REQUEST_FIELDS_INVALID = 2,
+ SRP_TASK_MANAGEMENT_FUNCTION_NOT_SUPPORTED = 4,
+ SRP_TASK_MANAGEMENT_FUNCTION_FAILED = 5
+};
+
+struct srp_buf {
+ dma_addr_t dma;
+ void *buf;
+};
+
+struct srp_queue {
+ void *pool;
+ void *items;
+ struct kfifo queue;
+ spinlock_t lock;
+};
+
+struct srp_target {
+ struct device *dev;
+
+ spinlock_t lock;
+ struct list_head cmd_queue;
+
+ size_t srp_iu_size;
+ struct srp_queue iu_queue;
+ size_t rx_ring_size;
+ struct srp_buf **rx_ring;
+
+ void *ldata;
+};
+
+struct iu_entry {
+ struct srp_target *target;
+
+ struct list_head ilist;
+ dma_addr_t remote_token;
+ unsigned long flags;
+
+ struct srp_buf *sbuf;
+ u16 iu_len;
+};
+
+struct ibmvscsis_cmd;
+
+typedef int (srp_rdma_t)(struct ibmvscsis_cmd *, struct scatterlist *, int,
+ struct srp_direct_buf *, int,
+ enum dma_data_direction, unsigned int);
+int srp_target_alloc(struct srp_target *, struct device *, size_t, size_t);
+void srp_target_free(struct srp_target *);
+struct iu_entry *srp_iu_get(struct srp_target *);
+void srp_iu_put(struct iu_entry *);
+int srp_transfer_data(struct ibmvscsis_cmd *, struct srp_cmd *,
+ srp_rdma_t, int, int);
+u64 srp_data_length(struct srp_cmd *cmd, enum dma_data_direction dir);
+int srp_get_desc_table(struct srp_cmd *srp_cmd, enum dma_data_direction *dir,
+ u64 *data_len);
+static inline int srp_cmd_direction(struct srp_cmd *cmd)
+{
+ return (cmd->buf_fmt >> 4) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+}
+
+#endif
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 1f539c288ae8..17d04c702e1b 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3288,6 +3288,11 @@ static void ipr_worker_thread(struct work_struct *work)
return;
}
+ if (!ioa_cfg->scan_enabled) {
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return;
+ }
+
restart:
do {
did_work = 0;
@@ -10214,6 +10219,7 @@ static int ipr_probe_ioa(struct pci_dev *pdev,
if (!ioa_cfg->reset_work_q) {
dev_err(&pdev->dev, "Couldn't register reset workqueue\n");
+ rc = -ENOMEM;
goto out_free_irq;
}
} else
@@ -10362,6 +10368,7 @@ static void ipr_remove(struct pci_dev *pdev)
static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
{
struct ipr_ioa_cfg *ioa_cfg;
+ unsigned long flags;
int rc, i;
rc = ipr_probe_ioa(pdev, dev_id);
@@ -10403,8 +10410,11 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
__ipr_remove(pdev);
return rc;
}
+ spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
+ ioa_cfg->scan_enabled = 1;
+ schedule_work(&ioa_cfg->work_q);
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
- scsi_scan_host(ioa_cfg->host);
ioa_cfg->iopoll_weight = ioa_cfg->chip_cfg->iopoll_weight;
if (ioa_cfg->iopoll_weight && ioa_cfg->sis64 && ioa_cfg->nvectors > 1) {
@@ -10414,7 +10424,8 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
}
}
- schedule_work(&ioa_cfg->work_q);
+ scsi_scan_host(ioa_cfg->host);
+
return 0;
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 1d42c7464dfc..cdb51960b53c 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1478,6 +1478,7 @@ struct ipr_ioa_cfg {
u8 in_ioa_bringdown:1;
u8 ioa_unit_checked:1;
u8 dump_taken:1;
+ u8 scan_enabled:1;
u8 scan_done:1;
u8 needs_hard_reset:1;
u8 dual_raid:1;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index a5655d571906..d197aa176dee 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -3877,7 +3877,7 @@ int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba,
uint32_t tag;
uint16_t hwq;
- if (shost_use_blk_mq(cmnd->device->host)) {
+ if (cmnd && shost_use_blk_mq(cmnd->device->host)) {
tag = blk_mq_unique_tag(cmnd->request);
hwq = blk_mq_unique_tag_to_hwq(tag);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 351d08ace24a..7080ce2920fd 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1323,21 +1323,18 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
{
lockdep_assert_held(&phba->hbalock);
+ BUG_ON(!piocb || !piocb->vport);
+
list_add_tail(&piocb->list, &pring->txcmplq);
piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ;
if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
(piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) &&
(piocb->iocb.ulpCommand != CMD_CLOSE_XRI_CN) &&
- (!(piocb->vport->load_flag & FC_UNLOADING))) {
- if (!piocb->vport)
- BUG();
- else
- mod_timer(&piocb->vport->els_tmofunc,
- jiffies +
- msecs_to_jiffies(1000 * (phba->fc_ratov << 1)));
- }
-
+ (!(piocb->vport->load_flag & FC_UNLOADING)))
+ mod_timer(&piocb->vport->els_tmofunc,
+ jiffies +
+ msecs_to_jiffies(1000 * (phba->fc_ratov << 1)));
return 0;
}
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c
index 180e027b1c8a..796e22037bc4 100644
--- a/drivers/ssb/driver_gpio.c
+++ b/drivers/ssb/driver_gpio.c
@@ -23,7 +23,7 @@
**************************************************/
#if IS_ENABLED(CONFIG_SSB_EMBEDDED)
-static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -38,14 +38,14 @@ static int ssb_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
* ChipCommon
**************************************************/
-static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
+static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
}
-static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
+static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned int gpio,
int value)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -54,7 +54,7 @@ static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
}
static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
- unsigned gpio)
+ unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -63,7 +63,7 @@ static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
}
static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
- unsigned gpio, int value)
+ unsigned int gpio, int value)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -72,7 +72,7 @@ static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
return 0;
}
-static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
+static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -85,7 +85,7 @@ static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
return 0;
}
-static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
+static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -256,14 +256,14 @@ static int ssb_gpio_chipco_init(struct ssb_bus *bus)
#ifdef CONFIG_SSB_DRIVER_EXTIF
-static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
+static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
}
-static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
+static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned int gpio,
int value)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -272,7 +272,7 @@ static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
}
static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
- unsigned gpio)
+ unsigned int gpio)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
@@ -281,7 +281,7 @@ static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
}
static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
- unsigned gpio, int value)
+ unsigned int gpio, int value)
{
struct ssb_bus *bus = gpiochip_get_data(chip);
diff --git a/drivers/staging/emxx_udc/Kconfig b/drivers/staging/emxx_udc/Kconfig
index cc3402020487..d7577096fb25 100644
--- a/drivers/staging/emxx_udc/Kconfig
+++ b/drivers/staging/emxx_udc/Kconfig
@@ -1,5 +1,5 @@
config USB_EMXX
- bool "EMXX USB Function Device Controller"
+ tristate "EMXX USB Function Device Controller"
depends on USB_GADGET && (ARCH_SHMOBILE || (ARM && COMPILE_TEST))
help
The Emma Mobile series of SoCs from Renesas Electronics and
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 3bd91758b2da..3b56b2826263 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -15,7 +15,7 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/ioport.h>
@@ -39,9 +39,11 @@
#include "emxx_udc.h"
+#define DRIVER_DESC "EMXX UDC driver"
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
static const char driver_name[] = "emxx_udc";
+static const char driver_desc[] = DRIVER_DESC;
/*===========================================================================*/
/* Prototype */
@@ -3296,6 +3298,28 @@ static void nbu2ss_drv_shutdown(struct platform_device *pdev)
}
/*-------------------------------------------------------------------------*/
+static int nbu2ss_drv_remove(struct platform_device *pdev)
+{
+ struct nbu2ss_udc *udc;
+ struct nbu2ss_ep *ep;
+ int i;
+
+ udc = &udc_controller;
+
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ ep = &udc->ep[i];
+ if (ep->virt_buf)
+ dma_free_coherent(NULL, PAGE_SIZE,
+ (void *)ep->virt_buf, ep->phys_buf);
+ }
+
+ /* Interrupt Handler - Release */
+ free_irq(INT_VBUS, udc);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
static int nbu2ss_drv_suspend(struct platform_device *pdev, pm_message_t state)
{
struct nbu2ss_udc *udc;
@@ -3347,12 +3371,16 @@ static int nbu2ss_drv_resume(struct platform_device *pdev)
static struct platform_driver udc_driver = {
.probe = nbu2ss_drv_probe,
.shutdown = nbu2ss_drv_shutdown,
+ .remove = nbu2ss_drv_remove,
.suspend = nbu2ss_drv_suspend,
.resume = nbu2ss_drv_resume,
.driver = {
- .name = driver_name,
- .suppress_bind_attrs = true,
+ .name = driver_name,
},
};
-builtin_platform_driver(udc_driver);
+module_platform_driver(udc_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Renesas Electronics Corporation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index 581a63a0a63e..463b1a360733 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -78,7 +78,7 @@ static void ll_release(struct dentry *de)
* INVALID) so d_lookup() matches it, but we have no lock on it (so
* lock_match() fails) and we spin around real_lookup().
*/
-static int ll_dcompare(const struct dentry *parent, const struct dentry *dentry,
+static int ll_dcompare(const struct dentry *dentry,
unsigned int len, const char *str,
const struct qstr *name)
{
diff --git a/drivers/staging/lustre/lustre/llite/statahead.c b/drivers/staging/lustre/lustre/llite/statahead.c
index 8e52722266fe..c1cb6b19e724 100644
--- a/drivers/staging/lustre/lustre/llite/statahead.c
+++ b/drivers/staging/lustre/lustre/llite/statahead.c
@@ -781,7 +781,7 @@ static int sa_args_init(struct inode *dir, struct inode *child,
struct ll_sa_entry *entry, struct md_enqueue_info **pmi,
struct ldlm_enqueue_info **pei)
{
- struct qstr *qstr = &entry->se_qstr;
+ const struct qstr *qstr = &entry->se_qstr;
struct ll_inode_info *lli = ll_i2info(dir);
struct md_enqueue_info *minfo;
struct ldlm_enqueue_info *einfo;
@@ -1340,7 +1340,7 @@ enum {
static int is_first_dirent(struct inode *dir, struct dentry *dentry)
{
struct ll_dir_chain chain;
- struct qstr *target = &dentry->d_name;
+ const struct qstr *target = &dentry->d_name;
struct page *page;
__u64 pos = 0;
int dot_de;
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index cae42e56f270..7292f23954df 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -16,7 +16,7 @@ menuconfig STAGING_MEDIA
If in doubt, say N here.
-if STAGING_MEDIA
+if STAGING_MEDIA && MEDIA_SUPPORT
# Please keep them in alphabetic order
source "drivers/staging/media/bcm2048/Kconfig"
diff --git a/drivers/staging/media/cec/cec-adap.c b/drivers/staging/media/cec/cec-adap.c
index 9fffddb7ac7e..b2393bbacb26 100644
--- a/drivers/staging/media/cec/cec-adap.c
+++ b/drivers/staging/media/cec/cec-adap.c
@@ -1252,7 +1252,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
return -EINVAL;
}
/* Zero unused part of the feature array */
- memset(features + i, 0, feature_sz - i);
+ memset(features + i + 1, 0, feature_sz - i - 1);
}
if (log_addrs->cec_version >= CEC_OP_CEC_VERSION_2_0) {
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 50f3d3a0dd7b..39b928c2849d 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -492,7 +492,8 @@ void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD);
spin_lock_bh(&conn->cmd_lock);
- if (!list_empty(&cmd->i_conn_node))
+ if (!list_empty(&cmd->i_conn_node) &&
+ !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
list_del_init(&cmd->i_conn_node);
spin_unlock_bh(&conn->cmd_lock);
@@ -4034,6 +4035,7 @@ int iscsi_target_rx_thread(void *arg)
static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
{
+ LIST_HEAD(tmp_list);
struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
struct iscsi_session *sess = conn->sess;
/*
@@ -4042,18 +4044,26 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
* has been reset -> returned sleeping pre-handler state.
*/
spin_lock_bh(&conn->cmd_lock);
- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
+ list_splice_init(&conn->conn_cmd_list, &tmp_list);
+ list_for_each_entry(cmd, &tmp_list, i_conn_node) {
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+ if (se_cmd->se_tfo != NULL) {
+ spin_lock(&se_cmd->t_state_lock);
+ se_cmd->transport_state |= CMD_T_FABRIC_STOP;
+ spin_unlock(&se_cmd->t_state_lock);
+ }
+ }
+ spin_unlock_bh(&conn->cmd_lock);
+
+ list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
list_del_init(&cmd->i_conn_node);
- spin_unlock_bh(&conn->cmd_lock);
iscsit_increment_maxcmdsn(cmd, sess);
-
iscsit_free_cmd(cmd, true);
- spin_lock_bh(&conn->cmd_lock);
}
- spin_unlock_bh(&conn->cmd_lock);
}
static void iscsit_stop_timers_for_cmds(
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index b5212f0f9571..adf419fa4291 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1371,8 +1371,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
}
login->zero_tsih = zero_tsih;
- conn->sess->se_sess->sup_prot_ops =
- conn->conn_transport->iscsit_get_sup_prot_ops(conn);
+ if (conn->sess)
+ conn->sess->se_sess->sup_prot_ops =
+ conn->conn_transport->iscsit_get_sup_prot_ops(conn);
tpg = conn->tpg;
if (!tpg) {
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index a4046ca6e60d..6b423485c5d6 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -821,13 +821,15 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
* in ATA and we need to set TPE=1
*/
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
- struct request_queue *q, int block_size)
+ struct request_queue *q)
{
+ int block_size = queue_logical_block_size(q);
+
if (!blk_queue_discard(q))
return false;
- attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
- block_size;
+ attrib->max_unmap_lba_count =
+ q->limits.max_discard_sectors >> (ilog2(block_size) - 9);
/*
* Currently hardcoded to 1 in Linux/SCSI code..
*/
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 75f0f08b2a34..d545993df18b 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -161,8 +161,7 @@ static int fd_configure_device(struct se_device *dev)
dev_size, div_u64(dev_size, fd_dev->fd_block_size),
fd_dev->fd_block_size);
- if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
- fd_dev->fd_block_size))
+ if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
pr_debug("IFILE: BLOCK Discard support available,"
" disabled by default\n");
/*
@@ -523,7 +522,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
*/
if (cmd->data_length > FD_MAX_BYTES) {
pr_err("FILEIO: Not able to process I/O of %u bytes due to"
- "FD_MAX_BYTES: %u iovec count limitiation\n",
+ "FD_MAX_BYTES: %u iovec count limitation\n",
cmd->data_length, FD_MAX_BYTES);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 22af12f8b8eb..372d744315f3 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -121,8 +121,7 @@ static int iblock_configure_device(struct se_device *dev)
dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
dev->dev_attrib.hw_queue_depth = q->nr_requests;
- if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
- dev->dev_attrib.hw_block_size))
+ if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
pr_debug("IBLOCK: BLOCK Discard support available,"
" disabled by default\n");
@@ -389,7 +388,7 @@ iblock_execute_sync_cache(struct se_cmd *cmd)
bio = bio_alloc(GFP_KERNEL, 0);
bio->bi_end_io = iblock_end_io_flush;
bio->bi_bdev = ib_dev->ibd_bd;
- bio->bi_rw = WRITE_FLUSH;
+ bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
if (!immed)
bio->bi_private = cmd;
submit_bio(bio);
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index fc91e85f54ba..e2c970a9d61c 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -146,6 +146,7 @@ sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
void target_qf_do_work(struct work_struct *work);
bool target_check_wce(struct se_device *dev);
bool target_check_fua(struct se_device *dev);
+void __target_execute_cmd(struct se_cmd *, bool);
/* target_core_stat.c */
void target_stat_setup_dev_default_groups(struct se_device *);
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index a9057aa07176..04f616b3ba0a 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -602,7 +602,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
spin_unlock_irq(&cmd->t_state_lock);
- __target_execute_cmd(cmd);
+ __target_execute_cmd(cmd, false);
kfree(buf);
return ret;
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 5ab3967dda43..6094a6beddde 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -754,7 +754,15 @@ EXPORT_SYMBOL(target_complete_cmd);
void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
{
- if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
+ if (scsi_status != SAM_STAT_GOOD) {
+ return;
+ }
+
+ /*
+ * Calculate new residual count based upon length of SCSI data
+ * transferred.
+ */
+ if (length < cmd->data_length) {
if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
cmd->residual_count += cmd->data_length - length;
} else {
@@ -763,6 +771,12 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len
}
cmd->data_length = length;
+ } else if (length > cmd->data_length) {
+ cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
+ cmd->residual_count = length - cmd->data_length;
+ } else {
+ cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT);
+ cmd->residual_count = 0;
}
target_complete_cmd(cmd, scsi_status);
@@ -1303,23 +1317,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
trace_target_sequencer_start(cmd);
- /*
- * Check for an existing UNIT ATTENTION condition
- */
- ret = target_scsi3_ua_check(cmd);
- if (ret)
- return ret;
-
- ret = target_alua_state_check(cmd);
- if (ret)
- return ret;
-
- ret = target_check_reservation(cmd);
- if (ret) {
- cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
- return ret;
- }
-
ret = dev->transport->parse_cdb(cmd);
if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
@@ -1761,20 +1758,45 @@ queue_full:
}
EXPORT_SYMBOL(transport_generic_request_failure);
-void __target_execute_cmd(struct se_cmd *cmd)
+void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
{
sense_reason_t ret;
- if (cmd->execute_cmd) {
- ret = cmd->execute_cmd(cmd);
- if (ret) {
- spin_lock_irq(&cmd->t_state_lock);
- cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
- spin_unlock_irq(&cmd->t_state_lock);
+ if (!cmd->execute_cmd) {
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ goto err;
+ }
+ if (do_checks) {
+ /*
+ * Check for an existing UNIT ATTENTION condition after
+ * target_handle_task_attr() has done SAM task attr
+ * checking, and possibly have already defered execution
+ * out to target_restart_delayed_cmds() context.
+ */
+ ret = target_scsi3_ua_check(cmd);
+ if (ret)
+ goto err;
- transport_generic_request_failure(cmd, ret);
+ ret = target_alua_state_check(cmd);
+ if (ret)
+ goto err;
+
+ ret = target_check_reservation(cmd);
+ if (ret) {
+ cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+ goto err;
}
}
+
+ ret = cmd->execute_cmd(cmd);
+ if (!ret)
+ return;
+err:
+ spin_lock_irq(&cmd->t_state_lock);
+ cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+ spin_unlock_irq(&cmd->t_state_lock);
+
+ transport_generic_request_failure(cmd, ret);
}
static int target_write_prot_action(struct se_cmd *cmd)
@@ -1819,6 +1841,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return false;
+ cmd->se_cmd_flags |= SCF_TASK_ATTR_SET;
+
/*
* Check for the existence of HEAD_OF_QUEUE, and if true return 1
* to allow the passed struct se_cmd list of tasks to the front of the list.
@@ -1899,7 +1923,7 @@ void target_execute_cmd(struct se_cmd *cmd)
return;
}
- __target_execute_cmd(cmd);
+ __target_execute_cmd(cmd, true);
}
EXPORT_SYMBOL(target_execute_cmd);
@@ -1923,7 +1947,7 @@ static void target_restart_delayed_cmds(struct se_device *dev)
list_del(&cmd->se_delayed_node);
spin_unlock(&dev->delayed_cmd_lock);
- __target_execute_cmd(cmd);
+ __target_execute_cmd(cmd, true);
if (cmd->sam_task_attr == TCM_ORDERED_TAG)
break;
@@ -1941,6 +1965,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
return;
+ if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET))
+ goto restart;
+
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
atomic_dec_mb(&dev->simple_cmds);
dev->dev_cur_ordered_id++;
@@ -1957,7 +1984,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n",
dev->dev_cur_ordered_id);
}
-
+restart:
target_restart_delayed_cmds(dev);
}
@@ -2557,15 +2584,10 @@ static void target_release_cmd_kref(struct kref *kref)
bool fabric_stop;
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
- if (list_empty(&se_cmd->se_cmd_list)) {
- spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
- target_free_cmd_mem(se_cmd);
- se_cmd->se_tfo->release_cmd(se_cmd);
- return;
- }
spin_lock(&se_cmd->t_state_lock);
- fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
+ fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
+ (se_cmd->transport_state & CMD_T_ABORTED);
spin_unlock(&se_cmd->t_state_lock);
if (se_cmd->cmd_wait_set || fabric_stop) {
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index f5186a744399..6ffbb603d912 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -91,6 +91,7 @@ static void ft_tport_delete(struct ft_tport *tport)
ft_sess_delete_all(tport);
lport = tport->lport;
+ lport->service_params &= ~FCP_SPPF_TARG_FCN;
BUG_ON(tport != lport->prov[FC_TYPE_FCP]);
RCU_INIT_POINTER(lport->prov[FC_TYPE_FCP], NULL);
@@ -110,6 +111,7 @@ void ft_lport_add(struct fc_lport *lport, void *arg)
{
mutex_lock(&ft_lport_lock);
ft_tport_get(lport);
+ lport->service_params |= FCP_SPPF_TARG_FCN;
mutex_unlock(&ft_lport_lock);
}
diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c
index 1b4ff0f4c716..ed5dd0e88657 100644
--- a/drivers/thermal/clock_cooling.c
+++ b/drivers/thermal/clock_cooling.c
@@ -426,6 +426,7 @@ clock_cooling_register(struct device *dev, const char *clock_name)
if (!ccdev)
return ERR_PTR(-ENOMEM);
+ mutex_init(&ccdev->lock);
ccdev->dev = dev;
ccdev->clk = devm_clk_get(dev, clock_name);
if (IS_ERR(ccdev->clk))
diff --git a/drivers/thermal/fair_share.c b/drivers/thermal/fair_share.c
index 34fe36504a55..68bd1b569118 100644
--- a/drivers/thermal/fair_share.c
+++ b/drivers/thermal/fair_share.c
@@ -116,7 +116,9 @@ static int fair_share_throttle(struct thermal_zone_device *tz, int trip)
instance->target = get_target_state(tz, cdev, percentage,
cur_trip_level);
+ mutex_lock(&instance->cdev->lock);
instance->cdev->updated = false;
+ mutex_unlock(&instance->cdev->lock);
thermal_cdev_update(cdev);
}
return 0;
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
index fc52016d4e85..bb118a152cbb 100644
--- a/drivers/thermal/gov_bang_bang.c
+++ b/drivers/thermal/gov_bang_bang.c
@@ -71,7 +71,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
dev_dbg(&instance->cdev->device, "target=%d\n",
(int)instance->target);
+ mutex_lock(&instance->cdev->lock);
instance->cdev->updated = false; /* cdev needs update */
+ mutex_unlock(&instance->cdev->lock);
}
mutex_unlock(&tz->lock);
diff --git a/drivers/thermal/intel_pch_thermal.c b/drivers/thermal/intel_pch_thermal.c
index 6a6ec1c95a7a..9b4815e81b0d 100644
--- a/drivers/thermal/intel_pch_thermal.c
+++ b/drivers/thermal/intel_pch_thermal.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/thermal.h>
+#include <linux/pm.h>
/* Intel PCH thermal Device IDs */
#define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */
@@ -65,6 +66,7 @@ struct pch_thermal_device {
unsigned long crt_temp;
int hot_trip_id;
unsigned long hot_temp;
+ bool bios_enabled;
};
static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
@@ -75,8 +77,10 @@ static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips)
*nr_trips = 0;
/* Check if BIOS has already enabled thermal sensor */
- if (WPT_TSS_TSDSS & readb(ptd->hw_base + WPT_TSS))
+ if (WPT_TSS_TSDSS & readb(ptd->hw_base + WPT_TSS)) {
+ ptd->bios_enabled = true;
goto read_trips;
+ }
tsel = readb(ptd->hw_base + WPT_TSEL);
/*
@@ -130,9 +134,39 @@ static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp)
return 0;
}
+static int pch_wpt_suspend(struct pch_thermal_device *ptd)
+{
+ u8 tsel;
+
+ if (ptd->bios_enabled)
+ return 0;
+
+ tsel = readb(ptd->hw_base + WPT_TSEL);
+
+ writeb(tsel & 0xFE, ptd->hw_base + WPT_TSEL);
+
+ return 0;
+}
+
+static int pch_wpt_resume(struct pch_thermal_device *ptd)
+{
+ u8 tsel;
+
+ if (ptd->bios_enabled)
+ return 0;
+
+ tsel = readb(ptd->hw_base + WPT_TSEL);
+
+ writeb(tsel | WPT_TSEL_ETS, ptd->hw_base + WPT_TSEL);
+
+ return 0;
+}
+
struct pch_dev_ops {
int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips);
int (*get_temp)(struct pch_thermal_device *ptd, int *temp);
+ int (*suspend)(struct pch_thermal_device *ptd);
+ int (*resume)(struct pch_thermal_device *ptd);
};
@@ -140,6 +174,8 @@ struct pch_dev_ops {
static const struct pch_dev_ops pch_dev_ops_wpt = {
.hw_init = pch_wpt_init,
.get_temp = pch_wpt_get_temp,
+ .suspend = pch_wpt_suspend,
+ .resume = pch_wpt_resume,
};
static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp)
@@ -269,6 +305,22 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
+static int intel_pch_thermal_suspend(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct pch_thermal_device *ptd = pci_get_drvdata(pdev);
+
+ return ptd->ops->suspend(ptd);
+}
+
+static int intel_pch_thermal_resume(struct device *device)
+{
+ struct pci_dev *pdev = to_pci_dev(device);
+ struct pch_thermal_device *ptd = pci_get_drvdata(pdev);
+
+ return ptd->ops->resume(ptd);
+}
+
static struct pci_device_id intel_pch_thermal_id[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) },
@@ -276,11 +328,17 @@ static struct pci_device_id intel_pch_thermal_id[] = {
};
MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
+static const struct dev_pm_ops intel_pch_pm_ops = {
+ .suspend = intel_pch_thermal_suspend,
+ .resume = intel_pch_thermal_resume,
+};
+
static struct pci_driver intel_pch_thermal_driver = {
.name = "intel_pch_thermal",
.id_table = intel_pch_thermal_id,
.probe = intel_pch_thermal_probe,
.remove = intel_pch_thermal_remove,
+ .driver.pm = &intel_pch_pm_ops,
};
module_pci_driver(intel_pch_thermal_driver);
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c
index 015ce2eb6eb7..0e4dc0afcfd2 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel_powerclamp.c
@@ -388,7 +388,7 @@ static int clamp_thread(void *arg)
int sleeptime;
unsigned long target_jiffies;
unsigned int guard;
- unsigned int compensation = 0;
+ unsigned int compensated_ratio;
int interval; /* jiffies to sleep for each attempt */
unsigned int duration_jiffies = msecs_to_jiffies(duration);
unsigned int window_size_now;
@@ -409,8 +409,11 @@ static int clamp_thread(void *arg)
* c-states, thus we need to compensate the injected idle ratio
* to achieve the actual target reported by the HW.
*/
- compensation = get_compensation(target_ratio);
- interval = duration_jiffies*100/(target_ratio+compensation);
+ compensated_ratio = target_ratio +
+ get_compensation(target_ratio);
+ if (compensated_ratio <= 0)
+ compensated_ratio = 1;
+ interval = duration_jiffies * 100 / compensated_ratio;
/* align idle time */
target_jiffies = roundup(jiffies, interval);
@@ -647,8 +650,8 @@ static int powerclamp_set_cur_state(struct thermal_cooling_device *cdev,
goto exit_set;
} else if (set_target_ratio > 0 && new_target_ratio == 0) {
pr_info("Stop forced idle injection\n");
- set_target_ratio = 0;
end_power_clamp();
+ set_target_ratio = 0;
} else /* adjust currently running */ {
set_target_ratio = new_target_ratio;
/* make new set_target_ratio visible to other cpus */
diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c
index 2f1a863a8e15..b4d3116cfdaf 100644
--- a/drivers/thermal/power_allocator.c
+++ b/drivers/thermal/power_allocator.c
@@ -529,7 +529,9 @@ static void allow_maximum_power(struct thermal_zone_device *tz)
continue;
instance->target = 0;
+ mutex_lock(&instance->cdev->lock);
instance->cdev->updated = false;
+ mutex_unlock(&instance->cdev->lock);
thermal_cdev_update(instance->cdev);
}
}
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index ea9366ad3e6b..bcef2e7c4ec9 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -175,7 +175,9 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
update_passive_instance(tz, trip_type, -1);
instance->initialized = true;
+ mutex_lock(&instance->cdev->lock);
instance->cdev->updated = false; /* cdev needs update */
+ mutex_unlock(&instance->cdev->lock);
}
mutex_unlock(&tz->lock);
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 5133cd1e10b7..e2fc6161dded 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1093,7 +1093,9 @@ int power_actor_set_power(struct thermal_cooling_device *cdev,
return ret;
instance->target = state;
+ mutex_lock(&cdev->lock);
cdev->updated = false;
+ mutex_unlock(&cdev->lock);
thermal_cdev_update(cdev);
return 0;
@@ -1623,11 +1625,13 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
struct thermal_instance *instance;
unsigned long target = 0;
+ mutex_lock(&cdev->lock);
/* cooling device is updated*/
- if (cdev->updated)
+ if (cdev->updated) {
+ mutex_unlock(&cdev->lock);
return;
+ }
- mutex_lock(&cdev->lock);
/* Make sure cdev enters the deepest cooling state */
list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) {
dev_dbg(&cdev->device, "zone%d->target=%lu\n",
@@ -1637,9 +1641,9 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev)
if (instance->target > target)
target = instance->target;
}
- mutex_unlock(&cdev->lock);
cdev->ops->set_cur_state(cdev, target);
cdev->updated = true;
+ mutex_unlock(&cdev->lock);
trace_cdev_update(cdev, target);
dev_dbg(&cdev->device, "set to state %lu\n", target);
}
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index 06fd2ed9ef9d..c41c7742903a 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -232,6 +232,7 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
return result;
}
+EXPORT_SYMBOL_GPL(thermal_add_hwmon_sysfs);
void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
{
@@ -270,3 +271,4 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
hwmon_device_unregister(hwmon->device);
kfree(hwmon);
}
+EXPORT_SYMBOL_GPL(thermal_remove_hwmon_sysfs);
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 1519d2ca7705..73137f4aac20 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -54,7 +54,7 @@ struct ar933x_uart_port {
static inline bool ar933x_uart_console_enabled(void)
{
- return config_enabled(CONFIG_SERIAL_AR933X_CONSOLE);
+ return IS_ENABLED(CONFIG_SERIAL_AR933X_CONSOLE);
}
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@@ -636,7 +636,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)
int ret;
np = pdev->dev.of_node;
- if (config_enabled(CONFIG_OF) && np) {
+ if (IS_ENABLED(CONFIG_OF) && np) {
id = of_alias_get_id(np, "serial");
if (id < 0) {
dev_err(&pdev->dev, "unable to get alias id, err=%d\n",
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 96a70789b4c2..4d6a5c672a3d 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -496,12 +496,10 @@ static int cp210x_write_reg_block(struct usb_serial_port *port, u8 req,
void *dmabuf;
int result;
- dmabuf = kmalloc(bufsize, GFP_KERNEL);
+ dmabuf = kmemdup(buf, bufsize, GFP_KERNEL);
if (!dmabuf)
return -ENOMEM;
- memcpy(dmabuf, buf, bufsize);
-
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
req, REQTYPE_HOST_TO_INTERFACE, 0,
port_priv->bInterfaceNumber, dmabuf, bufsize,
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index ae8c0365abd6..944de657a07a 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -350,6 +350,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
struct usb_serial_port *port = urb->context;
unsigned char *data = urb->transfer_buffer;
unsigned long flags;
+ int status = urb->status;
int i;
for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
@@ -360,22 +361,22 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
urb->actual_length);
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&port->dev, "%s - urb stopped: %d\n",
- __func__, urb->status);
+ __func__, status);
return;
case -EPIPE:
dev_err(&port->dev, "%s - urb stopped: %d\n",
- __func__, urb->status);
+ __func__, status);
return;
default:
dev_dbg(&port->dev, "%s - nonzero urb status: %d\n",
- __func__, urb->status);
+ __func__, status);
goto resubmit;
}
@@ -399,6 +400,7 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
{
unsigned long flags;
struct usb_serial_port *port = urb->context;
+ int status = urb->status;
int i;
for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i) {
@@ -410,22 +412,22 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb)
set_bit(i, &port->write_urbs_free);
spin_unlock_irqrestore(&port->lock, flags);
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ENOENT:
case -ECONNRESET:
case -ESHUTDOWN:
dev_dbg(&port->dev, "%s - urb stopped: %d\n",
- __func__, urb->status);
+ __func__, status);
return;
case -EPIPE:
dev_err_console(port, "%s - urb stopped: %d\n",
- __func__, urb->status);
+ __func__, status);
return;
default:
dev_err_console(port, "%s - nonzero urb status: %d\n",
- __func__, urb->status);
+ __func__, status);
goto resubmit;
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index d96d423d00e6..8e07536c233a 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -273,6 +273,7 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_LE922_USBCFG5 0x1045
#define TELIT_PRODUCT_LE920 0x1200
#define TELIT_PRODUCT_LE910 0x1201
+#define TELIT_PRODUCT_LE910_USBCFG4 0x1206
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -1198,6 +1199,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
+ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index e7dbbef2af2a..07b4bf01061d 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -1,5 +1,4 @@
-/* vi: ts=8 sw=8
- *
+/*
* TI 3410/5052 USB Serial Driver
*
* Copyright (C) 2004 Texas Instruments
@@ -35,9 +34,238 @@
#include <linux/usb.h>
#include <linux/usb/serial.h>
-#include "ti_usb_3410_5052.h"
-
-/* Defines */
+/* Configuration ids */
+#define TI_BOOT_CONFIG 1
+#define TI_ACTIVE_CONFIG 2
+
+/* Vendor and product ids */
+#define TI_VENDOR_ID 0x0451
+#define IBM_VENDOR_ID 0x04b3
+#define TI_3410_PRODUCT_ID 0x3410
+#define IBM_4543_PRODUCT_ID 0x4543
+#define IBM_454B_PRODUCT_ID 0x454b
+#define IBM_454C_PRODUCT_ID 0x454c
+#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
+#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
+#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
+#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
+#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
+
+/* Multi-Tech vendor and product ids */
+#define MTS_VENDOR_ID 0x06E0
+#define MTS_GSM_NO_FW_PRODUCT_ID 0xF108
+#define MTS_CDMA_NO_FW_PRODUCT_ID 0xF109
+#define MTS_CDMA_PRODUCT_ID 0xF110
+#define MTS_GSM_PRODUCT_ID 0xF111
+#define MTS_EDGE_PRODUCT_ID 0xF112
+#define MTS_MT9234MU_PRODUCT_ID 0xF114
+#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
+#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
+
+/* Abbott Diabetics vendor and product ids */
+#define ABBOTT_VENDOR_ID 0x1a61
+#define ABBOTT_STEREO_PLUG_ID 0x3410
+#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID
+#define ABBOTT_STRIP_PORT_ID 0x3420
+
+/* Honeywell vendor and product IDs */
+#define HONEYWELL_VENDOR_ID 0x10ac
+#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */
+
+/* Moxa UPORT 11x0 vendor and product IDs */
+#define MXU1_VENDOR_ID 0x110a
+#define MXU1_1110_PRODUCT_ID 0x1110
+#define MXU1_1130_PRODUCT_ID 0x1130
+#define MXU1_1150_PRODUCT_ID 0x1150
+#define MXU1_1151_PRODUCT_ID 0x1151
+#define MXU1_1131_PRODUCT_ID 0x1131
+
+/* Commands */
+#define TI_GET_VERSION 0x01
+#define TI_GET_PORT_STATUS 0x02
+#define TI_GET_PORT_DEV_INFO 0x03
+#define TI_GET_CONFIG 0x04
+#define TI_SET_CONFIG 0x05
+#define TI_OPEN_PORT 0x06
+#define TI_CLOSE_PORT 0x07
+#define TI_START_PORT 0x08
+#define TI_STOP_PORT 0x09
+#define TI_TEST_PORT 0x0A
+#define TI_PURGE_PORT 0x0B
+#define TI_RESET_EXT_DEVICE 0x0C
+#define TI_WRITE_DATA 0x80
+#define TI_READ_DATA 0x81
+#define TI_REQ_TYPE_CLASS 0x82
+
+/* Module identifiers */
+#define TI_I2C_PORT 0x01
+#define TI_IEEE1284_PORT 0x02
+#define TI_UART1_PORT 0x03
+#define TI_UART2_PORT 0x04
+#define TI_RAM_PORT 0x05
+
+/* Modem status */
+#define TI_MSR_DELTA_CTS 0x01
+#define TI_MSR_DELTA_DSR 0x02
+#define TI_MSR_DELTA_RI 0x04
+#define TI_MSR_DELTA_CD 0x08
+#define TI_MSR_CTS 0x10
+#define TI_MSR_DSR 0x20
+#define TI_MSR_RI 0x40
+#define TI_MSR_CD 0x80
+#define TI_MSR_DELTA_MASK 0x0F
+#define TI_MSR_MASK 0xF0
+
+/* Line status */
+#define TI_LSR_OVERRUN_ERROR 0x01
+#define TI_LSR_PARITY_ERROR 0x02
+#define TI_LSR_FRAMING_ERROR 0x04
+#define TI_LSR_BREAK 0x08
+#define TI_LSR_ERROR 0x0F
+#define TI_LSR_RX_FULL 0x10
+#define TI_LSR_TX_EMPTY 0x20
+
+/* Line control */
+#define TI_LCR_BREAK 0x40
+
+/* Modem control */
+#define TI_MCR_LOOP 0x04
+#define TI_MCR_DTR 0x10
+#define TI_MCR_RTS 0x20
+
+/* Mask settings */
+#define TI_UART_ENABLE_RTS_IN 0x0001
+#define TI_UART_DISABLE_RTS 0x0002
+#define TI_UART_ENABLE_PARITY_CHECKING 0x0008
+#define TI_UART_ENABLE_DSR_OUT 0x0010
+#define TI_UART_ENABLE_CTS_OUT 0x0020
+#define TI_UART_ENABLE_X_OUT 0x0040
+#define TI_UART_ENABLE_XA_OUT 0x0080
+#define TI_UART_ENABLE_X_IN 0x0100
+#define TI_UART_ENABLE_DTR_IN 0x0800
+#define TI_UART_DISABLE_DTR 0x1000
+#define TI_UART_ENABLE_MS_INTS 0x2000
+#define TI_UART_ENABLE_AUTO_START_DMA 0x4000
+
+/* Parity */
+#define TI_UART_NO_PARITY 0x00
+#define TI_UART_ODD_PARITY 0x01
+#define TI_UART_EVEN_PARITY 0x02
+#define TI_UART_MARK_PARITY 0x03
+#define TI_UART_SPACE_PARITY 0x04
+
+/* Stop bits */
+#define TI_UART_1_STOP_BITS 0x00
+#define TI_UART_1_5_STOP_BITS 0x01
+#define TI_UART_2_STOP_BITS 0x02
+
+/* Bits per character */
+#define TI_UART_5_DATA_BITS 0x00
+#define TI_UART_6_DATA_BITS 0x01
+#define TI_UART_7_DATA_BITS 0x02
+#define TI_UART_8_DATA_BITS 0x03
+
+/* 232/485 modes */
+#define TI_UART_232 0x00
+#define TI_UART_485_RECEIVER_DISABLED 0x01
+#define TI_UART_485_RECEIVER_ENABLED 0x02
+
+/* Pipe transfer mode and timeout */
+#define TI_PIPE_MODE_CONTINUOUS 0x01
+#define TI_PIPE_MODE_MASK 0x03
+#define TI_PIPE_TIMEOUT_MASK 0x7C
+#define TI_PIPE_TIMEOUT_ENABLE 0x80
+
+/* Config struct */
+struct ti_uart_config {
+ __u16 wBaudRate;
+ __u16 wFlags;
+ __u8 bDataBits;
+ __u8 bParity;
+ __u8 bStopBits;
+ char cXon;
+ char cXoff;
+ __u8 bUartMode;
+} __packed;
+
+/* Get port status */
+struct ti_port_status {
+ __u8 bCmdCode;
+ __u8 bModuleId;
+ __u8 bErrorCode;
+ __u8 bMSR;
+ __u8 bLSR;
+} __packed;
+
+/* Purge modes */
+#define TI_PURGE_OUTPUT 0x00
+#define TI_PURGE_INPUT 0x80
+
+/* Read/Write data */
+#define TI_RW_DATA_ADDR_SFR 0x10
+#define TI_RW_DATA_ADDR_IDATA 0x20
+#define TI_RW_DATA_ADDR_XDATA 0x30
+#define TI_RW_DATA_ADDR_CODE 0x40
+#define TI_RW_DATA_ADDR_GPIO 0x50
+#define TI_RW_DATA_ADDR_I2C 0x60
+#define TI_RW_DATA_ADDR_FLASH 0x70
+#define TI_RW_DATA_ADDR_DSP 0x80
+
+#define TI_RW_DATA_UNSPECIFIED 0x00
+#define TI_RW_DATA_BYTE 0x01
+#define TI_RW_DATA_WORD 0x02
+#define TI_RW_DATA_DOUBLE_WORD 0x04
+
+struct ti_write_data_bytes {
+ __u8 bAddrType;
+ __u8 bDataType;
+ __u8 bDataCounter;
+ __be16 wBaseAddrHi;
+ __be16 wBaseAddrLo;
+ __u8 bData[0];
+} __packed;
+
+struct ti_read_data_request {
+ __u8 bAddrType;
+ __u8 bDataType;
+ __u8 bDataCounter;
+ __be16 wBaseAddrHi;
+ __be16 wBaseAddrLo;
+} __packed;
+
+struct ti_read_data_bytes {
+ __u8 bCmdCode;
+ __u8 bModuleId;
+ __u8 bErrorCode;
+ __u8 bData[0];
+} __packed;
+
+/* Interrupt struct */
+struct ti_interrupt {
+ __u8 bICode;
+ __u8 bIInfo;
+} __packed;
+
+/* Interrupt codes */
+#define TI_CODE_HARDWARE_ERROR 0xFF
+#define TI_CODE_DATA_ERROR 0x03
+#define TI_CODE_MODEM_STATUS 0x04
+
+/* Download firmware max packet size */
+#define TI_DOWNLOAD_MAX_PACKET_SIZE 64
+
+/* Firmware image header */
+struct ti_firmware_header {
+ __le16 wLength;
+ __u8 bCheckSum;
+} __packed;
+
+/* UART addresses */
+#define TI_UART1_BASE_ADDR 0xFFA0 /* UART 1 base address */
+#define TI_UART2_BASE_ADDR 0xFFB0 /* UART 2 base address */
+#define TI_UART_OFFSET_LCR 0x0002 /* UART MCR register offset */
+#define TI_UART_OFFSET_MCR 0x0004 /* UART MCR register offset */
#define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>"
#define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver"
@@ -58,9 +286,6 @@
#define TI_EXTRA_VID_PID_COUNT 5
-
-/* Structures */
-
struct ti_port {
int tp_is_open;
__u8 tp_msr;
@@ -84,9 +309,6 @@ struct ti_device {
int td_urb_error;
};
-
-/* Function Declarations */
-
static int ti_startup(struct usb_serial *serial);
static void ti_release(struct usb_serial *serial);
static int ti_port_probe(struct usb_serial_port *port);
@@ -136,13 +358,8 @@ static int ti_write_byte(struct usb_serial_port *port, struct ti_device *tdev,
static int ti_download_firmware(struct ti_device *tdev);
-
-/* Data */
-
-/* module parameters */
static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
-/* supported devices */
static const struct usb_device_id ti_id_table_3410[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
@@ -174,7 +391,7 @@ static const struct usb_device_id ti_id_table_5052[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
- { } /* terminator */
+ { }
};
static const struct usb_device_id ti_id_table_combined[] = {
@@ -275,8 +492,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
&ti_1port_device, &ti_2port_device, NULL
};
-/* Module */
-
MODULE_AUTHOR(TI_DRIVER_AUTHOR);
MODULE_DESCRIPTION(TI_DRIVER_DESC);
MODULE_LICENSE("GPL");
@@ -302,8 +517,6 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
module_usb_serial_driver(serial_drivers, ti_id_table_combined);
-/* Functions */
-
static int ti_startup(struct usb_serial *serial)
{
struct ti_device *tdev;
@@ -319,7 +532,6 @@ static int ti_startup(struct usb_serial *serial)
dev->descriptor.bNumConfigurations,
dev->actconfig->desc.bConfigurationValue);
- /* create device structure */
tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL);
if (!tdev)
return -ENOMEM;
@@ -435,7 +647,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
struct urb *urb;
int port_number;
int status;
- __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
+ __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINUOUS |
TI_PIPE_TIMEOUT_ENABLE |
(TI_TRANSFER_TIMEOUT << 2));
@@ -954,6 +1166,15 @@ static void ti_break(struct tty_struct *tty, int break_state)
dev_dbg(&port->dev, "%s - error setting break, %d\n", __func__, status);
}
+static int ti_get_port_from_code(unsigned char code)
+{
+ return (code >> 4) - 3;
+}
+
+static int ti_get_func_from_code(unsigned char code)
+{
+ return code & 0x0f;
+}
static void ti_interrupt_callback(struct urb *urb)
{
@@ -995,8 +1216,8 @@ static void ti_interrupt_callback(struct urb *urb)
goto exit;
}
- port_number = TI_GET_PORT_FROM_CODE(data[0]);
- function = TI_GET_FUNC_FROM_CODE(data[0]);
+ port_number = ti_get_port_from_code(data[0]);
+ function = ti_get_func_from_code(data[0]);
dev_dbg(dev, "%s - port_number %d, function %d, data 0x%02X\n",
__func__, port_number, function, data[1]);
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
deleted file mode 100644
index bbfd3a184600..000000000000
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/* vi: ts=8 sw=8
- *
- * TI 3410/5052 USB Serial Driver Header
- *
- * Copyright (C) 2004 Texas Instruments
- *
- * This driver is based on the Linux io_ti driver, which is
- * Copyright (C) 2000-2002 Inside Out Networks
- * Copyright (C) 2001-2002 Greg Kroah-Hartman
- *
- * 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.
- *
- * For questions or problems with this driver, contact Texas Instruments
- * technical support, or Al Borchers <alborchers@steinerpoint.com>, or
- * Peter Berger <pberger@brimson.com>.
- */
-
-#ifndef _TI_3410_5052_H_
-#define _TI_3410_5052_H_
-
-/* Configuration ids */
-#define TI_BOOT_CONFIG 1
-#define TI_ACTIVE_CONFIG 2
-
-/* Vendor and product ids */
-#define TI_VENDOR_ID 0x0451
-#define IBM_VENDOR_ID 0x04b3
-#define TI_3410_PRODUCT_ID 0x3410
-#define IBM_4543_PRODUCT_ID 0x4543
-#define IBM_454B_PRODUCT_ID 0x454b
-#define IBM_454C_PRODUCT_ID 0x454c
-#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
-#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
-#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
-#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
-#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
-#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
-
-/* Multi-Tech vendor and product ids */
-#define MTS_VENDOR_ID 0x06E0
-#define MTS_GSM_NO_FW_PRODUCT_ID 0xF108
-#define MTS_CDMA_NO_FW_PRODUCT_ID 0xF109
-#define MTS_CDMA_PRODUCT_ID 0xF110
-#define MTS_GSM_PRODUCT_ID 0xF111
-#define MTS_EDGE_PRODUCT_ID 0xF112
-#define MTS_MT9234MU_PRODUCT_ID 0xF114
-#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
-#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
-
-/* Abbott Diabetics vendor and product ids */
-#define ABBOTT_VENDOR_ID 0x1a61
-#define ABBOTT_STEREO_PLUG_ID 0x3410
-#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID
-#define ABBOTT_STRIP_PORT_ID 0x3420
-
-/* Honeywell vendor and product IDs */
-#define HONEYWELL_VENDOR_ID 0x10ac
-#define HONEYWELL_HGI80_PRODUCT_ID 0x0102 /* Honeywell HGI80 */
-
-/* Moxa UPORT 11x0 vendor and product IDs */
-#define MXU1_VENDOR_ID 0x110a
-#define MXU1_1110_PRODUCT_ID 0x1110
-#define MXU1_1130_PRODUCT_ID 0x1130
-#define MXU1_1131_PRODUCT_ID 0x1131
-#define MXU1_1150_PRODUCT_ID 0x1150
-#define MXU1_1151_PRODUCT_ID 0x1151
-
-/* Commands */
-#define TI_GET_VERSION 0x01
-#define TI_GET_PORT_STATUS 0x02
-#define TI_GET_PORT_DEV_INFO 0x03
-#define TI_GET_CONFIG 0x04
-#define TI_SET_CONFIG 0x05
-#define TI_OPEN_PORT 0x06
-#define TI_CLOSE_PORT 0x07
-#define TI_START_PORT 0x08
-#define TI_STOP_PORT 0x09
-#define TI_TEST_PORT 0x0A
-#define TI_PURGE_PORT 0x0B
-#define TI_RESET_EXT_DEVICE 0x0C
-#define TI_WRITE_DATA 0x80
-#define TI_READ_DATA 0x81
-#define TI_REQ_TYPE_CLASS 0x82
-
-/* Module identifiers */
-#define TI_I2C_PORT 0x01
-#define TI_IEEE1284_PORT 0x02
-#define TI_UART1_PORT 0x03
-#define TI_UART2_PORT 0x04
-#define TI_RAM_PORT 0x05
-
-/* Modem status */
-#define TI_MSR_DELTA_CTS 0x01
-#define TI_MSR_DELTA_DSR 0x02
-#define TI_MSR_DELTA_RI 0x04
-#define TI_MSR_DELTA_CD 0x08
-#define TI_MSR_CTS 0x10
-#define TI_MSR_DSR 0x20
-#define TI_MSR_RI 0x40
-#define TI_MSR_CD 0x80
-#define TI_MSR_DELTA_MASK 0x0F
-#define TI_MSR_MASK 0xF0
-
-/* Line status */
-#define TI_LSR_OVERRUN_ERROR 0x01
-#define TI_LSR_PARITY_ERROR 0x02
-#define TI_LSR_FRAMING_ERROR 0x04
-#define TI_LSR_BREAK 0x08
-#define TI_LSR_ERROR 0x0F
-#define TI_LSR_RX_FULL 0x10
-#define TI_LSR_TX_EMPTY 0x20
-
-/* Line control */
-#define TI_LCR_BREAK 0x40
-
-/* Modem control */
-#define TI_MCR_LOOP 0x04
-#define TI_MCR_DTR 0x10
-#define TI_MCR_RTS 0x20
-
-/* Mask settings */
-#define TI_UART_ENABLE_RTS_IN 0x0001
-#define TI_UART_DISABLE_RTS 0x0002
-#define TI_UART_ENABLE_PARITY_CHECKING 0x0008
-#define TI_UART_ENABLE_DSR_OUT 0x0010
-#define TI_UART_ENABLE_CTS_OUT 0x0020
-#define TI_UART_ENABLE_X_OUT 0x0040
-#define TI_UART_ENABLE_XA_OUT 0x0080
-#define TI_UART_ENABLE_X_IN 0x0100
-#define TI_UART_ENABLE_DTR_IN 0x0800
-#define TI_UART_DISABLE_DTR 0x1000
-#define TI_UART_ENABLE_MS_INTS 0x2000
-#define TI_UART_ENABLE_AUTO_START_DMA 0x4000
-
-/* Parity */
-#define TI_UART_NO_PARITY 0x00
-#define TI_UART_ODD_PARITY 0x01
-#define TI_UART_EVEN_PARITY 0x02
-#define TI_UART_MARK_PARITY 0x03
-#define TI_UART_SPACE_PARITY 0x04
-
-/* Stop bits */
-#define TI_UART_1_STOP_BITS 0x00
-#define TI_UART_1_5_STOP_BITS 0x01
-#define TI_UART_2_STOP_BITS 0x02
-
-/* Bits per character */
-#define TI_UART_5_DATA_BITS 0x00
-#define TI_UART_6_DATA_BITS 0x01
-#define TI_UART_7_DATA_BITS 0x02
-#define TI_UART_8_DATA_BITS 0x03
-
-/* 232/485 modes */
-#define TI_UART_232 0x00
-#define TI_UART_485_RECEIVER_DISABLED 0x01
-#define TI_UART_485_RECEIVER_ENABLED 0x02
-
-/* Pipe transfer mode and timeout */
-#define TI_PIPE_MODE_CONTINOUS 0x01
-#define TI_PIPE_MODE_MASK 0x03
-#define TI_PIPE_TIMEOUT_MASK 0x7C
-#define TI_PIPE_TIMEOUT_ENABLE 0x80
-
-/* Config struct */
-struct ti_uart_config {
- __u16 wBaudRate;
- __u16 wFlags;
- __u8 bDataBits;
- __u8 bParity;
- __u8 bStopBits;
- char cXon;
- char cXoff;
- __u8 bUartMode;
-} __attribute__((packed));
-
-/* Get port status */
-struct ti_port_status {
- __u8 bCmdCode;
- __u8 bModuleId;
- __u8 bErrorCode;
- __u8 bMSR;
- __u8 bLSR;
-} __attribute__((packed));
-
-/* Purge modes */
-#define TI_PURGE_OUTPUT 0x00
-#define TI_PURGE_INPUT 0x80
-
-/* Read/Write data */
-#define TI_RW_DATA_ADDR_SFR 0x10
-#define TI_RW_DATA_ADDR_IDATA 0x20
-#define TI_RW_DATA_ADDR_XDATA 0x30
-#define TI_RW_DATA_ADDR_CODE 0x40
-#define TI_RW_DATA_ADDR_GPIO 0x50
-#define TI_RW_DATA_ADDR_I2C 0x60
-#define TI_RW_DATA_ADDR_FLASH 0x70
-#define TI_RW_DATA_ADDR_DSP 0x80
-
-#define TI_RW_DATA_UNSPECIFIED 0x00
-#define TI_RW_DATA_BYTE 0x01
-#define TI_RW_DATA_WORD 0x02
-#define TI_RW_DATA_DOUBLE_WORD 0x04
-
-struct ti_write_data_bytes {
- __u8 bAddrType;
- __u8 bDataType;
- __u8 bDataCounter;
- __be16 wBaseAddrHi;
- __be16 wBaseAddrLo;
- __u8 bData[0];
-} __attribute__((packed));
-
-struct ti_read_data_request {
- __u8 bAddrType;
- __u8 bDataType;
- __u8 bDataCounter;
- __be16 wBaseAddrHi;
- __be16 wBaseAddrLo;
-} __attribute__((packed));
-
-struct ti_read_data_bytes {
- __u8 bCmdCode;
- __u8 bModuleId;
- __u8 bErrorCode;
- __u8 bData[0];
-} __attribute__((packed));
-
-/* Interrupt struct */
-struct ti_interrupt {
- __u8 bICode;
- __u8 bIInfo;
-} __attribute__((packed));
-
-/* Interrupt codes */
-#define TI_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
-#define TI_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
-#define TI_CODE_HARDWARE_ERROR 0xFF
-#define TI_CODE_DATA_ERROR 0x03
-#define TI_CODE_MODEM_STATUS 0x04
-
-/* Download firmware max packet size */
-#define TI_DOWNLOAD_MAX_PACKET_SIZE 64
-
-/* Firmware image header */
-struct ti_firmware_header {
- __le16 wLength;
- __u8 bCheckSum;
-} __attribute__((packed));
-
-/* UART addresses */
-#define TI_UART1_BASE_ADDR 0xFFA0 /* UART 1 base address */
-#define TI_UART2_BASE_ADDR 0xFFB0 /* UART 2 base address */
-#define TI_UART_OFFSET_LCR 0x0002 /* UART MCR register offset */
-#define TI_UART_OFFSET_MCR 0x0004 /* UART MCR register offset */
-
-#endif /* _TI_3410_5052_H_ */
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
index 15ecfc9c5f6c..152b43822ef1 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -564,67 +564,80 @@ static int vfio_pci_set_msi_trigger(struct vfio_pci_device *vdev,
}
static int vfio_pci_set_ctx_trigger_single(struct eventfd_ctx **ctx,
- uint32_t flags, void *data)
+ unsigned int count, uint32_t flags,
+ void *data)
{
- int32_t fd = *(int32_t *)data;
-
- if (!(flags & VFIO_IRQ_SET_DATA_TYPE_MASK))
- return -EINVAL;
-
/* DATA_NONE/DATA_BOOL enables loopback testing */
if (flags & VFIO_IRQ_SET_DATA_NONE) {
- if (*ctx)
- eventfd_signal(*ctx, 1);
- return 0;
+ if (*ctx) {
+ if (count) {
+ eventfd_signal(*ctx, 1);
+ } else {
+ eventfd_ctx_put(*ctx);
+ *ctx = NULL;
+ }
+ return 0;
+ }
} else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
- uint8_t trigger = *(uint8_t *)data;
+ uint8_t trigger;
+
+ if (!count)
+ return -EINVAL;
+
+ trigger = *(uint8_t *)data;
if (trigger && *ctx)
eventfd_signal(*ctx, 1);
- return 0;
- }
- /* Handle SET_DATA_EVENTFD */
- if (fd == -1) {
- if (*ctx)
- eventfd_ctx_put(*ctx);
- *ctx = NULL;
return 0;
- } else if (fd >= 0) {
- struct eventfd_ctx *efdctx;
- efdctx = eventfd_ctx_fdget(fd);
- if (IS_ERR(efdctx))
- return PTR_ERR(efdctx);
- if (*ctx)
- eventfd_ctx_put(*ctx);
- *ctx = efdctx;
+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ int32_t fd;
+
+ if (!count)
+ return -EINVAL;
+
+ fd = *(int32_t *)data;
+ if (fd == -1) {
+ if (*ctx)
+ eventfd_ctx_put(*ctx);
+ *ctx = NULL;
+ } else if (fd >= 0) {
+ struct eventfd_ctx *efdctx;
+
+ efdctx = eventfd_ctx_fdget(fd);
+ if (IS_ERR(efdctx))
+ return PTR_ERR(efdctx);
+
+ if (*ctx)
+ eventfd_ctx_put(*ctx);
+
+ *ctx = efdctx;
+ }
return 0;
- } else
- return -EINVAL;
+ }
+
+ return -EINVAL;
}
static int vfio_pci_set_err_trigger(struct vfio_pci_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
- if (index != VFIO_PCI_ERR_IRQ_INDEX)
+ if (index != VFIO_PCI_ERR_IRQ_INDEX || start != 0 || count > 1)
return -EINVAL;
- /*
- * We should sanitize start & count, but that wasn't caught
- * originally, so this IRQ index must forever ignore them :-(
- */
-
- return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger, flags, data);
+ return vfio_pci_set_ctx_trigger_single(&vdev->err_trigger,
+ count, flags, data);
}
static int vfio_pci_set_req_trigger(struct vfio_pci_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags, void *data)
{
- if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count != 1)
+ if (index != VFIO_PCI_REQ_IRQ_INDEX || start != 0 || count > 1)
return -EINVAL;
- return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger, flags, data);
+ return vfio_pci_set_ctx_trigger_single(&vdev->req_trigger,
+ count, flags, data);
}
int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev, uint32_t flags,
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index 533eaf04f12f..40764ecad9ce 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -2,7 +2,6 @@ config VHOST_NET
tristate "Host kernel accelerator for virtio net"
depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP)
select VHOST
- select VHOST_RING
---help---
This kernel module can be loaded in host kernel to accelerate
guest networking with virtio_net. Not to be confused with virtio_net
@@ -15,17 +14,24 @@ config VHOST_SCSI
tristate "VHOST_SCSI TCM fabric driver"
depends on TARGET_CORE && EVENTFD && m
select VHOST
- select VHOST_RING
default n
---help---
Say M here to enable the vhost_scsi TCM fabric module
for use with virtio-scsi guests
-config VHOST_RING
- tristate
+config VHOST_VSOCK
+ tristate "vhost virtio-vsock driver"
+ depends on VSOCKETS && EVENTFD
+ select VIRTIO_VSOCKETS_COMMON
+ select VHOST
+ default n
---help---
- This option is selected by any driver which needs to access
- the host side of a virtio ring.
+ This kernel module can be loaded in the host kernel to provide AF_VSOCK
+ sockets for communicating with guests. The guests must have the
+ virtio_transport.ko driver loaded to use the virtio-vsock device.
+
+ To compile this driver as a module, choose M here: the module will be called
+ vhost_vsock.
config VHOST
tristate
diff --git a/drivers/vhost/Kconfig.vringh b/drivers/vhost/Kconfig.vringh
new file mode 100644
index 000000000000..6a4490c09d7f
--- /dev/null
+++ b/drivers/vhost/Kconfig.vringh
@@ -0,0 +1,5 @@
+config VHOST_RING
+ tristate
+ ---help---
+ This option is selected by any driver which needs to access
+ the host side of a virtio ring.
diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile
index e0441c34db1c..6b012b986b57 100644
--- a/drivers/vhost/Makefile
+++ b/drivers/vhost/Makefile
@@ -4,5 +4,9 @@ vhost_net-y := net.o
obj-$(CONFIG_VHOST_SCSI) += vhost_scsi.o
vhost_scsi-y := scsi.o
+obj-$(CONFIG_VHOST_VSOCK) += vhost_vsock.o
+vhost_vsock-y := vsock.o
+
obj-$(CONFIG_VHOST_RING) += vringh.o
+
obj-$(CONFIG_VHOST) += vhost.o
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e032ca397371..5dc128a8da83 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -61,7 +61,8 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
enum {
VHOST_NET_FEATURES = VHOST_FEATURES |
(1ULL << VHOST_NET_F_VIRTIO_NET_HDR) |
- (1ULL << VIRTIO_NET_F_MRG_RXBUF)
+ (1ULL << VIRTIO_NET_F_MRG_RXBUF) |
+ (1ULL << VIRTIO_F_IOMMU_PLATFORM)
};
enum {
@@ -334,7 +335,7 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
{
unsigned long uninitialized_var(endtime);
int r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
- out_num, in_num, NULL, NULL);
+ out_num, in_num, NULL, NULL);
if (r == vq->num && vq->busyloop_timeout) {
preempt_disable();
@@ -344,7 +345,7 @@ static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
cpu_relax_lowlatency();
preempt_enable();
r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
- out_num, in_num, NULL, NULL);
+ out_num, in_num, NULL, NULL);
}
return r;
@@ -377,6 +378,9 @@ static void handle_tx(struct vhost_net *net)
if (!sock)
goto out;
+ if (!vq_iotlb_prefetch(vq))
+ goto out;
+
vhost_disable_notify(&net->dev, vq);
hdr_size = nvq->vhost_hlen;
@@ -652,6 +656,10 @@ static void handle_rx(struct vhost_net *net)
sock = vq->private_data;
if (!sock)
goto out;
+
+ if (!vq_iotlb_prefetch(vq))
+ goto out;
+
vhost_disable_notify(&net->dev, vq);
vhost_net_disable_vq(net, vq);
@@ -1052,20 +1060,20 @@ static long vhost_net_reset_owner(struct vhost_net *n)
struct socket *tx_sock = NULL;
struct socket *rx_sock = NULL;
long err;
- struct vhost_memory *memory;
+ struct vhost_umem *umem;
mutex_lock(&n->dev.mutex);
err = vhost_dev_check_owner(&n->dev);
if (err)
goto done;
- memory = vhost_dev_reset_owner_prepare();
- if (!memory) {
+ umem = vhost_dev_reset_owner_prepare();
+ if (!umem) {
err = -ENOMEM;
goto done;
}
vhost_net_stop(n, &tx_sock, &rx_sock);
vhost_net_flush(n);
- vhost_dev_reset_owner(&n->dev, memory);
+ vhost_dev_reset_owner(&n->dev, umem);
vhost_net_vq_reset(n);
done:
mutex_unlock(&n->dev.mutex);
@@ -1096,10 +1104,14 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
}
mutex_lock(&n->dev.mutex);
if ((features & (1 << VHOST_F_LOG_ALL)) &&
- !vhost_log_access_ok(&n->dev)) {
- mutex_unlock(&n->dev.mutex);
- return -EFAULT;
+ !vhost_log_access_ok(&n->dev))
+ goto out_unlock;
+
+ if ((features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))) {
+ if (vhost_init_device_iotlb(&n->dev, true))
+ goto out_unlock;
}
+
for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
mutex_lock(&n->vqs[i].vq.mutex);
n->vqs[i].vq.acked_features = features;
@@ -1109,6 +1121,10 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
}
mutex_unlock(&n->dev.mutex);
return 0;
+
+out_unlock:
+ mutex_unlock(&n->dev.mutex);
+ return -EFAULT;
}
static long vhost_net_set_owner(struct vhost_net *n)
@@ -1182,9 +1198,40 @@ static long vhost_net_compat_ioctl(struct file *f, unsigned int ioctl,
}
#endif
+static ssize_t vhost_net_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+ struct file *file = iocb->ki_filp;
+ struct vhost_net *n = file->private_data;
+ struct vhost_dev *dev = &n->dev;
+ int noblock = file->f_flags & O_NONBLOCK;
+
+ return vhost_chr_read_iter(dev, to, noblock);
+}
+
+static ssize_t vhost_net_chr_write_iter(struct kiocb *iocb,
+ struct iov_iter *from)
+{
+ struct file *file = iocb->ki_filp;
+ struct vhost_net *n = file->private_data;
+ struct vhost_dev *dev = &n->dev;
+
+ return vhost_chr_write_iter(dev, from);
+}
+
+static unsigned int vhost_net_chr_poll(struct file *file, poll_table *wait)
+{
+ struct vhost_net *n = file->private_data;
+ struct vhost_dev *dev = &n->dev;
+
+ return vhost_chr_poll(file, dev, wait);
+}
+
static const struct file_operations vhost_net_fops = {
.owner = THIS_MODULE,
.release = vhost_net_release,
+ .read_iter = vhost_net_chr_read_iter,
+ .write_iter = vhost_net_chr_write_iter,
+ .poll = vhost_net_chr_poll,
.unlocked_ioctl = vhost_net_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = vhost_net_compat_ioctl,
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 388eec4e1a90..97fb2f8fa930 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -220,20 +220,20 @@ static long vhost_test_reset_owner(struct vhost_test *n)
{
void *priv = NULL;
long err;
- struct vhost_memory *memory;
+ struct vhost_umem *umem;
mutex_lock(&n->dev.mutex);
err = vhost_dev_check_owner(&n->dev);
if (err)
goto done;
- memory = vhost_dev_reset_owner_prepare();
- if (!memory) {
+ umem = vhost_dev_reset_owner_prepare();
+ if (!umem) {
err = -ENOMEM;
goto done;
}
vhost_test_stop(n, &priv);
vhost_test_flush(n);
- vhost_dev_reset_owner(&n->dev, memory);
+ vhost_dev_reset_owner(&n->dev, umem);
done:
mutex_unlock(&n->dev.mutex);
return err;
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 669fef1e2bb6..c6f2d89c0e97 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -27,6 +27,7 @@
#include <linux/cgroup.h>
#include <linux/module.h>
#include <linux/sort.h>
+#include <linux/interval_tree_generic.h>
#include "vhost.h"
@@ -34,6 +35,10 @@ static ushort max_mem_regions = 64;
module_param(max_mem_regions, ushort, 0444);
MODULE_PARM_DESC(max_mem_regions,
"Maximum number of memory regions in memory map. (default: 64)");
+static int max_iotlb_entries = 2048;
+module_param(max_iotlb_entries, int, 0444);
+MODULE_PARM_DESC(max_iotlb_entries,
+ "Maximum number of iotlb entries. (default: 2048)");
enum {
VHOST_MEMORY_F_LOG = 0x1,
@@ -42,6 +47,10 @@ enum {
#define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num])
#define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num])
+INTERVAL_TREE_DEFINE(struct vhost_umem_node,
+ rb, __u64, __subtree_last,
+ START, LAST, , vhost_umem_interval_tree);
+
#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
static void vhost_disable_cross_endian(struct vhost_virtqueue *vq)
{
@@ -131,6 +140,19 @@ static void vhost_reset_is_le(struct vhost_virtqueue *vq)
vq->is_le = virtio_legacy_is_little_endian();
}
+struct vhost_flush_struct {
+ struct vhost_work work;
+ struct completion wait_event;
+};
+
+static void vhost_flush_work(struct vhost_work *work)
+{
+ struct vhost_flush_struct *s;
+
+ s = container_of(work, struct vhost_flush_struct, work);
+ complete(&s->wait_event);
+}
+
static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
poll_table *pt)
{
@@ -155,11 +177,9 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn)
{
- INIT_LIST_HEAD(&work->node);
+ clear_bit(VHOST_WORK_QUEUED, &work->flags);
work->fn = fn;
init_waitqueue_head(&work->done);
- work->flushing = 0;
- work->queue_seq = work->done_seq = 0;
}
EXPORT_SYMBOL_GPL(vhost_work_init);
@@ -211,31 +231,17 @@ void vhost_poll_stop(struct vhost_poll *poll)
}
EXPORT_SYMBOL_GPL(vhost_poll_stop);
-static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work,
- unsigned seq)
-{
- int left;
-
- spin_lock_irq(&dev->work_lock);
- left = seq - work->done_seq;
- spin_unlock_irq(&dev->work_lock);
- return left <= 0;
-}
-
void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work)
{
- unsigned seq;
- int flushing;
+ struct vhost_flush_struct flush;
- spin_lock_irq(&dev->work_lock);
- seq = work->queue_seq;
- work->flushing++;
- spin_unlock_irq(&dev->work_lock);
- wait_event(work->done, vhost_work_seq_done(dev, work, seq));
- spin_lock_irq(&dev->work_lock);
- flushing = --work->flushing;
- spin_unlock_irq(&dev->work_lock);
- BUG_ON(flushing < 0);
+ if (dev->worker) {
+ init_completion(&flush.wait_event);
+ vhost_work_init(&flush.work, vhost_flush_work);
+
+ vhost_work_queue(dev, &flush.work);
+ wait_for_completion(&flush.wait_event);
+ }
}
EXPORT_SYMBOL_GPL(vhost_work_flush);
@@ -249,16 +255,16 @@ EXPORT_SYMBOL_GPL(vhost_poll_flush);
void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work)
{
- unsigned long flags;
+ if (!dev->worker)
+ return;
- spin_lock_irqsave(&dev->work_lock, flags);
- if (list_empty(&work->node)) {
- list_add_tail(&work->node, &dev->work_list);
- work->queue_seq++;
- spin_unlock_irqrestore(&dev->work_lock, flags);
+ if (!test_and_set_bit(VHOST_WORK_QUEUED, &work->flags)) {
+ /* We can only add the work to the list after we're
+ * sure it was not in the list.
+ */
+ smp_mb();
+ llist_add(&work->node, &dev->work_list);
wake_up_process(dev->worker);
- } else {
- spin_unlock_irqrestore(&dev->work_lock, flags);
}
}
EXPORT_SYMBOL_GPL(vhost_work_queue);
@@ -266,7 +272,7 @@ EXPORT_SYMBOL_GPL(vhost_work_queue);
/* A lockless hint for busy polling code to exit the loop */
bool vhost_has_work(struct vhost_dev *dev)
{
- return !list_empty(&dev->work_list);
+ return !llist_empty(&dev->work_list);
}
EXPORT_SYMBOL_GPL(vhost_has_work);
@@ -300,17 +306,18 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->call_ctx = NULL;
vq->call = NULL;
vq->log_ctx = NULL;
- vq->memory = NULL;
vhost_reset_is_le(vq);
vhost_disable_cross_endian(vq);
vq->busyloop_timeout = 0;
+ vq->umem = NULL;
+ vq->iotlb = NULL;
}
static int vhost_worker(void *data)
{
struct vhost_dev *dev = data;
- struct vhost_work *work = NULL;
- unsigned uninitialized_var(seq);
+ struct vhost_work *work, *work_next;
+ struct llist_node *node;
mm_segment_t oldfs = get_fs();
set_fs(USER_DS);
@@ -320,35 +327,25 @@ static int vhost_worker(void *data)
/* mb paired w/ kthread_stop */
set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irq(&dev->work_lock);
- if (work) {
- work->done_seq = seq;
- if (work->flushing)
- wake_up_all(&work->done);
- }
-
if (kthread_should_stop()) {
- spin_unlock_irq(&dev->work_lock);
__set_current_state(TASK_RUNNING);
break;
}
- if (!list_empty(&dev->work_list)) {
- work = list_first_entry(&dev->work_list,
- struct vhost_work, node);
- list_del_init(&work->node);
- seq = work->queue_seq;
- } else
- work = NULL;
- spin_unlock_irq(&dev->work_lock);
- if (work) {
+ node = llist_del_all(&dev->work_list);
+ if (!node)
+ schedule();
+
+ node = llist_reverse_order(node);
+ /* make sure flag is seen after deletion */
+ smp_wmb();
+ llist_for_each_entry_safe(work, work_next, node, node) {
+ clear_bit(VHOST_WORK_QUEUED, &work->flags);
__set_current_state(TASK_RUNNING);
work->fn(work);
if (need_resched())
schedule();
- } else
- schedule();
-
+ }
}
unuse_mm(dev->mm);
set_fs(oldfs);
@@ -407,11 +404,16 @@ void vhost_dev_init(struct vhost_dev *dev,
mutex_init(&dev->mutex);
dev->log_ctx = NULL;
dev->log_file = NULL;
- dev->memory = NULL;
+ dev->umem = NULL;
+ dev->iotlb = NULL;
dev->mm = NULL;
- spin_lock_init(&dev->work_lock);
- INIT_LIST_HEAD(&dev->work_list);
dev->worker = NULL;
+ init_llist_head(&dev->work_list);
+ init_waitqueue_head(&dev->wait);
+ INIT_LIST_HEAD(&dev->read_list);
+ INIT_LIST_HEAD(&dev->pending_list);
+ spin_lock_init(&dev->iotlb_lock);
+
for (i = 0; i < dev->nvqs; ++i) {
vq = dev->vqs[i];
@@ -512,27 +514,36 @@ err_mm:
}
EXPORT_SYMBOL_GPL(vhost_dev_set_owner);
-struct vhost_memory *vhost_dev_reset_owner_prepare(void)
+static void *vhost_kvzalloc(unsigned long size)
{
- return kmalloc(offsetof(struct vhost_memory, regions), GFP_KERNEL);
+ void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+
+ if (!n)
+ n = vzalloc(size);
+ return n;
+}
+
+struct vhost_umem *vhost_dev_reset_owner_prepare(void)
+{
+ return vhost_kvzalloc(sizeof(struct vhost_umem));
}
EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare);
/* Caller should have device mutex */
-void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_memory *memory)
+void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_umem *umem)
{
int i;
vhost_dev_cleanup(dev, true);
/* Restore memory to default empty mapping. */
- memory->nregions = 0;
- dev->memory = memory;
+ INIT_LIST_HEAD(&umem->umem_list);
+ dev->umem = umem;
/* We don't need VQ locks below since vhost_dev_cleanup makes sure
* VQs aren't running.
*/
for (i = 0; i < dev->nvqs; ++i)
- dev->vqs[i]->memory = memory;
+ dev->vqs[i]->umem = umem;
}
EXPORT_SYMBOL_GPL(vhost_dev_reset_owner);
@@ -549,6 +560,47 @@ void vhost_dev_stop(struct vhost_dev *dev)
}
EXPORT_SYMBOL_GPL(vhost_dev_stop);
+static void vhost_umem_free(struct vhost_umem *umem,
+ struct vhost_umem_node *node)
+{
+ vhost_umem_interval_tree_remove(node, &umem->umem_tree);
+ list_del(&node->link);
+ kfree(node);
+ umem->numem--;
+}
+
+static void vhost_umem_clean(struct vhost_umem *umem)
+{
+ struct vhost_umem_node *node, *tmp;
+
+ if (!umem)
+ return;
+
+ list_for_each_entry_safe(node, tmp, &umem->umem_list, link)
+ vhost_umem_free(umem, node);
+
+ kvfree(umem);
+}
+
+static void vhost_clear_msg(struct vhost_dev *dev)
+{
+ struct vhost_msg_node *node, *n;
+
+ spin_lock(&dev->iotlb_lock);
+
+ list_for_each_entry_safe(node, n, &dev->read_list, node) {
+ list_del(&node->node);
+ kfree(node);
+ }
+
+ list_for_each_entry_safe(node, n, &dev->pending_list, node) {
+ list_del(&node->node);
+ kfree(node);
+ }
+
+ spin_unlock(&dev->iotlb_lock);
+}
+
/* Caller should have device mutex if and only if locked is set */
void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
{
@@ -575,9 +627,13 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
fput(dev->log_file);
dev->log_file = NULL;
/* No one will access memory at this point */
- kvfree(dev->memory);
- dev->memory = NULL;
- WARN_ON(!list_empty(&dev->work_list));
+ vhost_umem_clean(dev->umem);
+ dev->umem = NULL;
+ vhost_umem_clean(dev->iotlb);
+ dev->iotlb = NULL;
+ vhost_clear_msg(dev);
+ wake_up_interruptible_poll(&dev->wait, POLLIN | POLLRDNORM);
+ WARN_ON(!llist_empty(&dev->work_list));
if (dev->worker) {
kthread_stop(dev->worker);
dev->worker = NULL;
@@ -601,26 +657,34 @@ static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
(sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8);
}
+static bool vhost_overflow(u64 uaddr, u64 size)
+{
+ /* Make sure 64 bit math will not overflow. */
+ return uaddr > ULONG_MAX || size > ULONG_MAX || uaddr > ULONG_MAX - size;
+}
+
/* Caller should have vq mutex and device mutex. */
-static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem,
+static int vq_memory_access_ok(void __user *log_base, struct vhost_umem *umem,
int log_all)
{
- int i;
+ struct vhost_umem_node *node;
- if (!mem)
+ if (!umem)
return 0;
- for (i = 0; i < mem->nregions; ++i) {
- struct vhost_memory_region *m = mem->regions + i;
- unsigned long a = m->userspace_addr;
- if (m->memory_size > ULONG_MAX)
+ list_for_each_entry(node, &umem->umem_list, link) {
+ unsigned long a = node->userspace_addr;
+
+ if (vhost_overflow(node->userspace_addr, node->size))
return 0;
- else if (!access_ok(VERIFY_WRITE, (void __user *)a,
- m->memory_size))
+
+
+ if (!access_ok(VERIFY_WRITE, (void __user *)a,
+ node->size))
return 0;
else if (log_all && !log_access_ok(log_base,
- m->guest_phys_addr,
- m->memory_size))
+ node->start,
+ node->size))
return 0;
}
return 1;
@@ -628,7 +692,7 @@ static int vq_memory_access_ok(void __user *log_base, struct vhost_memory *mem,
/* Can we switch to this memory table? */
/* Caller should have device mutex but not vq mutex */
-static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
+static int memory_access_ok(struct vhost_dev *d, struct vhost_umem *umem,
int log_all)
{
int i;
@@ -641,7 +705,8 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
log = log_all || vhost_has_feature(d->vqs[i], VHOST_F_LOG_ALL);
/* If ring is inactive, will check when it's enabled. */
if (d->vqs[i]->private_data)
- ok = vq_memory_access_ok(d->vqs[i]->log_base, mem, log);
+ ok = vq_memory_access_ok(d->vqs[i]->log_base,
+ umem, log);
else
ok = 1;
mutex_unlock(&d->vqs[i]->mutex);
@@ -651,12 +716,385 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
return 1;
}
+static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len,
+ struct iovec iov[], int iov_size, int access);
+
+static int vhost_copy_to_user(struct vhost_virtqueue *vq, void *to,
+ const void *from, unsigned size)
+{
+ int ret;
+
+ if (!vq->iotlb)
+ return __copy_to_user(to, from, size);
+ else {
+ /* This function should be called after iotlb
+ * prefetch, which means we're sure that all vq
+ * could be access through iotlb. So -EAGAIN should
+ * not happen in this case.
+ */
+ /* TODO: more fast path */
+ struct iov_iter t;
+ ret = translate_desc(vq, (u64)(uintptr_t)to, size, vq->iotlb_iov,
+ ARRAY_SIZE(vq->iotlb_iov),
+ VHOST_ACCESS_WO);
+ if (ret < 0)
+ goto out;
+ iov_iter_init(&t, WRITE, vq->iotlb_iov, ret, size);
+ ret = copy_to_iter(from, size, &t);
+ if (ret == size)
+ ret = 0;
+ }
+out:
+ return ret;
+}
+
+static int vhost_copy_from_user(struct vhost_virtqueue *vq, void *to,
+ void *from, unsigned size)
+{
+ int ret;
+
+ if (!vq->iotlb)
+ return __copy_from_user(to, from, size);
+ else {
+ /* This function should be called after iotlb
+ * prefetch, which means we're sure that vq
+ * could be access through iotlb. So -EAGAIN should
+ * not happen in this case.
+ */
+ /* TODO: more fast path */
+ struct iov_iter f;
+ ret = translate_desc(vq, (u64)(uintptr_t)from, size, vq->iotlb_iov,
+ ARRAY_SIZE(vq->iotlb_iov),
+ VHOST_ACCESS_RO);
+ if (ret < 0) {
+ vq_err(vq, "IOTLB translation failure: uaddr "
+ "%p size 0x%llx\n", from,
+ (unsigned long long) size);
+ goto out;
+ }
+ iov_iter_init(&f, READ, vq->iotlb_iov, ret, size);
+ ret = copy_from_iter(to, size, &f);
+ if (ret == size)
+ ret = 0;
+ }
+
+out:
+ return ret;
+}
+
+static void __user *__vhost_get_user(struct vhost_virtqueue *vq,
+ void *addr, unsigned size)
+{
+ int ret;
+
+ /* This function should be called after iotlb
+ * prefetch, which means we're sure that vq
+ * could be access through iotlb. So -EAGAIN should
+ * not happen in this case.
+ */
+ /* TODO: more fast path */
+ ret = translate_desc(vq, (u64)(uintptr_t)addr, size, vq->iotlb_iov,
+ ARRAY_SIZE(vq->iotlb_iov),
+ VHOST_ACCESS_RO);
+ if (ret < 0) {
+ vq_err(vq, "IOTLB translation failure: uaddr "
+ "%p size 0x%llx\n", addr,
+ (unsigned long long) size);
+ return NULL;
+ }
+
+ if (ret != 1 || vq->iotlb_iov[0].iov_len != size) {
+ vq_err(vq, "Non atomic userspace memory access: uaddr "
+ "%p size 0x%llx\n", addr,
+ (unsigned long long) size);
+ return NULL;
+ }
+
+ return vq->iotlb_iov[0].iov_base;
+}
+
+#define vhost_put_user(vq, x, ptr) \
+({ \
+ int ret = -EFAULT; \
+ if (!vq->iotlb) { \
+ ret = __put_user(x, ptr); \
+ } else { \
+ __typeof__(ptr) to = \
+ (__typeof__(ptr)) __vhost_get_user(vq, ptr, sizeof(*ptr)); \
+ if (to != NULL) \
+ ret = __put_user(x, to); \
+ else \
+ ret = -EFAULT; \
+ } \
+ ret; \
+})
+
+#define vhost_get_user(vq, x, ptr) \
+({ \
+ int ret; \
+ if (!vq->iotlb) { \
+ ret = __get_user(x, ptr); \
+ } else { \
+ __typeof__(ptr) from = \
+ (__typeof__(ptr)) __vhost_get_user(vq, ptr, sizeof(*ptr)); \
+ if (from != NULL) \
+ ret = __get_user(x, from); \
+ else \
+ ret = -EFAULT; \
+ } \
+ ret; \
+})
+
+static void vhost_dev_lock_vqs(struct vhost_dev *d)
+{
+ int i = 0;
+ for (i = 0; i < d->nvqs; ++i)
+ mutex_lock(&d->vqs[i]->mutex);
+}
+
+static void vhost_dev_unlock_vqs(struct vhost_dev *d)
+{
+ int i = 0;
+ for (i = 0; i < d->nvqs; ++i)
+ mutex_unlock(&d->vqs[i]->mutex);
+}
+
+static int vhost_new_umem_range(struct vhost_umem *umem,
+ u64 start, u64 size, u64 end,
+ u64 userspace_addr, int perm)
+{
+ struct vhost_umem_node *tmp, *node = kmalloc(sizeof(*node), GFP_ATOMIC);
+
+ if (!node)
+ return -ENOMEM;
+
+ if (umem->numem == max_iotlb_entries) {
+ tmp = list_first_entry(&umem->umem_list, typeof(*tmp), link);
+ vhost_umem_free(umem, tmp);
+ }
+
+ node->start = start;
+ node->size = size;
+ node->last = end;
+ node->userspace_addr = userspace_addr;
+ node->perm = perm;
+ INIT_LIST_HEAD(&node->link);
+ list_add_tail(&node->link, &umem->umem_list);
+ vhost_umem_interval_tree_insert(node, &umem->umem_tree);
+ umem->numem++;
+
+ return 0;
+}
+
+static void vhost_del_umem_range(struct vhost_umem *umem,
+ u64 start, u64 end)
+{
+ struct vhost_umem_node *node;
+
+ while ((node = vhost_umem_interval_tree_iter_first(&umem->umem_tree,
+ start, end)))
+ vhost_umem_free(umem, node);
+}
+
+static void vhost_iotlb_notify_vq(struct vhost_dev *d,
+ struct vhost_iotlb_msg *msg)
+{
+ struct vhost_msg_node *node, *n;
+
+ spin_lock(&d->iotlb_lock);
+
+ list_for_each_entry_safe(node, n, &d->pending_list, node) {
+ struct vhost_iotlb_msg *vq_msg = &node->msg.iotlb;
+ if (msg->iova <= vq_msg->iova &&
+ msg->iova + msg->size - 1 > vq_msg->iova &&
+ vq_msg->type == VHOST_IOTLB_MISS) {
+ vhost_poll_queue(&node->vq->poll);
+ list_del(&node->node);
+ kfree(node);
+ }
+ }
+
+ spin_unlock(&d->iotlb_lock);
+}
+
+static int umem_access_ok(u64 uaddr, u64 size, int access)
+{
+ unsigned long a = uaddr;
+
+ /* Make sure 64 bit math will not overflow. */
+ if (vhost_overflow(uaddr, size))
+ return -EFAULT;
+
+ if ((access & VHOST_ACCESS_RO) &&
+ !access_ok(VERIFY_READ, (void __user *)a, size))
+ return -EFAULT;
+ if ((access & VHOST_ACCESS_WO) &&
+ !access_ok(VERIFY_WRITE, (void __user *)a, size))
+ return -EFAULT;
+ return 0;
+}
+
+int vhost_process_iotlb_msg(struct vhost_dev *dev,
+ struct vhost_iotlb_msg *msg)
+{
+ int ret = 0;
+
+ vhost_dev_lock_vqs(dev);
+ switch (msg->type) {
+ case VHOST_IOTLB_UPDATE:
+ if (!dev->iotlb) {
+ ret = -EFAULT;
+ break;
+ }
+ if (umem_access_ok(msg->uaddr, msg->size, msg->perm)) {
+ ret = -EFAULT;
+ break;
+ }
+ if (vhost_new_umem_range(dev->iotlb, msg->iova, msg->size,
+ msg->iova + msg->size - 1,
+ msg->uaddr, msg->perm)) {
+ ret = -ENOMEM;
+ break;
+ }
+ vhost_iotlb_notify_vq(dev, msg);
+ break;
+ case VHOST_IOTLB_INVALIDATE:
+ vhost_del_umem_range(dev->iotlb, msg->iova,
+ msg->iova + msg->size - 1);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ vhost_dev_unlock_vqs(dev);
+ return ret;
+}
+ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
+ struct iov_iter *from)
+{
+ struct vhost_msg_node node;
+ unsigned size = sizeof(struct vhost_msg);
+ size_t ret;
+ int err;
+
+ if (iov_iter_count(from) < size)
+ return 0;
+ ret = copy_from_iter(&node.msg, size, from);
+ if (ret != size)
+ goto done;
+
+ switch (node.msg.type) {
+ case VHOST_IOTLB_MSG:
+ err = vhost_process_iotlb_msg(dev, &node.msg.iotlb);
+ if (err)
+ ret = err;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+done:
+ return ret;
+}
+EXPORT_SYMBOL(vhost_chr_write_iter);
+
+unsigned int vhost_chr_poll(struct file *file, struct vhost_dev *dev,
+ poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ poll_wait(file, &dev->wait, wait);
+
+ if (!list_empty(&dev->read_list))
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+EXPORT_SYMBOL(vhost_chr_poll);
+
+ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
+ int noblock)
+{
+ DEFINE_WAIT(wait);
+ struct vhost_msg_node *node;
+ ssize_t ret = 0;
+ unsigned size = sizeof(struct vhost_msg);
+
+ if (iov_iter_count(to) < size)
+ return 0;
+
+ while (1) {
+ if (!noblock)
+ prepare_to_wait(&dev->wait, &wait,
+ TASK_INTERRUPTIBLE);
+
+ node = vhost_dequeue_msg(dev, &dev->read_list);
+ if (node)
+ break;
+ if (noblock) {
+ ret = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ break;
+ }
+ if (!dev->iotlb) {
+ ret = -EBADFD;
+ break;
+ }
+
+ schedule();
+ }
+
+ if (!noblock)
+ finish_wait(&dev->wait, &wait);
+
+ if (node) {
+ ret = copy_to_iter(&node->msg, size, to);
+
+ if (ret != size || node->msg.type != VHOST_IOTLB_MISS) {
+ kfree(node);
+ return ret;
+ }
+
+ vhost_enqueue_msg(dev, &dev->pending_list, node);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(vhost_chr_read_iter);
+
+static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access)
+{
+ struct vhost_dev *dev = vq->dev;
+ struct vhost_msg_node *node;
+ struct vhost_iotlb_msg *msg;
+
+ node = vhost_new_msg(vq, VHOST_IOTLB_MISS);
+ if (!node)
+ return -ENOMEM;
+
+ msg = &node->msg.iotlb;
+ msg->type = VHOST_IOTLB_MISS;
+ msg->iova = iova;
+ msg->perm = access;
+
+ vhost_enqueue_msg(dev, &dev->read_list, node);
+
+ return 0;
+}
+
static int vq_access_ok(struct vhost_virtqueue *vq, unsigned int num,
struct vring_desc __user *desc,
struct vring_avail __user *avail,
struct vring_used __user *used)
+
{
size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
+
return access_ok(VERIFY_READ, desc, num * sizeof *desc) &&
access_ok(VERIFY_READ, avail,
sizeof *avail + num * sizeof *avail->ring + s) &&
@@ -664,11 +1102,59 @@ static int vq_access_ok(struct vhost_virtqueue *vq, unsigned int num,
sizeof *used + num * sizeof *used->ring + s);
}
+static int iotlb_access_ok(struct vhost_virtqueue *vq,
+ int access, u64 addr, u64 len)
+{
+ const struct vhost_umem_node *node;
+ struct vhost_umem *umem = vq->iotlb;
+ u64 s = 0, size;
+
+ while (len > s) {
+ node = vhost_umem_interval_tree_iter_first(&umem->umem_tree,
+ addr,
+ addr + len - 1);
+ if (node == NULL || node->start > addr) {
+ vhost_iotlb_miss(vq, addr, access);
+ return false;
+ } else if (!(node->perm & access)) {
+ /* Report the possible access violation by
+ * request another translation from userspace.
+ */
+ return false;
+ }
+
+ size = node->size - addr + node->start;
+ s += size;
+ addr += size;
+ }
+
+ return true;
+}
+
+int vq_iotlb_prefetch(struct vhost_virtqueue *vq)
+{
+ size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
+ unsigned int num = vq->num;
+
+ if (!vq->iotlb)
+ return 1;
+
+ return iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->desc,
+ num * sizeof *vq->desc) &&
+ iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->avail,
+ sizeof *vq->avail +
+ num * sizeof *vq->avail->ring + s) &&
+ iotlb_access_ok(vq, VHOST_ACCESS_WO, (u64)(uintptr_t)vq->used,
+ sizeof *vq->used +
+ num * sizeof *vq->used->ring + s);
+}
+EXPORT_SYMBOL_GPL(vq_iotlb_prefetch);
+
/* Can we log writes? */
/* Caller should have device mutex but not vq mutex */
int vhost_log_access_ok(struct vhost_dev *dev)
{
- return memory_access_ok(dev, dev->memory, 1);
+ return memory_access_ok(dev, dev->umem, 1);
}
EXPORT_SYMBOL_GPL(vhost_log_access_ok);
@@ -679,7 +1165,7 @@ static int vq_log_access_ok(struct vhost_virtqueue *vq,
{
size_t s = vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0;
- return vq_memory_access_ok(log_base, vq->memory,
+ return vq_memory_access_ok(log_base, vq->umem,
vhost_has_feature(vq, VHOST_F_LOG_ALL)) &&
(!vq->log_used || log_access_ok(log_base, vq->log_addr,
sizeof *vq->used +
@@ -690,33 +1176,36 @@ static int vq_log_access_ok(struct vhost_virtqueue *vq,
/* Caller should have vq mutex and device mutex */
int vhost_vq_access_ok(struct vhost_virtqueue *vq)
{
+ if (vq->iotlb) {
+ /* When device IOTLB was used, the access validation
+ * will be validated during prefetching.
+ */
+ return 1;
+ }
return vq_access_ok(vq, vq->num, vq->desc, vq->avail, vq->used) &&
vq_log_access_ok(vq, vq->log_base);
}
EXPORT_SYMBOL_GPL(vhost_vq_access_ok);
-static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2)
+static struct vhost_umem *vhost_umem_alloc(void)
{
- const struct vhost_memory_region *r1 = p1, *r2 = p2;
- if (r1->guest_phys_addr < r2->guest_phys_addr)
- return 1;
- if (r1->guest_phys_addr > r2->guest_phys_addr)
- return -1;
- return 0;
-}
+ struct vhost_umem *umem = vhost_kvzalloc(sizeof(*umem));
-static void *vhost_kvzalloc(unsigned long size)
-{
- void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+ if (!umem)
+ return NULL;
- if (!n)
- n = vzalloc(size);
- return n;
+ umem->umem_tree = RB_ROOT;
+ umem->numem = 0;
+ INIT_LIST_HEAD(&umem->umem_list);
+
+ return umem;
}
static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
{
- struct vhost_memory mem, *newmem, *oldmem;
+ struct vhost_memory mem, *newmem;
+ struct vhost_memory_region *region;
+ struct vhost_umem *newumem, *oldumem;
unsigned long size = offsetof(struct vhost_memory, regions);
int i;
@@ -736,24 +1225,47 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
kvfree(newmem);
return -EFAULT;
}
- sort(newmem->regions, newmem->nregions, sizeof(*newmem->regions),
- vhost_memory_reg_sort_cmp, NULL);
- if (!memory_access_ok(d, newmem, 0)) {
+ newumem = vhost_umem_alloc();
+ if (!newumem) {
kvfree(newmem);
- return -EFAULT;
+ return -ENOMEM;
}
- oldmem = d->memory;
- d->memory = newmem;
+
+ for (region = newmem->regions;
+ region < newmem->regions + mem.nregions;
+ region++) {
+ if (vhost_new_umem_range(newumem,
+ region->guest_phys_addr,
+ region->memory_size,
+ region->guest_phys_addr +
+ region->memory_size - 1,
+ region->userspace_addr,
+ VHOST_ACCESS_RW))
+ goto err;
+ }
+
+ if (!memory_access_ok(d, newumem, 0))
+ goto err;
+
+ oldumem = d->umem;
+ d->umem = newumem;
/* All memory accesses are done under some VQ mutex. */
for (i = 0; i < d->nvqs; ++i) {
mutex_lock(&d->vqs[i]->mutex);
- d->vqs[i]->memory = newmem;
+ d->vqs[i]->umem = newumem;
mutex_unlock(&d->vqs[i]->mutex);
}
- kvfree(oldmem);
+
+ kvfree(newmem);
+ vhost_umem_clean(oldumem);
return 0;
+
+err:
+ vhost_umem_clean(newumem);
+ kvfree(newmem);
+ return -EFAULT;
}
long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
@@ -974,6 +1486,30 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
}
EXPORT_SYMBOL_GPL(vhost_vring_ioctl);
+int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled)
+{
+ struct vhost_umem *niotlb, *oiotlb;
+ int i;
+
+ niotlb = vhost_umem_alloc();
+ if (!niotlb)
+ return -ENOMEM;
+
+ oiotlb = d->iotlb;
+ d->iotlb = niotlb;
+
+ for (i = 0; i < d->nvqs; ++i) {
+ mutex_lock(&d->vqs[i]->mutex);
+ d->vqs[i]->iotlb = niotlb;
+ mutex_unlock(&d->vqs[i]->mutex);
+ }
+
+ vhost_umem_clean(oiotlb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(vhost_init_device_iotlb);
+
/* Caller must have device mutex */
long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
{
@@ -1056,28 +1592,6 @@ done:
}
EXPORT_SYMBOL_GPL(vhost_dev_ioctl);
-static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
- __u64 addr, __u32 len)
-{
- const struct vhost_memory_region *reg;
- int start = 0, end = mem->nregions;
-
- while (start < end) {
- int slot = start + (end - start) / 2;
- reg = mem->regions + slot;
- if (addr >= reg->guest_phys_addr)
- end = slot;
- else
- start = slot + 1;
- }
-
- reg = mem->regions + start;
- if (addr >= reg->guest_phys_addr &&
- reg->guest_phys_addr + reg->memory_size > addr)
- return reg;
- return NULL;
-}
-
/* TODO: This is really inefficient. We need something like get_user()
* (instruction directly accesses the data, with an exception table entry
* returning -EFAULT). See Documentation/x86/exception-tables.txt.
@@ -1156,7 +1670,8 @@ EXPORT_SYMBOL_GPL(vhost_log_write);
static int vhost_update_used_flags(struct vhost_virtqueue *vq)
{
void __user *used;
- if (__put_user(cpu_to_vhost16(vq, vq->used_flags), &vq->used->flags) < 0)
+ if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
+ &vq->used->flags) < 0)
return -EFAULT;
if (unlikely(vq->log_used)) {
/* Make sure the flag is seen before log. */
@@ -1174,7 +1689,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
{
- if (__put_user(cpu_to_vhost16(vq, vq->avail_idx), vhost_avail_event(vq)))
+ if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
+ vhost_avail_event(vq)))
return -EFAULT;
if (unlikely(vq->log_used)) {
void __user *used;
@@ -1208,15 +1724,20 @@ int vhost_vq_init_access(struct vhost_virtqueue *vq)
if (r)
goto err;
vq->signalled_used_valid = false;
- if (!access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) {
+ if (!vq->iotlb &&
+ !access_ok(VERIFY_READ, &vq->used->idx, sizeof vq->used->idx)) {
r = -EFAULT;
goto err;
}
- r = __get_user(last_used_idx, &vq->used->idx);
- if (r)
+ r = vhost_get_user(vq, last_used_idx, &vq->used->idx);
+ if (r) {
+ vq_err(vq, "Can't access used idx at %p\n",
+ &vq->used->idx);
goto err;
+ }
vq->last_used_idx = vhost16_to_cpu(vq, last_used_idx);
return 0;
+
err:
vq->is_le = is_le;
return r;
@@ -1224,36 +1745,48 @@ err:
EXPORT_SYMBOL_GPL(vhost_vq_init_access);
static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len,
- struct iovec iov[], int iov_size)
+ struct iovec iov[], int iov_size, int access)
{
- const struct vhost_memory_region *reg;
- struct vhost_memory *mem;
+ const struct vhost_umem_node *node;
+ struct vhost_dev *dev = vq->dev;
+ struct vhost_umem *umem = dev->iotlb ? dev->iotlb : dev->umem;
struct iovec *_iov;
u64 s = 0;
int ret = 0;
- mem = vq->memory;
while ((u64)len > s) {
u64 size;
if (unlikely(ret >= iov_size)) {
ret = -ENOBUFS;
break;
}
- reg = find_region(mem, addr, len);
- if (unlikely(!reg)) {
- ret = -EFAULT;
+
+ node = vhost_umem_interval_tree_iter_first(&umem->umem_tree,
+ addr, addr + len - 1);
+ if (node == NULL || node->start > addr) {
+ if (umem != dev->iotlb) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = -EAGAIN;
+ break;
+ } else if (!(node->perm & access)) {
+ ret = -EPERM;
break;
}
+
_iov = iov + ret;
- size = reg->memory_size - addr + reg->guest_phys_addr;
+ size = node->size - addr + node->start;
_iov->iov_len = min((u64)len - s, size);
_iov->iov_base = (void __user *)(unsigned long)
- (reg->userspace_addr + addr - reg->guest_phys_addr);
+ (node->userspace_addr + addr - node->start);
s += size;
addr += size;
++ret;
}
+ if (ret == -EAGAIN)
+ vhost_iotlb_miss(vq, addr, access);
return ret;
}
@@ -1288,7 +1821,7 @@ static int get_indirect(struct vhost_virtqueue *vq,
unsigned int i = 0, count, found = 0;
u32 len = vhost32_to_cpu(vq, indirect->len);
struct iov_iter from;
- int ret;
+ int ret, access;
/* Sanity check */
if (unlikely(len % sizeof desc)) {
@@ -1300,9 +1833,10 @@ static int get_indirect(struct vhost_virtqueue *vq,
}
ret = translate_desc(vq, vhost64_to_cpu(vq, indirect->addr), len, vq->indirect,
- UIO_MAXIOV);
+ UIO_MAXIOV, VHOST_ACCESS_RO);
if (unlikely(ret < 0)) {
- vq_err(vq, "Translation failure %d in indirect.\n", ret);
+ if (ret != -EAGAIN)
+ vq_err(vq, "Translation failure %d in indirect.\n", ret);
return ret;
}
iov_iter_init(&from, READ, vq->indirect, ret, len);
@@ -1340,16 +1874,22 @@ static int get_indirect(struct vhost_virtqueue *vq,
return -EINVAL;
}
+ if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE))
+ access = VHOST_ACCESS_WO;
+ else
+ access = VHOST_ACCESS_RO;
+
ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr),
vhost32_to_cpu(vq, desc.len), iov + iov_count,
- iov_size - iov_count);
+ iov_size - iov_count, access);
if (unlikely(ret < 0)) {
- vq_err(vq, "Translation failure %d indirect idx %d\n",
- ret, i);
+ if (ret != -EAGAIN)
+ vq_err(vq, "Translation failure %d indirect idx %d\n",
+ ret, i);
return ret;
}
/* If this is an input descriptor, increment that count. */
- if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) {
+ if (access == VHOST_ACCESS_WO) {
*in_num += ret;
if (unlikely(log)) {
log[*log_num].addr = vhost64_to_cpu(vq, desc.addr);
@@ -1388,11 +1928,11 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
u16 last_avail_idx;
__virtio16 avail_idx;
__virtio16 ring_head;
- int ret;
+ int ret, access;
/* Check it isn't doing very strange things with descriptor numbers. */
last_avail_idx = vq->last_avail_idx;
- if (unlikely(__get_user(avail_idx, &vq->avail->idx))) {
+ if (unlikely(vhost_get_user(vq, avail_idx, &vq->avail->idx))) {
vq_err(vq, "Failed to access avail idx at %p\n",
&vq->avail->idx);
return -EFAULT;
@@ -1414,8 +1954,8 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
- if (unlikely(__get_user(ring_head,
- &vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
+ if (unlikely(vhost_get_user(vq, ring_head,
+ &vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
vq_err(vq, "Failed to read head: idx %d address %p\n",
last_avail_idx,
&vq->avail->ring[last_avail_idx % vq->num]);
@@ -1450,7 +1990,8 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
i, vq->num, head);
return -EINVAL;
}
- ret = __copy_from_user(&desc, vq->desc + i, sizeof desc);
+ ret = vhost_copy_from_user(vq, &desc, vq->desc + i,
+ sizeof desc);
if (unlikely(ret)) {
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
i, vq->desc + i);
@@ -1461,22 +2002,28 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
out_num, in_num,
log, log_num, &desc);
if (unlikely(ret < 0)) {
- vq_err(vq, "Failure detected "
- "in indirect descriptor at idx %d\n", i);
+ if (ret != -EAGAIN)
+ vq_err(vq, "Failure detected "
+ "in indirect descriptor at idx %d\n", i);
return ret;
}
continue;
}
+ if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE))
+ access = VHOST_ACCESS_WO;
+ else
+ access = VHOST_ACCESS_RO;
ret = translate_desc(vq, vhost64_to_cpu(vq, desc.addr),
vhost32_to_cpu(vq, desc.len), iov + iov_count,
- iov_size - iov_count);
+ iov_size - iov_count, access);
if (unlikely(ret < 0)) {
- vq_err(vq, "Translation failure %d descriptor idx %d\n",
- ret, i);
+ if (ret != -EAGAIN)
+ vq_err(vq, "Translation failure %d descriptor idx %d\n",
+ ret, i);
return ret;
}
- if (desc.flags & cpu_to_vhost16(vq, VRING_DESC_F_WRITE)) {
+ if (access == VHOST_ACCESS_WO) {
/* If this is an input descriptor,
* increment that count. */
*in_num += ret;
@@ -1538,15 +2085,15 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
start = vq->last_used_idx & (vq->num - 1);
used = vq->used->ring + start;
if (count == 1) {
- if (__put_user(heads[0].id, &used->id)) {
+ if (vhost_put_user(vq, heads[0].id, &used->id)) {
vq_err(vq, "Failed to write used id");
return -EFAULT;
}
- if (__put_user(heads[0].len, &used->len)) {
+ if (vhost_put_user(vq, heads[0].len, &used->len)) {
vq_err(vq, "Failed to write used len");
return -EFAULT;
}
- } else if (__copy_to_user(used, heads, count * sizeof *used)) {
+ } else if (vhost_copy_to_user(vq, used, heads, count * sizeof *used)) {
vq_err(vq, "Failed to write used");
return -EFAULT;
}
@@ -1590,7 +2137,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
/* Make sure buffer is written before we update index. */
smp_wmb();
- if (__put_user(cpu_to_vhost16(vq, vq->last_used_idx), &vq->used->idx)) {
+ if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
+ &vq->used->idx)) {
vq_err(vq, "Failed to increment used idx");
return -EFAULT;
}
@@ -1622,7 +2170,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
__virtio16 flags;
- if (__get_user(flags, &vq->avail->flags)) {
+ if (vhost_get_user(vq, flags, &vq->avail->flags)) {
vq_err(vq, "Failed to get flags");
return true;
}
@@ -1636,7 +2184,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
if (unlikely(!v))
return true;
- if (__get_user(event, vhost_used_event(vq))) {
+ if (vhost_get_user(vq, event, vhost_used_event(vq))) {
vq_err(vq, "Failed to get used event idx");
return true;
}
@@ -1678,7 +2226,7 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
__virtio16 avail_idx;
int r;
- r = __get_user(avail_idx, &vq->avail->idx);
+ r = vhost_get_user(vq, avail_idx, &vq->avail->idx);
if (r)
return false;
@@ -1713,7 +2261,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
/* They could have slipped one in as we were doing that: make
* sure it's written, then check again. */
smp_mb();
- r = __get_user(avail_idx, &vq->avail->idx);
+ r = vhost_get_user(vq, avail_idx, &vq->avail->idx);
if (r) {
vq_err(vq, "Failed to check avail idx at %p: %d\n",
&vq->avail->idx, r);
@@ -1741,6 +2289,47 @@ void vhost_disable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
}
EXPORT_SYMBOL_GPL(vhost_disable_notify);
+/* Create a new message. */
+struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type)
+{
+ struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL);
+ if (!node)
+ return NULL;
+ node->vq = vq;
+ node->msg.type = type;
+ return node;
+}
+EXPORT_SYMBOL_GPL(vhost_new_msg);
+
+void vhost_enqueue_msg(struct vhost_dev *dev, struct list_head *head,
+ struct vhost_msg_node *node)
+{
+ spin_lock(&dev->iotlb_lock);
+ list_add_tail(&node->node, head);
+ spin_unlock(&dev->iotlb_lock);
+
+ wake_up_interruptible_poll(&dev->wait, POLLIN | POLLRDNORM);
+}
+EXPORT_SYMBOL_GPL(vhost_enqueue_msg);
+
+struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev,
+ struct list_head *head)
+{
+ struct vhost_msg_node *node = NULL;
+
+ spin_lock(&dev->iotlb_lock);
+ if (!list_empty(head)) {
+ node = list_first_entry(head, struct vhost_msg_node,
+ node);
+ list_del(&node->node);
+ }
+ spin_unlock(&dev->iotlb_lock);
+
+ return node;
+}
+EXPORT_SYMBOL_GPL(vhost_dequeue_msg);
+
+
static int __init vhost_init(void)
{
return 0;
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index d36d8beb3351..78f3c5fc02e4 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -15,13 +15,15 @@
struct vhost_work;
typedef void (*vhost_work_fn_t)(struct vhost_work *work);
+#define VHOST_WORK_QUEUED 1
struct vhost_work {
- struct list_head node;
+ struct llist_node node;
vhost_work_fn_t fn;
wait_queue_head_t done;
int flushing;
unsigned queue_seq;
unsigned done_seq;
+ unsigned long flags;
};
/* Poll a file (eventfd or socket) */
@@ -53,6 +55,27 @@ struct vhost_log {
u64 len;
};
+#define START(node) ((node)->start)
+#define LAST(node) ((node)->last)
+
+struct vhost_umem_node {
+ struct rb_node rb;
+ struct list_head link;
+ __u64 start;
+ __u64 last;
+ __u64 size;
+ __u64 userspace_addr;
+ __u32 perm;
+ __u32 flags_padding;
+ __u64 __subtree_last;
+};
+
+struct vhost_umem {
+ struct rb_root umem_tree;
+ struct list_head umem_list;
+ int numem;
+};
+
/* The virtqueue structure describes a queue attached to a device. */
struct vhost_virtqueue {
struct vhost_dev *dev;
@@ -98,10 +121,12 @@ struct vhost_virtqueue {
u64 log_addr;
struct iovec iov[UIO_MAXIOV];
+ struct iovec iotlb_iov[64];
struct iovec *indirect;
struct vring_used_elem *heads;
/* Protected by virtqueue mutex. */
- struct vhost_memory *memory;
+ struct vhost_umem *umem;
+ struct vhost_umem *iotlb;
void *private_data;
u64 acked_features;
/* Log write descriptors */
@@ -118,25 +143,35 @@ struct vhost_virtqueue {
u32 busyloop_timeout;
};
+struct vhost_msg_node {
+ struct vhost_msg msg;
+ struct vhost_virtqueue *vq;
+ struct list_head node;
+};
+
struct vhost_dev {
- struct vhost_memory *memory;
struct mm_struct *mm;
struct mutex mutex;
struct vhost_virtqueue **vqs;
int nvqs;
struct file *log_file;
struct eventfd_ctx *log_ctx;
- spinlock_t work_lock;
- struct list_head work_list;
+ struct llist_head work_list;
struct task_struct *worker;
+ struct vhost_umem *umem;
+ struct vhost_umem *iotlb;
+ spinlock_t iotlb_lock;
+ struct list_head read_list;
+ struct list_head pending_list;
+ wait_queue_head_t wait;
};
void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
long vhost_dev_set_owner(struct vhost_dev *dev);
bool vhost_dev_has_owner(struct vhost_dev *dev);
long vhost_dev_check_owner(struct vhost_dev *);
-struct vhost_memory *vhost_dev_reset_owner_prepare(void);
-void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_memory *);
+struct vhost_umem *vhost_dev_reset_owner_prepare(void);
+void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *);
void vhost_dev_cleanup(struct vhost_dev *, bool locked);
void vhost_dev_stop(struct vhost_dev *);
long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
@@ -165,6 +200,21 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
+int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
+
+struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
+void vhost_enqueue_msg(struct vhost_dev *dev,
+ struct list_head *head,
+ struct vhost_msg_node *node);
+struct vhost_msg_node *vhost_dequeue_msg(struct vhost_dev *dev,
+ struct list_head *head);
+unsigned int vhost_chr_poll(struct file *file, struct vhost_dev *dev,
+ poll_table *wait);
+ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
+ int noblock);
+ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
+ struct iov_iter *from);
+int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled);
#define vq_err(vq, fmt, ...) do { \
pr_debug(pr_fmt(fmt), ##__VA_ARGS__); \
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
new file mode 100644
index 000000000000..e3b30ea9ece5
--- /dev/null
+++ b/drivers/vhost/vsock.c
@@ -0,0 +1,723 @@
+/*
+ * vhost transport for vsock
+ *
+ * Copyright (C) 2013-2015 Red Hat, Inc.
+ * Author: Asias He <asias@redhat.com>
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+#include <linux/miscdevice.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/vmalloc.h>
+#include <net/sock.h>
+#include <linux/virtio_vsock.h>
+#include <linux/vhost.h>
+
+#include <net/af_vsock.h>
+#include "vhost.h"
+
+#define VHOST_VSOCK_DEFAULT_HOST_CID 2
+
+enum {
+ VHOST_VSOCK_FEATURES = VHOST_FEATURES,
+};
+
+/* Used to track all the vhost_vsock instances on the system. */
+static DEFINE_SPINLOCK(vhost_vsock_lock);
+static LIST_HEAD(vhost_vsock_list);
+
+struct vhost_vsock {
+ struct vhost_dev dev;
+ struct vhost_virtqueue vqs[2];
+
+ /* Link to global vhost_vsock_list, protected by vhost_vsock_lock */
+ struct list_head list;
+
+ struct vhost_work send_pkt_work;
+ spinlock_t send_pkt_list_lock;
+ struct list_head send_pkt_list; /* host->guest pending packets */
+
+ atomic_t queued_replies;
+
+ u32 guest_cid;
+};
+
+static u32 vhost_transport_get_local_cid(void)
+{
+ return VHOST_VSOCK_DEFAULT_HOST_CID;
+}
+
+static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
+{
+ struct vhost_vsock *vsock;
+
+ spin_lock_bh(&vhost_vsock_lock);
+ list_for_each_entry(vsock, &vhost_vsock_list, list) {
+ u32 other_cid = vsock->guest_cid;
+
+ /* Skip instances that have no CID yet */
+ if (other_cid == 0)
+ continue;
+
+ if (other_cid == guest_cid) {
+ spin_unlock_bh(&vhost_vsock_lock);
+ return vsock;
+ }
+ }
+ spin_unlock_bh(&vhost_vsock_lock);
+
+ return NULL;
+}
+
+static void
+vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
+ struct vhost_virtqueue *vq)
+{
+ struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX];
+ bool added = false;
+ bool restart_tx = false;
+
+ mutex_lock(&vq->mutex);
+
+ if (!vq->private_data)
+ goto out;
+
+ /* Avoid further vmexits, we're already processing the virtqueue */
+ vhost_disable_notify(&vsock->dev, vq);
+
+ for (;;) {
+ struct virtio_vsock_pkt *pkt;
+ struct iov_iter iov_iter;
+ unsigned out, in;
+ size_t nbytes;
+ size_t len;
+ int head;
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ if (list_empty(&vsock->send_pkt_list)) {
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+ vhost_enable_notify(&vsock->dev, vq);
+ break;
+ }
+
+ pkt = list_first_entry(&vsock->send_pkt_list,
+ struct virtio_vsock_pkt, list);
+ list_del_init(&pkt->list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ head = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
+ &out, &in, NULL, NULL);
+ if (head < 0) {
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ list_add(&pkt->list, &vsock->send_pkt_list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+ break;
+ }
+
+ if (head == vq->num) {
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ list_add(&pkt->list, &vsock->send_pkt_list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ /* We cannot finish yet if more buffers snuck in while
+ * re-enabling notify.
+ */
+ if (unlikely(vhost_enable_notify(&vsock->dev, vq))) {
+ vhost_disable_notify(&vsock->dev, vq);
+ continue;
+ }
+ break;
+ }
+
+ if (out) {
+ virtio_transport_free_pkt(pkt);
+ vq_err(vq, "Expected 0 output buffers, got %u\n", out);
+ break;
+ }
+
+ len = iov_length(&vq->iov[out], in);
+ iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len);
+
+ nbytes = copy_to_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter);
+ if (nbytes != sizeof(pkt->hdr)) {
+ virtio_transport_free_pkt(pkt);
+ vq_err(vq, "Faulted on copying pkt hdr\n");
+ break;
+ }
+
+ nbytes = copy_to_iter(pkt->buf, pkt->len, &iov_iter);
+ if (nbytes != pkt->len) {
+ virtio_transport_free_pkt(pkt);
+ vq_err(vq, "Faulted on copying pkt buf\n");
+ break;
+ }
+
+ vhost_add_used(vq, head, sizeof(pkt->hdr) + pkt->len);
+ added = true;
+
+ if (pkt->reply) {
+ int val;
+
+ val = atomic_dec_return(&vsock->queued_replies);
+
+ /* Do we have resources to resume tx processing? */
+ if (val + 1 == tx_vq->num)
+ restart_tx = true;
+ }
+
+ virtio_transport_free_pkt(pkt);
+ }
+ if (added)
+ vhost_signal(&vsock->dev, vq);
+
+out:
+ mutex_unlock(&vq->mutex);
+
+ if (restart_tx)
+ vhost_poll_queue(&tx_vq->poll);
+}
+
+static void vhost_transport_send_pkt_work(struct vhost_work *work)
+{
+ struct vhost_virtqueue *vq;
+ struct vhost_vsock *vsock;
+
+ vsock = container_of(work, struct vhost_vsock, send_pkt_work);
+ vq = &vsock->vqs[VSOCK_VQ_RX];
+
+ vhost_transport_do_send_pkt(vsock, vq);
+}
+
+static int
+vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
+{
+ struct vhost_vsock *vsock;
+ struct vhost_virtqueue *vq;
+ int len = pkt->len;
+
+ /* Find the vhost_vsock according to guest context id */
+ vsock = vhost_vsock_get(le64_to_cpu(pkt->hdr.dst_cid));
+ if (!vsock) {
+ virtio_transport_free_pkt(pkt);
+ return -ENODEV;
+ }
+
+ vq = &vsock->vqs[VSOCK_VQ_RX];
+
+ if (pkt->reply)
+ atomic_inc(&vsock->queued_replies);
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ list_add_tail(&pkt->list, &vsock->send_pkt_list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+ return len;
+}
+
+static struct virtio_vsock_pkt *
+vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq,
+ unsigned int out, unsigned int in)
+{
+ struct virtio_vsock_pkt *pkt;
+ struct iov_iter iov_iter;
+ size_t nbytes;
+ size_t len;
+
+ if (in != 0) {
+ vq_err(vq, "Expected 0 input buffers, got %u\n", in);
+ return NULL;
+ }
+
+ pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
+ if (!pkt)
+ return NULL;
+
+ len = iov_length(vq->iov, out);
+ iov_iter_init(&iov_iter, WRITE, vq->iov, out, len);
+
+ nbytes = copy_from_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter);
+ if (nbytes != sizeof(pkt->hdr)) {
+ vq_err(vq, "Expected %zu bytes for pkt->hdr, got %zu bytes\n",
+ sizeof(pkt->hdr), nbytes);
+ kfree(pkt);
+ return NULL;
+ }
+
+ if (le16_to_cpu(pkt->hdr.type) == VIRTIO_VSOCK_TYPE_STREAM)
+ pkt->len = le32_to_cpu(pkt->hdr.len);
+
+ /* No payload */
+ if (!pkt->len)
+ return pkt;
+
+ /* The pkt is too big */
+ if (pkt->len > VIRTIO_VSOCK_MAX_PKT_BUF_SIZE) {
+ kfree(pkt);
+ return NULL;
+ }
+
+ pkt->buf = kmalloc(pkt->len, GFP_KERNEL);
+ if (!pkt->buf) {
+ kfree(pkt);
+ return NULL;
+ }
+
+ nbytes = copy_from_iter(pkt->buf, pkt->len, &iov_iter);
+ if (nbytes != pkt->len) {
+ vq_err(vq, "Expected %u byte payload, got %zu bytes\n",
+ pkt->len, nbytes);
+ virtio_transport_free_pkt(pkt);
+ return NULL;
+ }
+
+ return pkt;
+}
+
+/* Is there space left for replies to rx packets? */
+static bool vhost_vsock_more_replies(struct vhost_vsock *vsock)
+{
+ struct vhost_virtqueue *vq = &vsock->vqs[VSOCK_VQ_TX];
+ int val;
+
+ smp_rmb(); /* paired with atomic_inc() and atomic_dec_return() */
+ val = atomic_read(&vsock->queued_replies);
+
+ return val < vq->num;
+}
+
+static void vhost_vsock_handle_tx_kick(struct vhost_work *work)
+{
+ struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
+ poll.work);
+ struct vhost_vsock *vsock = container_of(vq->dev, struct vhost_vsock,
+ dev);
+ struct virtio_vsock_pkt *pkt;
+ int head;
+ unsigned int out, in;
+ bool added = false;
+
+ mutex_lock(&vq->mutex);
+
+ if (!vq->private_data)
+ goto out;
+
+ vhost_disable_notify(&vsock->dev, vq);
+ for (;;) {
+ u32 len;
+
+ if (!vhost_vsock_more_replies(vsock)) {
+ /* Stop tx until the device processes already
+ * pending replies. Leave tx virtqueue
+ * callbacks disabled.
+ */
+ goto no_more_replies;
+ }
+
+ head = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov),
+ &out, &in, NULL, NULL);
+ if (head < 0)
+ break;
+
+ if (head == vq->num) {
+ if (unlikely(vhost_enable_notify(&vsock->dev, vq))) {
+ vhost_disable_notify(&vsock->dev, vq);
+ continue;
+ }
+ break;
+ }
+
+ pkt = vhost_vsock_alloc_pkt(vq, out, in);
+ if (!pkt) {
+ vq_err(vq, "Faulted on pkt\n");
+ continue;
+ }
+
+ len = pkt->len;
+
+ /* Only accept correctly addressed packets */
+ if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid)
+ virtio_transport_recv_pkt(pkt);
+ else
+ virtio_transport_free_pkt(pkt);
+
+ vhost_add_used(vq, head, sizeof(pkt->hdr) + len);
+ added = true;
+ }
+
+no_more_replies:
+ if (added)
+ vhost_signal(&vsock->dev, vq);
+
+out:
+ mutex_unlock(&vq->mutex);
+}
+
+static void vhost_vsock_handle_rx_kick(struct vhost_work *work)
+{
+ struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
+ poll.work);
+ struct vhost_vsock *vsock = container_of(vq->dev, struct vhost_vsock,
+ dev);
+
+ vhost_transport_do_send_pkt(vsock, vq);
+}
+
+static int vhost_vsock_start(struct vhost_vsock *vsock)
+{
+ size_t i;
+ int ret;
+
+ mutex_lock(&vsock->dev.mutex);
+
+ ret = vhost_dev_check_owner(&vsock->dev);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ struct vhost_virtqueue *vq = &vsock->vqs[i];
+
+ mutex_lock(&vq->mutex);
+
+ if (!vhost_vq_access_ok(vq)) {
+ ret = -EFAULT;
+ mutex_unlock(&vq->mutex);
+ goto err_vq;
+ }
+
+ if (!vq->private_data) {
+ vq->private_data = vsock;
+ vhost_vq_init_access(vq);
+ }
+
+ mutex_unlock(&vq->mutex);
+ }
+
+ mutex_unlock(&vsock->dev.mutex);
+ return 0;
+
+err_vq:
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ struct vhost_virtqueue *vq = &vsock->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vq->private_data = NULL;
+ mutex_unlock(&vq->mutex);
+ }
+err:
+ mutex_unlock(&vsock->dev.mutex);
+ return ret;
+}
+
+static int vhost_vsock_stop(struct vhost_vsock *vsock)
+{
+ size_t i;
+ int ret;
+
+ mutex_lock(&vsock->dev.mutex);
+
+ ret = vhost_dev_check_owner(&vsock->dev);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ struct vhost_virtqueue *vq = &vsock->vqs[i];
+
+ mutex_lock(&vq->mutex);
+ vq->private_data = NULL;
+ mutex_unlock(&vq->mutex);
+ }
+
+err:
+ mutex_unlock(&vsock->dev.mutex);
+ return ret;
+}
+
+static void vhost_vsock_free(struct vhost_vsock *vsock)
+{
+ kvfree(vsock);
+}
+
+static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
+{
+ struct vhost_virtqueue **vqs;
+ struct vhost_vsock *vsock;
+ int ret;
+
+ /* This struct is large and allocation could fail, fall back to vmalloc
+ * if there is no other way.
+ */
+ vsock = kzalloc(sizeof(*vsock), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+ if (!vsock) {
+ vsock = vmalloc(sizeof(*vsock));
+ if (!vsock)
+ return -ENOMEM;
+ }
+
+ vqs = kmalloc_array(ARRAY_SIZE(vsock->vqs), sizeof(*vqs), GFP_KERNEL);
+ if (!vqs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ atomic_set(&vsock->queued_replies, 0);
+
+ vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX];
+ vqs[VSOCK_VQ_RX] = &vsock->vqs[VSOCK_VQ_RX];
+ vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
+ vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
+
+ vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
+
+ file->private_data = vsock;
+ spin_lock_init(&vsock->send_pkt_list_lock);
+ INIT_LIST_HEAD(&vsock->send_pkt_list);
+ vhost_work_init(&vsock->send_pkt_work, vhost_transport_send_pkt_work);
+
+ spin_lock_bh(&vhost_vsock_lock);
+ list_add_tail(&vsock->list, &vhost_vsock_list);
+ spin_unlock_bh(&vhost_vsock_lock);
+ return 0;
+
+out:
+ vhost_vsock_free(vsock);
+ return ret;
+}
+
+static void vhost_vsock_flush(struct vhost_vsock *vsock)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++)
+ if (vsock->vqs[i].handle_kick)
+ vhost_poll_flush(&vsock->vqs[i].poll);
+ vhost_work_flush(&vsock->dev, &vsock->send_pkt_work);
+}
+
+static void vhost_vsock_reset_orphans(struct sock *sk)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+
+ /* vmci_transport.c doesn't take sk_lock here either. At least we're
+ * under vsock_table_lock so the sock cannot disappear while we're
+ * executing.
+ */
+
+ if (!vhost_vsock_get(vsk->local_addr.svm_cid)) {
+ sock_set_flag(sk, SOCK_DONE);
+ vsk->peer_shutdown = SHUTDOWN_MASK;
+ sk->sk_state = SS_UNCONNECTED;
+ sk->sk_err = ECONNRESET;
+ sk->sk_error_report(sk);
+ }
+}
+
+static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
+{
+ struct vhost_vsock *vsock = file->private_data;
+
+ spin_lock_bh(&vhost_vsock_lock);
+ list_del(&vsock->list);
+ spin_unlock_bh(&vhost_vsock_lock);
+
+ /* Iterating over all connections for all CIDs to find orphans is
+ * inefficient. Room for improvement here. */
+ vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
+
+ vhost_vsock_stop(vsock);
+ vhost_vsock_flush(vsock);
+ vhost_dev_stop(&vsock->dev);
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ while (!list_empty(&vsock->send_pkt_list)) {
+ struct virtio_vsock_pkt *pkt;
+
+ pkt = list_first_entry(&vsock->send_pkt_list,
+ struct virtio_vsock_pkt, list);
+ list_del_init(&pkt->list);
+ virtio_transport_free_pkt(pkt);
+ }
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ vhost_dev_cleanup(&vsock->dev, false);
+ kfree(vsock->dev.vqs);
+ vhost_vsock_free(vsock);
+ return 0;
+}
+
+static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
+{
+ struct vhost_vsock *other;
+
+ /* Refuse reserved CIDs */
+ if (guest_cid <= VMADDR_CID_HOST ||
+ guest_cid == U32_MAX)
+ return -EINVAL;
+
+ /* 64-bit CIDs are not yet supported */
+ if (guest_cid > U32_MAX)
+ return -EINVAL;
+
+ /* Refuse if CID is already in use */
+ other = vhost_vsock_get(guest_cid);
+ if (other && other != vsock)
+ return -EADDRINUSE;
+
+ spin_lock_bh(&vhost_vsock_lock);
+ vsock->guest_cid = guest_cid;
+ spin_unlock_bh(&vhost_vsock_lock);
+
+ return 0;
+}
+
+static int vhost_vsock_set_features(struct vhost_vsock *vsock, u64 features)
+{
+ struct vhost_virtqueue *vq;
+ int i;
+
+ if (features & ~VHOST_VSOCK_FEATURES)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&vsock->dev.mutex);
+ if ((features & (1 << VHOST_F_LOG_ALL)) &&
+ !vhost_log_access_ok(&vsock->dev)) {
+ mutex_unlock(&vsock->dev.mutex);
+ return -EFAULT;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) {
+ vq = &vsock->vqs[i];
+ mutex_lock(&vq->mutex);
+ vq->acked_features = features;
+ mutex_unlock(&vq->mutex);
+ }
+ mutex_unlock(&vsock->dev.mutex);
+ return 0;
+}
+
+static long vhost_vsock_dev_ioctl(struct file *f, unsigned int ioctl,
+ unsigned long arg)
+{
+ struct vhost_vsock *vsock = f->private_data;
+ void __user *argp = (void __user *)arg;
+ u64 guest_cid;
+ u64 features;
+ int start;
+ int r;
+
+ switch (ioctl) {
+ case VHOST_VSOCK_SET_GUEST_CID:
+ if (copy_from_user(&guest_cid, argp, sizeof(guest_cid)))
+ return -EFAULT;
+ return vhost_vsock_set_cid(vsock, guest_cid);
+ case VHOST_VSOCK_SET_RUNNING:
+ if (copy_from_user(&start, argp, sizeof(start)))
+ return -EFAULT;
+ if (start)
+ return vhost_vsock_start(vsock);
+ else
+ return vhost_vsock_stop(vsock);
+ case VHOST_GET_FEATURES:
+ features = VHOST_VSOCK_FEATURES;
+ if (copy_to_user(argp, &features, sizeof(features)))
+ return -EFAULT;
+ return 0;
+ case VHOST_SET_FEATURES:
+ if (copy_from_user(&features, argp, sizeof(features)))
+ return -EFAULT;
+ return vhost_vsock_set_features(vsock, features);
+ default:
+ mutex_lock(&vsock->dev.mutex);
+ r = vhost_dev_ioctl(&vsock->dev, ioctl, argp);
+ if (r == -ENOIOCTLCMD)
+ r = vhost_vring_ioctl(&vsock->dev, ioctl, argp);
+ else
+ vhost_vsock_flush(vsock);
+ mutex_unlock(&vsock->dev.mutex);
+ return r;
+ }
+}
+
+static const struct file_operations vhost_vsock_fops = {
+ .owner = THIS_MODULE,
+ .open = vhost_vsock_dev_open,
+ .release = vhost_vsock_dev_release,
+ .llseek = noop_llseek,
+ .unlocked_ioctl = vhost_vsock_dev_ioctl,
+};
+
+static struct miscdevice vhost_vsock_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "vhost-vsock",
+ .fops = &vhost_vsock_fops,
+};
+
+static struct virtio_transport vhost_transport = {
+ .transport = {
+ .get_local_cid = vhost_transport_get_local_cid,
+
+ .init = virtio_transport_do_socket_init,
+ .destruct = virtio_transport_destruct,
+ .release = virtio_transport_release,
+ .connect = virtio_transport_connect,
+ .shutdown = virtio_transport_shutdown,
+
+ .dgram_enqueue = virtio_transport_dgram_enqueue,
+ .dgram_dequeue = virtio_transport_dgram_dequeue,
+ .dgram_bind = virtio_transport_dgram_bind,
+ .dgram_allow = virtio_transport_dgram_allow,
+
+ .stream_enqueue = virtio_transport_stream_enqueue,
+ .stream_dequeue = virtio_transport_stream_dequeue,
+ .stream_has_data = virtio_transport_stream_has_data,
+ .stream_has_space = virtio_transport_stream_has_space,
+ .stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
+ .stream_is_active = virtio_transport_stream_is_active,
+ .stream_allow = virtio_transport_stream_allow,
+
+ .notify_poll_in = virtio_transport_notify_poll_in,
+ .notify_poll_out = virtio_transport_notify_poll_out,
+ .notify_recv_init = virtio_transport_notify_recv_init,
+ .notify_recv_pre_block = virtio_transport_notify_recv_pre_block,
+ .notify_recv_pre_dequeue = virtio_transport_notify_recv_pre_dequeue,
+ .notify_recv_post_dequeue = virtio_transport_notify_recv_post_dequeue,
+ .notify_send_init = virtio_transport_notify_send_init,
+ .notify_send_pre_block = virtio_transport_notify_send_pre_block,
+ .notify_send_pre_enqueue = virtio_transport_notify_send_pre_enqueue,
+ .notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
+
+ .set_buffer_size = virtio_transport_set_buffer_size,
+ .set_min_buffer_size = virtio_transport_set_min_buffer_size,
+ .set_max_buffer_size = virtio_transport_set_max_buffer_size,
+ .get_buffer_size = virtio_transport_get_buffer_size,
+ .get_min_buffer_size = virtio_transport_get_min_buffer_size,
+ .get_max_buffer_size = virtio_transport_get_max_buffer_size,
+ },
+
+ .send_pkt = vhost_transport_send_pkt,
+};
+
+static int __init vhost_vsock_init(void)
+{
+ int ret;
+
+ ret = vsock_core_init(&vhost_transport.transport);
+ if (ret < 0)
+ return ret;
+ return misc_register(&vhost_vsock_misc);
+};
+
+static void __exit vhost_vsock_exit(void)
+{
+ misc_deregister(&vhost_vsock_misc);
+ vsock_core_exit();
+};
+
+module_init(vhost_vsock_init);
+module_exit(vhost_vsock_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Asias He");
+MODULE_DESCRIPTION("vhost transport for vsock ");
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
index 2fb90cb6803f..1d7c012f09db 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
@@ -1332,7 +1332,7 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
}
dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
- &rg->attrs);
+ rg->attrs);
rg->token = NULL;
rg->vaddr = NULL;
@@ -1370,7 +1370,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omapfb2_mem_region *rg;
void *token;
- DEFINE_DMA_ATTRS(attrs);
+ unsigned long attrs;
dma_addr_t dma_handle;
int r;
@@ -1386,15 +1386,15 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
size = PAGE_ALIGN(size);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ attrs = DMA_ATTR_WRITE_COMBINE;
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
- dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
+ attrs |= DMA_ATTR_NO_KERNEL_MAPPING;
DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
token = dma_alloc_attrs(fbdev->dev, size, &dma_handle,
- GFP_KERNEL, &attrs);
+ GFP_KERNEL, attrs);
if (token == NULL) {
dev_err(fbdev->dev, "failed to allocate framebuffer\n");
@@ -1408,7 +1408,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
r = omap_vrfb_request_ctx(&rg->vrfb);
if (r) {
dma_free_attrs(fbdev->dev, size, token, dma_handle,
- &attrs);
+ attrs);
dev_err(fbdev->dev, "vrfb create ctx failed\n");
return r;
}
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb.h b/drivers/video/fbdev/omap2/omapfb/omapfb.h
index bcb9ff4a607d..555487d6dbea 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb.h
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb.h
@@ -28,7 +28,6 @@
#endif
#include <linux/rwsem.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-mapping.h>
#include <video/omapfb_dss.h>
@@ -51,7 +50,7 @@ extern bool omapfb_debug;
struct omapfb2_mem_region {
int id;
- struct dma_attrs attrs;
+ unsigned long attrs;
void *token;
dma_addr_t dma_handle;
u32 paddr;
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 888d5f8322ce..4e7003db12c4 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -207,6 +207,8 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
num = min(num, ARRAY_SIZE(vb->pfns));
mutex_lock(&vb->balloon_lock);
+ /* We can't release more pages than taken */
+ num = min(num, (size_t)vb->num_pages);
for (vb->num_pfns = 0; vb->num_pfns < num;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = balloon_page_dequeue(vb_dev_info);
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ca6bfddaacad..e383ecdaca59 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -117,7 +117,10 @@ struct vring_virtqueue {
#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq)
/*
- * The interaction between virtio and a possible IOMMU is a mess.
+ * Modern virtio devices have feature bits to specify whether they need a
+ * quirk and bypass the IOMMU. If not there, just use the DMA API.
+ *
+ * If there, the interaction between virtio and DMA API is messy.
*
* On most systems with virtio, physical addresses match bus addresses,
* and it doesn't particularly matter whether we use the DMA API.
@@ -133,10 +136,18 @@ struct vring_virtqueue {
*
* For the time being, we preserve historic behavior and bypass the DMA
* API.
+ *
+ * TODO: install a per-device DMA ops structure that does the right thing
+ * taking into account all the above quirks, and use the DMA API
+ * unconditionally on data path.
*/
static bool vring_use_dma_api(struct virtio_device *vdev)
{
+ if (!virtio_has_iommu_quirk(vdev))
+ return true;
+
+ /* Otherwise, we are left to guess. */
/*
* In theory, it's possible to have a buggy QEMU-supposed
* emulated Q35 IOMMU and Xen enabled at the same time. On
@@ -316,6 +327,8 @@ static inline int virtqueue_add(struct virtqueue *_vq,
* host should service the ring ASAP. */
if (out_sgs)
vq->notify(&vq->vq);
+ if (indirect)
+ kfree(desc);
END_USE(vq);
return -ENOSPC;
}
@@ -415,6 +428,7 @@ unmap_release:
if (indirect)
kfree(desc);
+ END_USE(vq);
return -EIO;
}
@@ -1099,6 +1113,8 @@ void vring_transport_features(struct virtio_device *vdev)
break;
case VIRTIO_F_VERSION_1:
break;
+ case VIRTIO_F_IOMMU_PLATFORM:
+ break;
default:
/* We don't understand this bit. */
__virtio_clear_bit(vdev, i);
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 7399782c0998..87e6035c9e81 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -294,7 +294,7 @@ error:
void *
xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
int order = get_order(size);
@@ -346,7 +346,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_alloc_coherent);
void
xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dev_addr, struct dma_attrs *attrs)
+ dma_addr_t dev_addr, unsigned long attrs)
{
int order = get_order(size);
phys_addr_t phys;
@@ -378,7 +378,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_free_coherent);
dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
dma_addr_t dev_addr = xen_phys_to_bus(phys);
@@ -434,7 +434,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_page);
*/
static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
phys_addr_t paddr = xen_bus_to_phys(dev_addr);
@@ -462,7 +462,7 @@ static void xen_unmap_single(struct device *hwdev, dma_addr_t dev_addr,
void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
xen_unmap_single(hwdev, dev_addr, size, dir, attrs);
}
@@ -538,7 +538,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_sync_single_for_device);
int
xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -599,7 +599,7 @@ EXPORT_SYMBOL_GPL(xen_swiotlb_map_sg_attrs);
void
xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 47db55aee7f2..60fb47469c86 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -257,36 +257,12 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
return v9fs_fid_lookup_with_uid(dentry, uid, any);
}
-struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
-{
- struct p9_fid *fid, *ret;
-
- fid = v9fs_fid_lookup(dentry);
- if (IS_ERR(fid))
- return fid;
-
- ret = p9_client_walk(fid, 0, NULL, 1);
- return ret;
-}
-
-static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, kuid_t uid)
-{
- struct p9_fid *fid, *ret;
-
- fid = v9fs_fid_lookup_with_uid(dentry, uid, 0);
- if (IS_ERR(fid))
- return fid;
-
- ret = p9_client_walk(fid, 0, NULL, 1);
- return ret;
-}
-
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
{
int err;
struct p9_fid *fid;
- fid = v9fs_fid_clone_with_uid(dentry, GLOBAL_ROOT_UID);
+ fid = clone_fid(v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0));
if (IS_ERR(fid))
goto error_out;
/*
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 12700df0bb51..4491bcaf42b8 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -28,7 +28,14 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
{
return v9fs_fid_lookup(dentry->d_parent);
}
-struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
+static inline struct p9_fid *clone_fid(struct p9_fid *fid)
+{
+ return IS_ERR(fid) ? fid : p9_client_walk(fid, 0, NULL, 1);
+}
+static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
+{
+ return clone_fid(v9fs_fid_lookup(dentry));
+}
#endif
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 7da9a8354fad..8b1999b528e9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -661,7 +661,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
}
/* clone a fid to use for creation */
- ofid = p9_client_walk(dfid, 0, NULL, 1);
+ ofid = clone_fid(dfid);
if (IS_ERR(ofid)) {
err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
@@ -975,13 +975,13 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (IS_ERR(oldfid))
return PTR_ERR(oldfid);
- olddirfid = v9fs_parent_fid(old_dentry);
+ olddirfid = clone_fid(v9fs_parent_fid(old_dentry));
if (IS_ERR(olddirfid)) {
retval = PTR_ERR(olddirfid);
goto done;
}
- newdirfid = v9fs_parent_fid(new_dentry);
+ newdirfid = clone_fid(v9fs_parent_fid(new_dentry));
if (IS_ERR(newdirfid)) {
retval = PTR_ERR(newdirfid);
goto clunk_olddir;
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 2ed04c2fe7af..eeabcb0bad12 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -281,7 +281,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
}
/* clone a fid to use for creation */
- ofid = p9_client_walk(dfid, 0, NULL, 1);
+ ofid = clone_fid(dfid);
if (IS_ERR(ofid)) {
err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index a6bd349bab23..f329eee6dc93 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -97,8 +97,6 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
const void *value, size_t value_len, int flags)
{
struct p9_fid *fid = v9fs_fid_lookup(dentry);
- if (IS_ERR(fid))
- return PTR_ERR(fid);
return v9fs_fid_xattr_set(fid, name, value, value_len, flags);
}
@@ -115,7 +113,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
name, value_len, flags);
/* Clone it */
- fid = p9_client_walk(fid, 0, NULL, 1);
+ fid = clone_fid(fid);
if (IS_ERR(fid))
return PTR_ERR(fid);
diff --git a/fs/Kconfig b/fs/Kconfig
index 4524916fa200..2bc7ad775842 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -70,6 +70,12 @@ config FS_POSIX_ACL
config EXPORTFS
tristate
+config EXPORTFS_BLOCK_OPS
+ bool "Enable filesystem export operations for block IO"
+ help
+ This option enables the export operations for a filesystem to support
+ external block IO.
+
config FILE_LOCKING
bool "Enable POSIX file locking API" if EXPERT
default y
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 72c03354c14b..c7efddf6e038 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -89,7 +89,8 @@ config BINFMT_SCRIPT
config BINFMT_FLAT
bool "Kernel support for flat binaries"
- depends on !MMU && (!FRV || BROKEN)
+ depends on !MMU || M68K
+ depends on !FRV || BROKEN
help
Support uClinux FLAT format binaries.
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index bec25f7017c0..29444c83da48 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -101,7 +101,7 @@ out:
}
static int
-adfs_match(struct qstr *name, struct object_info *obj)
+adfs_match(const struct qstr *name, struct object_info *obj)
{
int i;
@@ -126,7 +126,7 @@ adfs_match(struct qstr *name, struct object_info *obj)
}
static int
-adfs_dir_lookup_byname(struct inode *inode, struct qstr *name, struct object_info *obj)
+adfs_dir_lookup_byname(struct inode *inode, const struct qstr *name, struct object_info *obj)
{
struct super_block *sb = inode->i_sb;
const struct adfs_dir_ops *ops = ADFS_SB(sb)->s_dir;
@@ -227,7 +227,7 @@ adfs_hash(const struct dentry *parent, struct qstr *qstr)
* requirements of the underlying filesystem.
*/
static int
-adfs_compare(const struct dentry *parent, const struct dentry *dentry,
+adfs_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
int i;
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c
index d6c7a51c93e4..d8f217c711d3 100644
--- a/fs/affs/amigaffs.c
+++ b/fs/affs/amigaffs.c
@@ -472,9 +472,7 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
bool
affs_nofilenametruncate(const struct dentry *dentry)
{
- struct inode *inode = d_inode(dentry);
-
- return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE);
+ return affs_test_opt(AFFS_SB(dentry->d_sb)->s_flags, SF_NO_TRUNCATE);
}
/* Check if the name is valid for a affs object. */
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index eb32029bc776..a2d68f828d53 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -14,11 +14,11 @@ typedef int (*toupper_t)(int);
static int affs_toupper(int ch);
static int affs_hash_dentry(const struct dentry *, struct qstr *);
-static int affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+static int affs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
static int affs_intl_toupper(int ch);
static int affs_intl_hash_dentry(const struct dentry *, struct qstr *);
-static int affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+static int affs_intl_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
const struct dentry_operations affs_dentry_operations = {
@@ -131,20 +131,20 @@ static inline int __affs_compare_dentry(unsigned int len,
}
static int
-affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+affs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return __affs_compare_dentry(len, str, name, affs_toupper,
- affs_nofilenametruncate(parent));
+ affs_nofilenametruncate(dentry));
}
static int
-affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+affs_intl_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return __affs_compare_dentry(len, str, name, affs_intl_toupper,
- affs_nofilenametruncate(parent));
+ affs_nofilenametruncate(dentry));
}
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 3767f6641af1..fa84bb8832e0 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -159,7 +159,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *parent = dentry->d_parent;
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
unsigned int len = name->len;
unsigned int hash = name->hash;
const unsigned char *str = name->name;
@@ -172,7 +172,7 @@ static struct dentry *autofs4_lookup_active(struct dentry *dentry)
list_for_each(p, head) {
struct autofs_info *ino;
struct dentry *active;
- struct qstr *qstr;
+ const struct qstr *qstr;
ino = list_entry(p, struct autofs_info, active);
active = ino->dentry;
@@ -214,7 +214,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry,
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct dentry *parent = dentry->d_parent;
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
unsigned int len = name->len;
unsigned int hash = name->hash;
const unsigned char *str = name->name;
@@ -227,7 +227,7 @@ static struct dentry *autofs4_lookup_expiring(struct dentry *dentry,
list_for_each(p, head) {
struct autofs_info *ino;
struct dentry *expiring;
- struct qstr *qstr;
+ const struct qstr *qstr;
if (rcu_walk) {
spin_unlock(&sbi->lookup_lock);
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 708214457d16..431fd7ee3488 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -225,7 +225,7 @@ rename_retry:
}
static struct autofs_wait_queue *
-autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
+autofs4_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr)
{
struct autofs_wait_queue *wq;
@@ -249,7 +249,7 @@ autofs4_find_wait(struct autofs_sb_info *sbi, struct qstr *qstr)
*/
static int validate_request(struct autofs_wait_queue **wait,
struct autofs_sb_info *sbi,
- struct qstr *qstr,
+ const struct qstr *qstr,
struct dentry *dentry, enum autofs_notify notify)
{
struct autofs_wait_queue *wq;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 203589311bf8..464a972e88c1 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -67,8 +67,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
struct elf_fdpic_params *);
#ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
- unsigned long *);
static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
struct file *,
struct mm_struct *);
@@ -515,8 +513,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
sp = mm->start_stack;
/* stack the program arguments and environment */
- if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
+ if (transfer_args_to_stack(bprm, &sp) < 0)
return -EFAULT;
+ sp &= ~15;
#endif
/*
@@ -711,39 +710,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
/*****************************************************************************/
/*
- * transfer the program arguments and environment from the holding pages onto
- * the stack
- */
-#ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
- unsigned long *_sp)
-{
- unsigned long index, stop, sp;
- char *src;
- int ret = 0;
-
- stop = bprm->p >> PAGE_SHIFT;
- sp = *_sp;
-
- for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
- src = kmap(bprm->page[index]);
- sp -= PAGE_SIZE;
- if (copy_to_user((void *) sp, src, PAGE_SIZE) != 0)
- ret = -EFAULT;
- kunmap(bprm->page[index]);
- if (ret < 0)
- goto out;
- }
-
- *_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
-
-out:
- return ret;
-}
-#endif
-
-/*****************************************************************************/
-/*
* load the appropriate binary image (executable or interpreter) into memory
* - we assume no MMU is available
* - if no other PIC bits are set in params->hdr->e_flags
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index caf9e39bb82b..9b2917a30294 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -15,7 +15,8 @@
* JAN/99 -- coded full program relocation (gerg@snapgear.com)
*/
-#include <linux/export.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -25,8 +26,6 @@
#include <linux/string.h>
#include <linux/fs.h>
#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/slab.h>
@@ -34,26 +33,16 @@
#include <linux/personality.h>
#include <linux/init.h>
#include <linux/flat.h>
-#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
#include <asm/byteorder.h>
-#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/cacheflush.h>
#include <asm/page.h>
/****************************************************************************/
-#if 0
-#define DEBUG 1
-#endif
-
-#ifdef DEBUG
-#define DBG_FLT(a...) printk(a)
-#else
-#define DBG_FLT(a...)
-#endif
-
/*
* User data (data section and bss) needs to be aligned.
* We pick 0x20 here because it is the max value elf2flt has always
@@ -80,7 +69,7 @@ struct lib_info {
unsigned long text_len; /* Length of text segment */
unsigned long entry; /* Start address for this module */
unsigned long build_date; /* When this one was compiled */
- short loaded; /* Has this library been loaded? */
+ bool loaded; /* Has this library been loaded? */
} lib_list[MAX_SHARED_LIBS];
};
@@ -106,59 +95,67 @@ static struct linux_binfmt flat_format = {
static int flat_core_dump(struct coredump_params *cprm)
{
- printk("Process %s:%d received signr %d and should have core dumped\n",
- current->comm, current->pid, (int) cprm->siginfo->si_signo);
- return(1);
+ pr_warn("Process %s:%d received signr %d and should have core dumped\n",
+ current->comm, current->pid, cprm->siginfo->si_signo);
+ return 1;
}
/****************************************************************************/
/*
* create_flat_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
+ * addresses on the "stack", recording the new stack pointer value.
*/
-static unsigned long create_flat_tables(
- unsigned long pp,
- struct linux_binprm * bprm)
+static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start)
{
- unsigned long *argv,*envp;
- unsigned long * sp;
- char * p = (char*)pp;
- int argc = bprm->argc;
- int envc = bprm->envc;
- char uninitialized_var(dummy);
-
- sp = (unsigned long *)p;
- sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
- sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
- argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
- envp = argv + (argc + 1);
+ char __user *p;
+ unsigned long __user *sp;
+ long i, len;
+
+ p = (char __user *)arg_start;
+ sp = (unsigned long __user *)current->mm->start_stack;
+
+ sp -= bprm->envc + 1;
+ sp -= bprm->argc + 1;
+ sp -= flat_argvp_envp_on_stack() ? 2 : 0;
+ sp -= 1; /* &argc */
+ current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
+ sp = (unsigned long __user *)current->mm->start_stack;
+
+ __put_user(bprm->argc, sp++);
if (flat_argvp_envp_on_stack()) {
- put_user((unsigned long) envp, sp + 2);
- put_user((unsigned long) argv, sp + 1);
- }
-
- put_user(argc, sp);
- current->mm->arg_start = (unsigned long) p;
- while (argc-->0) {
- put_user((unsigned long) p, argv++);
- do {
- get_user(dummy, p); p++;
- } while (dummy);
- }
- put_user((unsigned long) NULL, argv);
- current->mm->arg_end = current->mm->env_start = (unsigned long) p;
- while (envc-->0) {
- put_user((unsigned long)p, envp); envp++;
- do {
- get_user(dummy, p); p++;
- } while (dummy);
- }
- put_user((unsigned long) NULL, envp);
- current->mm->env_end = (unsigned long) p;
- return (unsigned long)sp;
+ unsigned long argv, envp;
+ argv = (unsigned long)(sp + 2);
+ envp = (unsigned long)(sp + 2 + bprm->argc + 1);
+ __put_user(argv, sp++);
+ __put_user(envp, sp++);
+ }
+
+ current->mm->arg_start = (unsigned long)p;
+ for (i = bprm->argc; i > 0; i--) {
+ __put_user((unsigned long)p, sp++);
+ len = strnlen_user(p, MAX_ARG_STRLEN);
+ if (!len || len > MAX_ARG_STRLEN)
+ return -EINVAL;
+ p += len;
+ }
+ __put_user(0, sp++);
+ current->mm->arg_end = (unsigned long)p;
+
+ current->mm->env_start = (unsigned long) p;
+ for (i = bprm->envc; i > 0; i--) {
+ __put_user((unsigned long)p, sp++);
+ len = strnlen_user(p, MAX_ARG_STRLEN);
+ if (!len || len > MAX_ARG_STRLEN)
+ return -EINVAL;
+ p += len;
+ }
+ __put_user(0, sp++);
+ current->mm->env_end = (unsigned long)p;
+
+ return 0;
}
/****************************************************************************/
@@ -190,17 +187,17 @@ static int decompress_exec(
loff_t fpos;
int ret, retval;
- DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
+ pr_debug("decompress_exec(offset=%lx,buf=%p,len=%lx)\n", offset, dst, len);
memset(&strm, 0, sizeof(strm));
strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
if (strm.workspace == NULL) {
- DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
+ pr_debug("no memory for decompress workspace\n");
return -ENOMEM;
}
buf = kmalloc(LBUFSIZE, GFP_KERNEL);
if (buf == NULL) {
- DBG_FLT("binfmt_flat: no memory for read buffer\n");
+ pr_debug("no memory for read buffer\n");
retval = -ENOMEM;
goto out_free;
}
@@ -218,49 +215,49 @@ static int decompress_exec(
/* Check minimum size -- gzip header */
if (ret < 10) {
- DBG_FLT("binfmt_flat: file too small?\n");
+ pr_debug("file too small?\n");
goto out_free_buf;
}
/* Check gzip magic number */
if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
- DBG_FLT("binfmt_flat: unknown compression magic?\n");
+ pr_debug("unknown compression magic?\n");
goto out_free_buf;
}
/* Check gzip method */
if (buf[2] != 8) {
- DBG_FLT("binfmt_flat: unknown compression method?\n");
+ pr_debug("unknown compression method?\n");
goto out_free_buf;
}
/* Check gzip flags */
if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
(buf[3] & RESERVED)) {
- DBG_FLT("binfmt_flat: unknown flags?\n");
+ pr_debug("unknown flags?\n");
goto out_free_buf;
}
ret = 10;
if (buf[3] & EXTRA_FIELD) {
ret += 2 + buf[10] + (buf[11] << 8);
- if (unlikely(LBUFSIZE <= ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
+ if (unlikely(ret >= LBUFSIZE)) {
+ pr_debug("buffer overflow (EXTRA)?\n");
goto out_free_buf;
}
}
if (buf[3] & ORIG_NAME) {
while (ret < LBUFSIZE && buf[ret++] != 0)
;
- if (unlikely(LBUFSIZE == ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
+ if (unlikely(ret == LBUFSIZE)) {
+ pr_debug("buffer overflow (ORIG_NAME)?\n");
goto out_free_buf;
}
}
if (buf[3] & COMMENT) {
while (ret < LBUFSIZE && buf[ret++] != 0)
;
- if (unlikely(LBUFSIZE == ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
+ if (unlikely(ret == LBUFSIZE)) {
+ pr_debug("buffer overflow (COMMENT)?\n");
goto out_free_buf;
}
}
@@ -273,7 +270,7 @@ static int decompress_exec(
strm.total_out = 0;
if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
- DBG_FLT("binfmt_flat: zlib init failed?\n");
+ pr_debug("zlib init failed?\n");
goto out_free_buf;
}
@@ -290,7 +287,7 @@ static int decompress_exec(
}
if (ret < 0) {
- DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
+ pr_debug("decompression failed (%d), %s\n",
ret, strm.msg);
goto out_zlib;
}
@@ -327,24 +324,23 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
r &= 0x00ffffff; /* Trim ID off here */
}
if (id >= MAX_SHARED_LIBS) {
- printk("BINFMT_FLAT: reference 0x%x to shared library %d",
- (unsigned) r, id);
+ pr_err("reference 0x%lx to shared library %d", r, id);
goto failed;
}
if (curid != id) {
if (internalp) {
- printk("BINFMT_FLAT: reloc address 0x%x not in same module "
- "(%d != %d)", (unsigned) r, curid, id);
+ pr_err("reloc address 0x%lx not in same module "
+ "(%d != %d)", r, curid, id);
goto failed;
- } else if ( ! p->lib_list[id].loaded &&
- load_flat_shared_library(id, p) < 0) {
- printk("BINFMT_FLAT: failed to load library %d", id);
+ } else if (!p->lib_list[id].loaded &&
+ load_flat_shared_library(id, p) < 0) {
+ pr_err("failed to load library %d", id);
goto failed;
}
/* Check versioning information (i.e. time stamps) */
if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
p->lib_list[curid].build_date < p->lib_list[id].build_date) {
- printk("BINFMT_FLAT: library %d is younger than %d", id, curid);
+ pr_err("library %d is younger than %d", id, curid);
goto failed;
}
}
@@ -358,8 +354,8 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
text_len = p->lib_list[id].text_len;
if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
- printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
- (int) r,(int)(start_brk-start_data+text_len),(int)text_len);
+ pr_err("reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
+ r, start_brk-start_data+text_len, text_len);
goto failed;
}
@@ -369,10 +365,10 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
addr = r - text_len + start_data;
/* Range checked already above so doing the range tests is redundant...*/
- return(addr);
+ return addr;
failed:
- printk(", killing %s!\n", current->comm);
+ pr_cont(", killing %s!\n", current->comm);
send_sig(SIGSEGV, current, 0);
return RELOC_FAILED;
@@ -382,62 +378,57 @@ failed:
static void old_reloc(unsigned long rl)
{
-#ifdef DEBUG
- char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
-#endif
+ static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
flat_v2_reloc_t r;
- unsigned long *ptr;
-
+ unsigned long __user *ptr;
+ unsigned long val;
+
r.value = rl;
#if defined(CONFIG_COLDFIRE)
- ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset);
+ ptr = (unsigned long __user *)(current->mm->start_code + r.reloc.offset);
#else
- ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset);
+ ptr = (unsigned long __user *)(current->mm->start_data + r.reloc.offset);
#endif
+ get_user(val, ptr);
+
+ pr_debug("Relocation of variable at DATASEG+%x "
+ "(address %p, currently %lx) into segment %s\n",
+ r.reloc.offset, ptr, val, segment[r.reloc.type]);
-#ifdef DEBUG
- printk("Relocation of variable at DATASEG+%x "
- "(address %p, currently %x) into segment %s\n",
- r.reloc.offset, ptr, (int)*ptr, segment[r.reloc.type]);
-#endif
-
switch (r.reloc.type) {
case OLD_FLAT_RELOC_TYPE_TEXT:
- *ptr += current->mm->start_code;
+ val += current->mm->start_code;
break;
case OLD_FLAT_RELOC_TYPE_DATA:
- *ptr += current->mm->start_data;
+ val += current->mm->start_data;
break;
case OLD_FLAT_RELOC_TYPE_BSS:
- *ptr += current->mm->end_data;
+ val += current->mm->end_data;
break;
default:
- printk("BINFMT_FLAT: Unknown relocation type=%x\n", r.reloc.type);
+ pr_err("Unknown relocation type=%x\n", r.reloc.type);
break;
}
+ put_user(val, ptr);
-#ifdef DEBUG
- printk("Relocation became %x\n", (int)*ptr);
-#endif
-}
+ pr_debug("Relocation became %lx\n", val);
+}
/****************************************************************************/
-static int load_flat_file(struct linux_binprm * bprm,
+static int load_flat_file(struct linux_binprm *bprm,
struct lib_info *libinfo, int id, unsigned long *extra_stack)
{
- struct flat_hdr * hdr;
- unsigned long textpos = 0, datapos = 0, result;
- unsigned long realdatastart = 0;
- unsigned long text_len, data_len, bss_len, stack_len, flags;
- unsigned long full_data;
- unsigned long len, memp = 0;
- unsigned long memp_size, extra, rlim;
- unsigned long *reloc = 0, *rp;
+ struct flat_hdr *hdr;
+ unsigned long textpos, datapos, realdatastart;
+ unsigned long text_len, data_len, bss_len, stack_len, full_data, flags;
+ unsigned long len, memp, memp_size, extra, rlim;
+ unsigned long __user *reloc, *rp;
struct inode *inode;
- int i, rev, relocs = 0;
+ int i, rev, relocs;
loff_t fpos;
unsigned long start_code, end_code;
+ ssize_t result;
int ret;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
@@ -469,20 +460,30 @@ static int load_flat_file(struct linux_binprm * bprm,
}
if (flags & FLAT_FLAG_KTRACE)
- printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
+ pr_info("Loading file: %s\n", bprm->filename);
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
- printk("BINFMT_FLAT: bad flat file version 0x%x (supported "
- "0x%lx and 0x%lx)\n",
- rev, FLAT_VERSION, OLD_FLAT_VERSION);
+ pr_err("bad flat file version 0x%x (supported 0x%lx and 0x%lx)\n",
+ rev, FLAT_VERSION, OLD_FLAT_VERSION);
ret = -ENOEXEC;
goto err;
}
-
+
/* Don't allow old format executables to use shared libraries */
if (rev == OLD_FLAT_VERSION && id != 0) {
- printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
- (int) FLAT_VERSION);
+ pr_err("shared libraries are not available before rev 0x%lx\n",
+ FLAT_VERSION);
+ ret = -ENOEXEC;
+ goto err;
+ }
+
+ /*
+ * Make sure the header params are sane.
+ * 28 bits (256 MB) is way more than reasonable in this case.
+ * If some top bits are set we have probable binary corruption.
+ */
+ if ((text_len | data_len | bss_len | stack_len | full_data) >> 28) {
+ pr_err("bad header\n");
ret = -ENOEXEC;
goto err;
}
@@ -496,7 +497,7 @@ static int load_flat_file(struct linux_binprm * bprm,
#ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
- printk("Support for ZFLAT executables is not enabled.\n");
+ pr_err("Support for ZFLAT executables is not enabled.\n");
ret = -ENOEXEC;
goto err;
}
@@ -517,11 +518,9 @@ static int load_flat_file(struct linux_binprm * bprm,
/* Flush all traces of the currently running executable */
if (id == 0) {
- result = flush_old_exec(bprm);
- if (result) {
- ret = result;
+ ret = flush_old_exec(bprm);
+ if (ret)
goto err;
- }
/* OK, This is the point of no return */
set_personality(PER_LINUX_32BIT);
@@ -539,48 +538,48 @@ static int load_flat_file(struct linux_binprm * bprm,
* case, and then the fully copied to RAM case which lumps
* it all together.
*/
- if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
+ if (!IS_ENABLED(CONFIG_MMU) && !(flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))) {
/*
* this should give us a ROM ptr, but if it doesn't we don't
* really care
*/
- DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
+ pr_debug("ROM mapping of file (we hope)\n");
textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
MAP_PRIVATE|MAP_EXECUTABLE, 0);
if (!textpos || IS_ERR_VALUE(textpos)) {
- if (!textpos)
- textpos = (unsigned long) -ENOMEM;
- printk("Unable to mmap process text, errno %d\n", (int)-textpos);
ret = textpos;
+ if (!textpos)
+ ret = -ENOMEM;
+ pr_err("Unable to mmap process text, errno %d\n", ret);
goto err;
}
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
len = PAGE_ALIGN(len);
- realdatastart = vm_mmap(0, 0, len,
+ realdatastart = vm_mmap(NULL, 0, len,
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
+ ret = realdatastart;
if (!realdatastart)
- realdatastart = (unsigned long) -ENOMEM;
- printk("Unable to allocate RAM for process data, errno %d\n",
- (int)-realdatastart);
+ ret = -ENOMEM;
+ pr_err("Unable to allocate RAM for process data, "
+ "errno %d\n", ret);
vm_munmap(textpos, text_len);
- ret = realdatastart;
goto err;
}
datapos = ALIGN(realdatastart +
MAX_SHARED_LIBS * sizeof(unsigned long),
FLAT_DATA_ALIGN);
- DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
- (int)(data_len + bss_len + stack_len), (int)datapos);
+ pr_debug("Allocated data+bss+stack (%ld bytes): %lx\n",
+ data_len + bss_len + stack_len, datapos);
fpos = ntohl(hdr->data_start);
#ifdef CONFIG_BINFMT_ZFLAT
if (flags & FLAT_FLAG_GZDATA) {
- result = decompress_exec(bprm, fpos, (char *) datapos,
+ result = decompress_exec(bprm, fpos, (char *)datapos,
full_data, 0);
} else
#endif
@@ -589,29 +588,30 @@ static int load_flat_file(struct linux_binprm * bprm,
full_data);
}
if (IS_ERR_VALUE(result)) {
- printk("Unable to read data+bss, errno %d\n", (int)-result);
+ ret = result;
+ pr_err("Unable to read data+bss, errno %d\n", ret);
vm_munmap(textpos, text_len);
vm_munmap(realdatastart, len);
- ret = result;
goto err;
}
- reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
+ reloc = (unsigned long __user *)
+ (datapos + (ntohl(hdr->reloc_start) - text_len));
memp = realdatastart;
memp_size = len;
} else {
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
len = PAGE_ALIGN(len);
- textpos = vm_mmap(0, 0, len,
+ textpos = vm_mmap(NULL, 0, len,
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
if (!textpos || IS_ERR_VALUE(textpos)) {
- if (!textpos)
- textpos = (unsigned long) -ENOMEM;
- printk("Unable to allocate RAM for process text/data, errno %d\n",
- (int)-textpos);
ret = textpos;
+ if (!textpos)
+ ret = -ENOMEM;
+ pr_err("Unable to allocate RAM for process text/data, "
+ "errno %d\n", ret);
goto err;
}
@@ -620,7 +620,7 @@ static int load_flat_file(struct linux_binprm * bprm,
MAX_SHARED_LIBS * sizeof(unsigned long),
FLAT_DATA_ALIGN);
- reloc = (unsigned long *)
+ reloc = (unsigned long __user *)
(datapos + (ntohl(hdr->reloc_start) - text_len));
memp = textpos;
memp_size = len;
@@ -629,21 +629,59 @@ static int load_flat_file(struct linux_binprm * bprm,
* load it all in and treat it like a RAM load from now on
*/
if (flags & FLAT_FLAG_GZIP) {
- result = decompress_exec(bprm, sizeof (struct flat_hdr),
- (((char *) textpos) + sizeof (struct flat_hdr)),
+#ifndef CONFIG_MMU
+ result = decompress_exec(bprm, sizeof(struct flat_hdr),
+ (((char *)textpos) + sizeof(struct flat_hdr)),
(text_len + full_data
- - sizeof (struct flat_hdr)),
+ - sizeof(struct flat_hdr)),
0);
memmove((void *) datapos, (void *) realdatastart,
full_data);
+#else
+ /*
+ * This is used on MMU systems mainly for testing.
+ * Let's use a kernel buffer to simplify things.
+ */
+ long unz_text_len = text_len - sizeof(struct flat_hdr);
+ long unz_len = unz_text_len + full_data;
+ char *unz_data = vmalloc(unz_len);
+ if (!unz_data) {
+ result = -ENOMEM;
+ } else {
+ result = decompress_exec(bprm, sizeof(struct flat_hdr),
+ unz_data, unz_len, 0);
+ if (result == 0 &&
+ (copy_to_user((void __user *)textpos + sizeof(struct flat_hdr),
+ unz_data, unz_text_len) ||
+ copy_to_user((void __user *)datapos,
+ unz_data + unz_text_len, full_data)))
+ result = -EFAULT;
+ vfree(unz_data);
+ }
+#endif
} else if (flags & FLAT_FLAG_GZDATA) {
result = read_code(bprm->file, textpos, 0, text_len);
- if (!IS_ERR_VALUE(result))
+ if (!IS_ERR_VALUE(result)) {
+#ifndef CONFIG_MMU
result = decompress_exec(bprm, text_len, (char *) datapos,
full_data, 0);
- }
- else
+#else
+ char *unz_data = vmalloc(full_data);
+ if (!unz_data) {
+ result = -ENOMEM;
+ } else {
+ result = decompress_exec(bprm, text_len,
+ unz_data, full_data, 0);
+ if (result == 0 &&
+ copy_to_user((void __user *)datapos,
+ unz_data, full_data))
+ result = -EFAULT;
+ vfree(unz_data);
+ }
#endif
+ }
+ } else
+#endif /* CONFIG_BINFMT_ZFLAT */
{
result = read_code(bprm->file, textpos, 0, text_len);
if (!IS_ERR_VALUE(result))
@@ -652,21 +690,19 @@ static int load_flat_file(struct linux_binprm * bprm,
full_data);
}
if (IS_ERR_VALUE(result)) {
- printk("Unable to read code+data+bss, errno %d\n",(int)-result);
+ ret = result;
+ pr_err("Unable to read code+data+bss, errno %d\n", ret);
vm_munmap(textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
- ret = result;
goto err;
}
}
- if (flags & FLAT_FLAG_KTRACE)
- printk("Mapping is %x, Entry point is %x, data_start is %x\n",
- (int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
+ start_code = textpos + sizeof(struct flat_hdr);
+ end_code = textpos + text_len;
+ text_len -= sizeof(struct flat_hdr); /* the real code len */
/* The main program needs a little extra setup in the task structure */
- start_code = textpos + sizeof (struct flat_hdr);
- end_code = textpos + text_len;
if (id == 0) {
current->mm->start_code = start_code;
current->mm->end_code = end_code;
@@ -681,19 +717,19 @@ static int load_flat_file(struct linux_binprm * bprm,
*/
current->mm->start_brk = datapos + data_len + bss_len;
current->mm->brk = (current->mm->start_brk + 3) & ~3;
+#ifndef CONFIG_MMU
current->mm->context.end_brk = memp + memp_size - stack_len;
+#endif
}
- if (flags & FLAT_FLAG_KTRACE)
- printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
+ if (flags & FLAT_FLAG_KTRACE) {
+ pr_info("Mapping is %lx, Entry point is %x, data_start is %x\n",
+ textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
+ pr_info("%s %s: TEXT=%lx-%lx DATA=%lx-%lx BSS=%lx-%lx\n",
id ? "Lib" : "Load", bprm->filename,
- (int) start_code, (int) end_code,
- (int) datapos,
- (int) (datapos + data_len),
- (int) (datapos + data_len),
- (int) (((datapos + data_len + bss_len) + 3) & ~3));
-
- text_len -= sizeof(struct flat_hdr); /* the real code len */
+ start_code, end_code, datapos, datapos + data_len,
+ datapos + data_len, (datapos + data_len + bss_len + 3) & ~3);
+ }
/* Store the current module values into the global library structure */
libinfo->lib_list[id].start_code = start_code;
@@ -703,7 +739,7 @@ static int load_flat_file(struct linux_binprm * bprm,
libinfo->lib_list[id].loaded = 1;
libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
-
+
/*
* We just load the allocations into some temporary memory to
* help simplify all this mumbo jumbo
@@ -717,15 +753,20 @@ static int load_flat_file(struct linux_binprm * bprm,
* image.
*/
if (flags & FLAT_FLAG_GOTPIC) {
- for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) {
- unsigned long addr;
- if (*rp) {
- addr = calc_reloc(*rp, libinfo, id, 0);
+ for (rp = (unsigned long __user *)datapos; ; rp++) {
+ unsigned long addr, rp_val;
+ if (get_user(rp_val, rp))
+ return -EFAULT;
+ if (rp_val == 0xffffffff)
+ break;
+ if (rp_val) {
+ addr = calc_reloc(rp_val, libinfo, id, 0);
if (addr == RELOC_FAILED) {
ret = -ENOEXEC;
goto err;
}
- *rp = addr;
+ if (put_user(addr, rp))
+ return -EFAULT;
}
}
}
@@ -742,19 +783,23 @@ static int load_flat_file(struct linux_binprm * bprm,
* __start to address 4 so that is okay).
*/
if (rev > OLD_FLAT_VERSION) {
- unsigned long persistent = 0;
- for (i=0; i < relocs; i++) {
+ unsigned long __maybe_unused persistent = 0;
+ for (i = 0; i < relocs; i++) {
unsigned long addr, relval;
- /* Get the address of the pointer to be
- relocated (of course, the address has to be
- relocated first). */
- relval = ntohl(reloc[i]);
- if (flat_set_persistent (relval, &persistent))
+ /*
+ * Get the address of the pointer to be
+ * relocated (of course, the address has to be
+ * relocated first).
+ */
+ if (get_user(relval, reloc + i))
+ return -EFAULT;
+ relval = ntohl(relval);
+ if (flat_set_persistent(relval, &persistent))
continue;
addr = flat_get_relocate_addr(relval);
- rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
- if (rp == (unsigned long *)RELOC_FAILED) {
+ rp = (unsigned long __user *)calc_reloc(addr, libinfo, id, 1);
+ if (rp == (unsigned long __user *)RELOC_FAILED) {
ret = -ENOEXEC;
goto err;
}
@@ -780,17 +825,23 @@ static int load_flat_file(struct linux_binprm * bprm,
}
}
} else {
- for (i=0; i < relocs; i++)
- old_reloc(ntohl(reloc[i]));
+ for (i = 0; i < relocs; i++) {
+ unsigned long relval;
+ if (get_user(relval, reloc + i))
+ return -EFAULT;
+ relval = ntohl(relval);
+ old_reloc(relval);
+ }
}
-
+
flush_icache_range(start_code, end_code);
/* zero the BSS, BRK and stack areas */
- memset((void*)(datapos + data_len), 0, bss_len +
- (memp + memp_size - stack_len - /* end brk */
- libinfo->lib_list[id].start_brk) + /* start brk */
- stack_len);
+ if (clear_user((void __user *)(datapos + data_len), bss_len +
+ (memp + memp_size - stack_len - /* end brk */
+ libinfo->lib_list[id].start_brk) + /* start brk */
+ stack_len))
+ return -EFAULT;
return 0;
err:
@@ -846,7 +897,7 @@ out:
allow_write_access(bprm.file);
fput(bprm.file);
- return(res);
+ return res;
}
#endif /* CONFIG_BINFMT_SHARED_FLAT */
@@ -857,18 +908,17 @@ out:
* libraries. There is no binary dependent code anywhere else.
*/
-static int load_flat_binary(struct linux_binprm * bprm)
+static int load_flat_binary(struct linux_binprm *bprm)
{
struct lib_info libinfo;
struct pt_regs *regs = current_pt_regs();
- unsigned long p = bprm->p;
- unsigned long stack_len;
+ unsigned long stack_len = 0;
unsigned long start_addr;
- unsigned long *sp;
int res;
int i, j;
memset(&libinfo, 0, sizeof(libinfo));
+
/*
* We have to add the size of our arguments to our stack size
* otherwise it's too easy for users to create stack overflows
@@ -876,38 +926,54 @@ static int load_flat_binary(struct linux_binprm * bprm)
* pedantic and include space for the argv/envp array as it may have
* a lot of entries.
*/
-#define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
- stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
- stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
- stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
- stack_len += FLAT_STACK_ALIGN - 1; /* reserve for upcoming alignment */
-
+#ifndef CONFIG_MMU
+ stack_len += PAGE_SIZE * MAX_ARG_PAGES - bprm->p; /* the strings */
+#endif
+ stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
+ stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
+ stack_len = ALIGN(stack_len, FLAT_STACK_ALIGN);
+
res = load_flat_file(bprm, &libinfo, 0, &stack_len);
if (res < 0)
return res;
-
+
/* Update data segment pointers for all libraries */
- for (i=0; i<MAX_SHARED_LIBS; i++)
- if (libinfo.lib_list[i].loaded)
- for (j=0; j<MAX_SHARED_LIBS; j++)
- (-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
- (libinfo.lib_list[j].loaded)?
- libinfo.lib_list[j].start_data:UNLOADED_LIB;
+ for (i = 0; i < MAX_SHARED_LIBS; i++) {
+ if (!libinfo.lib_list[i].loaded)
+ continue;
+ for (j = 0; j < MAX_SHARED_LIBS; j++) {
+ unsigned long val = libinfo.lib_list[j].loaded ?
+ libinfo.lib_list[j].start_data : UNLOADED_LIB;
+ unsigned long __user *p = (unsigned long __user *)
+ libinfo.lib_list[i].start_data;
+ p -= j + 1;
+ if (put_user(val, p))
+ return -EFAULT;
+ }
+ }
install_exec_creds(bprm);
set_binfmt(&flat_format);
- p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
- DBG_FLT("p=%x\n", (int)p);
+#ifdef CONFIG_MMU
+ res = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
+ if (!res)
+ res = create_flat_tables(bprm, bprm->p);
+#else
+ /* Stash our initial stack pointer into the mm structure */
+ current->mm->start_stack =
+ ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
+ pr_debug("sp=%lx\n", current->mm->start_stack);
- /* copy the arg pages onto the stack, this could be more efficient :-) */
- for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
- * (char *) --p =
- ((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
+ /* copy the arg pages onto the stack */
+ res = transfer_args_to_stack(bprm, &current->mm->start_stack);
+ if (!res)
+ res = create_flat_tables(bprm, current->mm->start_stack);
+#endif
+ if (res)
+ return res;
- sp = (unsigned long *) create_flat_tables(p, bprm);
-
/* Fake some return addresses to ensure the call chain will
* initialise library in order for us. We are required to call
* lib 1 first, then 2, ... and finally the main program (id 0).
@@ -915,24 +981,24 @@ static int load_flat_binary(struct linux_binprm * bprm)
start_addr = libinfo.lib_list[0].entry;
#ifdef CONFIG_BINFMT_SHARED_FLAT
- for (i = MAX_SHARED_LIBS-1; i>0; i--) {
+ for (i = MAX_SHARED_LIBS-1; i > 0; i--) {
if (libinfo.lib_list[i].loaded) {
/* Push previos first to call address */
- --sp; put_user(start_addr, sp);
+ unsigned long __user *sp;
+ current->mm->start_stack -= sizeof(unsigned long);
+ sp = (unsigned long __user *)current->mm->start_stack;
+ __put_user(start_addr, sp);
start_addr = libinfo.lib_list[i].entry;
}
}
#endif
-
- /* Stash our initial stack pointer into the mm structure */
- current->mm->start_stack = (unsigned long )sp;
#ifdef FLAT_PLAT_INIT
FLAT_PLAT_INIT(regs);
#endif
- DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
- (int)regs, (int)start_addr, (int)current->mm->start_stack);
-
+
+ pr_debug("start_thread(regs=0x%p, entry=0x%lx, start_stack=0x%lx)\n",
+ regs, start_addr, current->mm->start_stack);
start_thread(regs, start_addr, current->mm->start_stack);
return 0;
@@ -945,9 +1011,6 @@ static int __init init_flat_binfmt(void)
register_binfmt(&flat_format);
return 0;
}
-
-/****************************************************************************/
-
core_initcall(init_flat_binfmt);
/****************************************************************************/
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 5417516f6e59..6103a6362ccd 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -26,6 +26,8 @@
#include <linux/fs.h>
#include <linux/uaccess.h>
+#include "internal.h"
+
#ifdef DEBUG
# define USE_DEBUG 1
#else
@@ -43,6 +45,7 @@ enum {Enabled, Magic};
#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
#define MISC_FMT_OPEN_BINARY (1 << 30)
#define MISC_FMT_CREDENTIALS (1 << 29)
+#define MISC_FMT_OPEN_FILE (1 << 28)
typedef struct {
struct list_head list;
@@ -54,6 +57,7 @@ typedef struct {
char *interpreter; /* filename of interpreter */
char *name;
struct dentry *dentry;
+ struct file *interp_file;
} Node;
static DEFINE_RWLOCK(entries_lock);
@@ -201,7 +205,13 @@ static int load_misc_binary(struct linux_binprm *bprm)
if (retval < 0)
goto error;
- interp_file = open_exec(iname);
+ if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) {
+ interp_file = filp_clone_open(fmt->interp_file);
+ if (!IS_ERR(interp_file))
+ deny_write_access(interp_file);
+ } else {
+ interp_file = open_exec(iname);
+ }
retval = PTR_ERR(interp_file);
if (IS_ERR(interp_file))
goto error;
@@ -285,6 +295,11 @@ static char *check_special_flags(char *sfs, Node *e)
e->flags |= (MISC_FMT_CREDENTIALS |
MISC_FMT_OPEN_BINARY);
break;
+ case 'F':
+ pr_debug("register: flag: F: open interpreter file now\n");
+ p++;
+ e->flags |= MISC_FMT_OPEN_FILE;
+ break;
default:
cont = 0;
}
@@ -543,6 +558,8 @@ static void entry_status(Node *e, char *page)
*dp++ = 'O';
if (e->flags & MISC_FMT_CREDENTIALS)
*dp++ = 'C';
+ if (e->flags & MISC_FMT_OPEN_FILE)
+ *dp++ = 'F';
*dp++ = '\n';
if (!test_bit(Magic, &e->flags)) {
@@ -590,6 +607,11 @@ static void kill_node(Node *e)
}
write_unlock(&entries_lock);
+ if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) {
+ filp_close(e->interp_file, NULL);
+ e->interp_file = NULL;
+ }
+
if (dentry) {
drop_nlink(d_inode(dentry));
d_drop(dentry);
@@ -696,6 +718,21 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
goto out2;
}
+ if (e->flags & MISC_FMT_OPEN_FILE) {
+ struct file *f;
+
+ f = open_exec(e->interpreter);
+ if (IS_ERR(f)) {
+ err = PTR_ERR(f);
+ pr_notice("register: failed to install interpreter file %s\n", e->interpreter);
+ simple_release_fs(&bm_mnt, &entry_count);
+ iput(inode);
+ inode = NULL;
+ goto out2;
+ }
+ e->interp_file = f;
+ }
+
e->dentry = dget(dentry);
inode->i_private = e;
inode->i_fop = &bm_entry_operations;
@@ -713,7 +750,7 @@ out:
if (err) {
kfree(e);
- return -EINVAL;
+ return err;
}
return count;
}
diff --git a/fs/block_dev.c b/fs/block_dev.c
index ada42cf42d06..c3cdde87cc8c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -416,7 +416,7 @@ int bdev_read_page(struct block_device *bdev, sector_t sector,
result = blk_queue_enter(bdev->bd_queue, false);
if (result)
return result;
- result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, READ);
+ result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, false);
blk_queue_exit(bdev->bd_queue);
return result;
}
@@ -445,7 +445,6 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
struct page *page, struct writeback_control *wbc)
{
int result;
- int rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE;
const struct block_device_operations *ops = bdev->bd_disk->fops;
if (!ops->rw_page || bdev_get_integrity(bdev))
@@ -455,7 +454,7 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
return result;
set_page_writeback(page);
- result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, rw);
+ result = ops->rw_page(bdev, sector + get_start_sect(bdev), page, true);
if (result)
end_page_writeback(page);
else
@@ -1275,11 +1274,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
bdev->bd_disk = disk;
bdev->bd_queue = disk->queue;
bdev->bd_contains = bdev;
- if (IS_ENABLED(CONFIG_BLK_DEV_DAX) &&
- blk_queue_dax(disk->queue))
- bdev->bd_inode->i_flags = S_DAX;
- else
- bdev->bd_inode->i_flags = 0;
+ bdev->bd_inode->i_flags = 0;
if (!partno) {
ret = -ENXIO;
diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c
index 67a607709d4f..53bb7af4e5f0 100644
--- a/fs/btrfs/acl.c
+++ b/fs/btrfs/acl.c
@@ -55,8 +55,7 @@ struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
}
if (size > 0) {
acl = posix_acl_from_xattr(&init_user_ns, value, size);
- } else if (size == -ENOENT || size == -ENODATA || size == 0) {
- /* FIXME, who returns -ENOENT? I think nobody */
+ } else if (size == -ERANGE || size == -ENODATA || size == 0) {
acl = NULL;
} else {
acl = ERR_PTR(-EIO);
diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c
index 5fb60ea7eee2..e0f071f6b5a7 100644
--- a/fs/btrfs/async-thread.c
+++ b/fs/btrfs/async-thread.c
@@ -34,6 +34,10 @@
struct __btrfs_workqueue {
struct workqueue_struct *normal_wq;
+
+ /* File system this workqueue services */
+ struct btrfs_fs_info *fs_info;
+
/* List head pointing to ordered work list */
struct list_head ordered_list;
@@ -70,6 +74,18 @@ void btrfs_##name(struct work_struct *arg) \
normal_work_helper(work); \
}
+struct btrfs_fs_info *
+btrfs_workqueue_owner(struct __btrfs_workqueue *wq)
+{
+ return wq->fs_info;
+}
+
+struct btrfs_fs_info *
+btrfs_work_owner(struct btrfs_work *work)
+{
+ return work->wq->fs_info;
+}
+
BTRFS_WORK_HELPER(worker_helper);
BTRFS_WORK_HELPER(delalloc_helper);
BTRFS_WORK_HELPER(flush_delalloc_helper);
@@ -94,14 +110,15 @@ BTRFS_WORK_HELPER(scrubnc_helper);
BTRFS_WORK_HELPER(scrubparity_helper);
static struct __btrfs_workqueue *
-__btrfs_alloc_workqueue(const char *name, unsigned int flags, int limit_active,
- int thresh)
+__btrfs_alloc_workqueue(struct btrfs_fs_info *fs_info, const char *name,
+ unsigned int flags, int limit_active, int thresh)
{
struct __btrfs_workqueue *ret = kzalloc(sizeof(*ret), GFP_KERNEL);
if (!ret)
return NULL;
+ ret->fs_info = fs_info;
ret->limit_active = limit_active;
atomic_set(&ret->pending, 0);
if (thresh == 0)
@@ -143,7 +160,8 @@ __btrfs_alloc_workqueue(const char *name, unsigned int flags, int limit_active,
static inline void
__btrfs_destroy_workqueue(struct __btrfs_workqueue *wq);
-struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
+struct btrfs_workqueue *btrfs_alloc_workqueue(struct btrfs_fs_info *fs_info,
+ const char *name,
unsigned int flags,
int limit_active,
int thresh)
@@ -153,7 +171,8 @@ struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
if (!ret)
return NULL;
- ret->normal = __btrfs_alloc_workqueue(name, flags & ~WQ_HIGHPRI,
+ ret->normal = __btrfs_alloc_workqueue(fs_info, name,
+ flags & ~WQ_HIGHPRI,
limit_active, thresh);
if (!ret->normal) {
kfree(ret);
@@ -161,8 +180,8 @@ struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
}
if (flags & WQ_HIGHPRI) {
- ret->high = __btrfs_alloc_workqueue(name, flags, limit_active,
- thresh);
+ ret->high = __btrfs_alloc_workqueue(fs_info, name, flags,
+ limit_active, thresh);
if (!ret->high) {
__btrfs_destroy_workqueue(ret->normal);
kfree(ret);
diff --git a/fs/btrfs/async-thread.h b/fs/btrfs/async-thread.h
index ad4d0647d1a6..8e52484cd461 100644
--- a/fs/btrfs/async-thread.h
+++ b/fs/btrfs/async-thread.h
@@ -21,6 +21,7 @@
#define __BTRFS_ASYNC_THREAD_
#include <linux/workqueue.h>
+struct btrfs_fs_info;
struct btrfs_workqueue;
/* Internal use only */
struct __btrfs_workqueue;
@@ -67,7 +68,8 @@ BTRFS_WORK_HELPER_PROTO(scrubnc_helper);
BTRFS_WORK_HELPER_PROTO(scrubparity_helper);
-struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
+struct btrfs_workqueue *btrfs_alloc_workqueue(struct btrfs_fs_info *fs_info,
+ const char *name,
unsigned int flags,
int limit_active,
int thresh);
@@ -80,4 +82,6 @@ void btrfs_queue_work(struct btrfs_workqueue *wq,
void btrfs_destroy_workqueue(struct btrfs_workqueue *wq);
void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
void btrfs_set_work_high_priority(struct btrfs_work *work);
+struct btrfs_fs_info *btrfs_work_owner(struct btrfs_work *work);
+struct btrfs_fs_info *btrfs_workqueue_owner(struct __btrfs_workqueue *wq);
#endif
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 8bb3509099e8..2b88439c2ee8 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -139,7 +139,7 @@ int __init btrfs_prelim_ref_init(void)
btrfs_prelim_ref_cache = kmem_cache_create("btrfs_prelim_ref",
sizeof(struct __prelim_ref),
0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ SLAB_MEM_SPREAD,
NULL);
if (!btrfs_prelim_ref_cache)
return -ENOMEM;
@@ -361,7 +361,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
goto out;
}
- if (btrfs_test_is_dummy_root(root)) {
+ if (btrfs_is_testing(fs_info)) {
srcu_read_unlock(&fs_info->subvol_srcu, index);
ret = -ENOENT;
goto out;
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index 5d5cae05818d..66789471b49d 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -2945,7 +2945,7 @@ static void __btrfsic_submit_bio(struct bio *bio)
printk(KERN_INFO
"submit_bio(rw=%d,0x%x, bi_vcnt=%u,"
" bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n",
- bio_op(bio), bio->bi_rw, bio->bi_vcnt,
+ bio_op(bio), bio->bi_opf, bio->bi_vcnt,
(unsigned long long)bio->bi_iter.bi_sector,
dev_bytenr, bio->bi_bdev);
@@ -2976,18 +2976,18 @@ static void __btrfsic_submit_bio(struct bio *bio)
btrfsic_process_written_block(dev_state, dev_bytenr,
mapped_datav, bio->bi_vcnt,
bio, &bio_is_patched,
- NULL, bio->bi_rw);
+ NULL, bio->bi_opf);
while (i > 0) {
i--;
kunmap(bio->bi_io_vec[i].bv_page);
}
kfree(mapped_datav);
- } else if (NULL != dev_state && (bio->bi_rw & REQ_PREFLUSH)) {
+ } else if (NULL != dev_state && (bio->bi_opf & REQ_PREFLUSH)) {
if (dev_state->state->print_mask &
BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH)
printk(KERN_INFO
"submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n",
- bio_op(bio), bio->bi_rw, bio->bi_bdev);
+ bio_op(bio), bio->bi_opf, bio->bi_bdev);
if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) {
if ((dev_state->state->print_mask &
(BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH |
@@ -3005,7 +3005,7 @@ static void __btrfsic_submit_bio(struct bio *bio)
block->never_written = 0;
block->iodone_w_error = 0;
block->flush_gen = dev_state->last_flush_gen + 1;
- block->submit_bio_bh_rw = bio->bi_rw;
+ block->submit_bio_bh_rw = bio->bi_opf;
block->orig_bio_bh_private = bio->bi_private;
block->orig_bio_bh_end_io.bio = bio->bi_end_io;
block->next_in_same_bio = NULL;
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index cefedabf0a92..029db6e1105c 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -403,7 +403,10 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
}
ret = btrfs_map_bio(root, bio, 0, 1);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret) {
+ bio->bi_error = ret;
+ bio_endio(bio);
+ }
bio_put(bio);
@@ -434,7 +437,10 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
}
ret = btrfs_map_bio(root, bio, 0, 1);
- BUG_ON(ret); /* -ENOMEM */
+ if (ret) {
+ bio->bi_error = ret;
+ bio_endio(bio);
+ }
bio_put(bio);
return 0;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index a85cf7d23309..d1c56c94dd5a 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1153,14 +1153,14 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
ret = update_ref_for_cow(trans, root, buf, cow, &last_ref);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
if (test_bit(BTRFS_ROOT_REF_COWS, &root->state)) {
ret = btrfs_reloc_cow_block(trans, root, buf, cow);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
}
@@ -1198,7 +1198,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
if (last_ref) {
ret = tree_mod_log_free_eb(root->fs_info, buf);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
}
@@ -1505,7 +1505,7 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct extent_buffer *buf)
{
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return 0;
/* ensure we can see the force_cow */
@@ -1771,6 +1771,14 @@ static noinline int generic_bin_search(struct extent_buffer *eb,
unsigned long map_len = 0;
int err;
+ if (low > high) {
+ btrfs_err(eb->fs_info,
+ "%s: low (%d) > high (%d) eb %llu owner %llu level %d",
+ __func__, low, high, eb->start,
+ btrfs_header_owner(eb), btrfs_header_level(eb));
+ return -EINVAL;
+ }
+
while (low < high) {
mid = (low + high) / 2;
offset = p + mid * item_size;
@@ -1858,7 +1866,6 @@ static void root_sub_used(struct btrfs_root *root, u32 size)
/* given a node and slot number, this reads the blocks it points to. The
* extent buffer is returned with a reference taken (but unlocked).
- * NULL is returned on error.
*/
static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
struct extent_buffer *parent, int slot)
@@ -1866,19 +1873,16 @@ static noinline struct extent_buffer *read_node_slot(struct btrfs_root *root,
int level = btrfs_header_level(parent);
struct extent_buffer *eb;
- if (slot < 0)
- return NULL;
- if (slot >= btrfs_header_nritems(parent))
- return NULL;
+ if (slot < 0 || slot >= btrfs_header_nritems(parent))
+ return ERR_PTR(-ENOENT);
BUG_ON(level == 0);
eb = read_tree_block(root, btrfs_node_blockptr(parent, slot),
btrfs_node_ptr_generation(parent, slot));
- if (IS_ERR(eb) || !extent_buffer_uptodate(eb)) {
- if (!IS_ERR(eb))
- free_extent_buffer(eb);
- eb = NULL;
+ if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) {
+ free_extent_buffer(eb);
+ eb = ERR_PTR(-EIO);
}
return eb;
@@ -1931,8 +1935,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
/* promote the child to a root */
child = read_node_slot(root, mid, 0);
- if (!child) {
- ret = -EROFS;
+ if (IS_ERR(child)) {
+ ret = PTR_ERR(child);
btrfs_handle_fs_error(root->fs_info, ret, NULL);
goto enospc;
}
@@ -1970,6 +1974,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
return 0;
left = read_node_slot(root, parent, pslot - 1);
+ if (IS_ERR(left))
+ left = NULL;
+
if (left) {
btrfs_tree_lock(left);
btrfs_set_lock_blocking(left);
@@ -1980,7 +1987,11 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
goto enospc;
}
}
+
right = read_node_slot(root, parent, pslot + 1);
+ if (IS_ERR(right))
+ right = NULL;
+
if (right) {
btrfs_tree_lock(right);
btrfs_set_lock_blocking(right);
@@ -2135,6 +2146,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
return 1;
left = read_node_slot(root, parent, pslot - 1);
+ if (IS_ERR(left))
+ left = NULL;
/* first, try to make some room in the middle buffer */
if (left) {
@@ -2185,6 +2198,8 @@ static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans,
free_extent_buffer(left);
}
right = read_node_slot(root, parent, pslot + 1);
+ if (IS_ERR(right))
+ right = NULL;
/*
* then try to empty the right most buffer into the middle
@@ -3240,7 +3255,7 @@ static int push_node_left(struct btrfs_trans_handle *trans,
ret = tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0,
push_items);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
copy_extent_buffer(dst, src,
@@ -3315,7 +3330,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
ret = tree_mod_log_eb_copy(root->fs_info, dst, src, 0,
src_nritems - push_items, push_items);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
copy_extent_buffer(dst, src,
@@ -3519,7 +3534,7 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
ret = tree_mod_log_eb_copy(root->fs_info, split, c, 0,
mid, c_nritems - mid);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
copy_extent_buffer(split, c,
@@ -3773,7 +3788,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_assert_tree_locked(path->nodes[1]);
right = read_node_slot(root, upper, slot + 1);
- if (right == NULL)
+ /*
+ * slot + 1 is not valid or we fail to read the right node,
+ * no big deal, just return.
+ */
+ if (IS_ERR(right))
return 1;
btrfs_tree_lock(right);
@@ -4003,7 +4022,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_assert_tree_locked(path->nodes[1]);
left = read_node_slot(root, path->nodes[1], slot - 1);
- if (left == NULL)
+ /*
+ * slot - 1 is not valid or we fail to read the left node,
+ * no big deal, just return.
+ */
+ if (IS_ERR(left))
return 1;
btrfs_tree_lock(left);
@@ -5210,7 +5233,10 @@ find_next_key:
}
btrfs_set_path_blocking(path);
cur = read_node_slot(root, cur, slot);
- BUG_ON(!cur); /* -ENOMEM */
+ if (IS_ERR(cur)) {
+ ret = PTR_ERR(cur);
+ goto out;
+ }
btrfs_tree_read_lock(cur);
@@ -5229,15 +5255,21 @@ out:
return ret;
}
-static void tree_move_down(struct btrfs_root *root,
+static int tree_move_down(struct btrfs_root *root,
struct btrfs_path *path,
int *level, int root_level)
{
+ struct extent_buffer *eb;
+
BUG_ON(*level == 0);
- path->nodes[*level - 1] = read_node_slot(root, path->nodes[*level],
- path->slots[*level]);
+ eb = read_node_slot(root, path->nodes[*level], path->slots[*level]);
+ if (IS_ERR(eb))
+ return PTR_ERR(eb);
+
+ path->nodes[*level - 1] = eb;
path->slots[*level - 1] = 0;
(*level)--;
+ return 0;
}
static int tree_move_next_or_upnext(struct btrfs_root *root,
@@ -5282,8 +5314,7 @@ static int tree_advance(struct btrfs_root *root,
if (*level == 0 || !allow_down) {
ret = tree_move_next_or_upnext(root, path, level, root_level);
} else {
- tree_move_down(root, path, level, root_level);
- ret = 0;
+ ret = tree_move_down(root, path, level, root_level);
}
if (ret >= 0) {
if (*level == 0)
@@ -5457,8 +5488,10 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
left_root_level,
advance_left != ADVANCE_ONLY_NEXT,
&left_key);
- if (ret < 0)
+ if (ret == -1)
left_end_reached = ADVANCE;
+ else if (ret < 0)
+ goto out;
advance_left = 0;
}
if (advance_right && !right_end_reached) {
@@ -5466,8 +5499,10 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
right_root_level,
advance_right != ADVANCE_ONLY_NEXT,
&right_key);
- if (ret < 0)
+ if (ret == -1)
right_end_reached = ADVANCE;
+ else if (ret < 0)
+ goto out;
advance_right = 0;
}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 443fcc402114..2fe8f89091a3 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -117,6 +117,7 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
#define BTRFS_FS_STATE_REMOUNTING 1
#define BTRFS_FS_STATE_TRANS_ABORTED 2
#define BTRFS_FS_STATE_DEV_REPLACING 3
+#define BTRFS_FS_STATE_DUMMY_FS_INFO 4
#define BTRFS_BACKREF_REV_MAX 256
#define BTRFS_BACKREF_REV_SHIFT 56
@@ -144,21 +145,6 @@ struct btrfs_header {
u8 level;
} __attribute__ ((__packed__));
-#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
- sizeof(struct btrfs_header)) / \
- sizeof(struct btrfs_key_ptr))
-#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
-#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->nodesize))
-#define BTRFS_FILE_EXTENT_INLINE_DATA_START \
- (offsetof(struct btrfs_file_extent_item, disk_bytenr))
-#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
- sizeof(struct btrfs_item) - \
- BTRFS_FILE_EXTENT_INLINE_DATA_START)
-#define BTRFS_MAX_XATTR_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
- sizeof(struct btrfs_item) -\
- sizeof(struct btrfs_dir_item))
-
-
/*
* this is a very generous portion of the super block, giving us
* room to translate 14 chunks with 3 stripes each.
@@ -1114,12 +1100,11 @@ struct btrfs_subvolume_writers {
#define BTRFS_ROOT_REF_COWS 1
#define BTRFS_ROOT_TRACK_DIRTY 2
#define BTRFS_ROOT_IN_RADIX 3
-#define BTRFS_ROOT_DUMMY_ROOT 4
-#define BTRFS_ROOT_ORPHAN_ITEM_INSERTED 5
-#define BTRFS_ROOT_DEFRAG_RUNNING 6
-#define BTRFS_ROOT_FORCE_COW 7
-#define BTRFS_ROOT_MULTI_LOG_TASKS 8
-#define BTRFS_ROOT_DIRTY 9
+#define BTRFS_ROOT_ORPHAN_ITEM_INSERTED 4
+#define BTRFS_ROOT_DEFRAG_RUNNING 5
+#define BTRFS_ROOT_FORCE_COW 6
+#define BTRFS_ROOT_MULTI_LOG_TASKS 7
+#define BTRFS_ROOT_DIRTY 8
/*
* in ram representation of the tree. extent_root is used for all allocations
@@ -1181,8 +1166,10 @@ struct btrfs_root {
u64 highest_objectid;
+#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
/* only used with CONFIG_BTRFS_FS_RUN_SANITY_TESTS is enabled */
u64 alloc_bytenr;
+#endif
u64 defrag_trans_start;
struct btrfs_key defrag_progress;
@@ -1259,6 +1246,39 @@ struct btrfs_root {
atomic_t qgroup_meta_rsv;
};
+static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 blocksize)
+{
+ return blocksize - sizeof(struct btrfs_header);
+}
+
+static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_root *root)
+{
+ return __BTRFS_LEAF_DATA_SIZE(root->nodesize);
+}
+
+static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_root *root)
+{
+ return BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
+}
+
+static inline u32 BTRFS_NODEPTRS_PER_BLOCK(const struct btrfs_root *root)
+{
+ return BTRFS_LEAF_DATA_SIZE(root) / sizeof(struct btrfs_key_ptr);
+}
+
+#define BTRFS_FILE_EXTENT_INLINE_DATA_START \
+ (offsetof(struct btrfs_file_extent_item, disk_bytenr))
+static inline u32 BTRFS_MAX_INLINE_DATA_SIZE(const struct btrfs_root *root)
+{
+ return BTRFS_MAX_ITEM_SIZE(root) -
+ BTRFS_FILE_EXTENT_INLINE_DATA_START;
+}
+
+static inline u32 BTRFS_MAX_XATTR_SIZE(const struct btrfs_root *root)
+{
+ return BTRFS_MAX_ITEM_SIZE(root) - sizeof(struct btrfs_dir_item);
+}
+
/*
* Flags for mount options.
*
@@ -1299,21 +1319,21 @@ struct btrfs_root {
#define btrfs_clear_opt(o, opt) ((o) &= ~BTRFS_MOUNT_##opt)
#define btrfs_set_opt(o, opt) ((o) |= BTRFS_MOUNT_##opt)
#define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
-#define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
+#define btrfs_test_opt(fs_info, opt) ((fs_info)->mount_opt & \
BTRFS_MOUNT_##opt)
-#define btrfs_set_and_info(root, opt, fmt, args...) \
+#define btrfs_set_and_info(fs_info, opt, fmt, args...) \
{ \
- if (!btrfs_test_opt(root, opt)) \
- btrfs_info(root->fs_info, fmt, ##args); \
- btrfs_set_opt(root->fs_info->mount_opt, opt); \
+ if (!btrfs_test_opt(fs_info, opt)) \
+ btrfs_info(fs_info, fmt, ##args); \
+ btrfs_set_opt(fs_info->mount_opt, opt); \
}
-#define btrfs_clear_and_info(root, opt, fmt, args...) \
+#define btrfs_clear_and_info(fs_info, opt, fmt, args...) \
{ \
- if (btrfs_test_opt(root, opt)) \
- btrfs_info(root->fs_info, fmt, ##args); \
- btrfs_clear_opt(root->fs_info->mount_opt, opt); \
+ if (btrfs_test_opt(fs_info, opt)) \
+ btrfs_info(fs_info, fmt, ##args); \
+ btrfs_clear_opt(fs_info->mount_opt, opt); \
}
#ifdef CONFIG_BTRFS_DEBUG
@@ -1321,9 +1341,9 @@ static inline int
btrfs_should_fragment_free_space(struct btrfs_root *root,
struct btrfs_block_group_cache *block_group)
{
- return (btrfs_test_opt(root, FRAGMENT_METADATA) &&
+ return (btrfs_test_opt(root->fs_info, FRAGMENT_METADATA) &&
block_group->flags & BTRFS_BLOCK_GROUP_METADATA) ||
- (btrfs_test_opt(root, FRAGMENT_DATA) &&
+ (btrfs_test_opt(root->fs_info, FRAGMENT_DATA) &&
block_group->flags & BTRFS_BLOCK_GROUP_DATA);
}
#endif
@@ -2886,9 +2906,6 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
/* root-item.c */
-int btrfs_find_root_ref(struct btrfs_root *tree_root,
- struct btrfs_path *path,
- u64 root_id, u64 ref_id);
int btrfs_add_root_ref(struct btrfs_trans_handle *trans,
struct btrfs_root *tree_root,
u64 root_id, u64 ref_id, u64 dirid, u64 sequence,
@@ -3362,23 +3379,23 @@ const char *btrfs_decode_error(int errno);
__cold
void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
- struct btrfs_root *root, const char *function,
+ const char *function,
unsigned int line, int errno);
/*
* Call btrfs_abort_transaction as early as possible when an error condition is
* detected, that way the exact line number is reported.
*/
-#define btrfs_abort_transaction(trans, root, errno) \
+#define btrfs_abort_transaction(trans, errno) \
do { \
/* Report first abort since mount */ \
if (!test_and_set_bit(BTRFS_FS_STATE_TRANS_ABORTED, \
- &((root)->fs_info->fs_state))) { \
+ &((trans)->fs_info->fs_state))) { \
WARN(1, KERN_DEBUG \
"BTRFS: Transaction aborted (error %d)\n", \
(errno)); \
} \
- __btrfs_abort_transaction((trans), (root), __func__, \
+ __btrfs_abort_transaction((trans), __func__, \
__LINE__, (errno)); \
} while (0)
@@ -3610,13 +3627,13 @@ static inline int btrfs_defrag_cancelled(struct btrfs_fs_info *fs_info)
void btrfs_test_destroy_inode(struct inode *inode);
#endif
-static inline int btrfs_test_is_dummy_root(struct btrfs_root *root)
+static inline int btrfs_is_testing(struct btrfs_fs_info *fs_info)
{
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
- if (unlikely(test_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state)))
+ if (unlikely(test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO,
+ &fs_info->fs_state)))
return 1;
#endif
return 0;
}
-
#endif
diff --git a/fs/btrfs/dedupe.h b/fs/btrfs/dedupe.h
new file mode 100644
index 000000000000..83ebfe28da9e
--- /dev/null
+++ b/fs/btrfs/dedupe.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 Fujitsu. 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 __BTRFS_DEDUPE__
+#define __BTRFS_DEDUPE__
+
+/* later in-band dedupe will expand this struct */
+struct btrfs_dedupe_hash;
+#endif
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index dd3c040139a2..3eeb9cd8cfa5 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -34,7 +34,7 @@ int __init btrfs_delayed_inode_init(void)
delayed_node_cache = kmem_cache_create("btrfs_delayed_node",
sizeof(struct btrfs_delayed_node),
0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ SLAB_MEM_SPREAD,
NULL);
if (!delayed_node_cache)
return -ENOMEM;
@@ -1170,7 +1170,7 @@ static int __btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
if (ret) {
btrfs_release_delayed_node(curr_node);
curr_node = NULL;
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
break;
}
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 430b3689b112..d9ddcfc18c91 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -606,7 +606,8 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
qrecord->num_bytes = num_bytes;
qrecord->old_roots = NULL;
- qexisting = btrfs_qgroup_insert_dirty_extent(delayed_refs,
+ qexisting = btrfs_qgroup_insert_dirty_extent(fs_info,
+ delayed_refs,
qrecord);
if (qexisting)
kfree(qrecord);
@@ -615,7 +616,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
spin_lock_init(&head_ref->lock);
mutex_init(&head_ref->mutex);
- trace_add_delayed_ref_head(ref, head_ref, action);
+ trace_add_delayed_ref_head(fs_info, ref, head_ref, action);
existing = htree_insert(&delayed_refs->href_root,
&head_ref->href_node);
@@ -682,7 +683,7 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
ref->type = BTRFS_TREE_BLOCK_REF_KEY;
full_ref->level = level;
- trace_add_delayed_tree_ref(ref, full_ref, action);
+ trace_add_delayed_tree_ref(fs_info, ref, full_ref, action);
ret = add_delayed_ref_tail_merge(trans, delayed_refs, head_ref, ref);
@@ -739,7 +740,7 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
full_ref->objectid = owner;
full_ref->offset = offset;
- trace_add_delayed_data_ref(ref, full_ref, action);
+ trace_add_delayed_data_ref(fs_info, ref, full_ref, action);
ret = add_delayed_ref_tail_merge(trans, delayed_refs, head_ref, ref);
@@ -861,33 +862,6 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
return 0;
}
-int btrfs_add_delayed_qgroup_reserve(struct btrfs_fs_info *fs_info,
- struct btrfs_trans_handle *trans,
- u64 ref_root, u64 bytenr, u64 num_bytes)
-{
- struct btrfs_delayed_ref_root *delayed_refs;
- struct btrfs_delayed_ref_head *ref_head;
- int ret = 0;
-
- if (!fs_info->quota_enabled || !is_fstree(ref_root))
- return 0;
-
- delayed_refs = &trans->transaction->delayed_refs;
-
- spin_lock(&delayed_refs->lock);
- ref_head = find_ref_head(&delayed_refs->href_root, bytenr, 0);
- if (!ref_head) {
- ret = -ENOENT;
- goto out;
- }
- WARN_ON(ref_head->qgroup_reserved || ref_head->qgroup_ref_root);
- ref_head->qgroup_ref_root = ref_root;
- ref_head->qgroup_reserved = num_bytes;
-out:
- spin_unlock(&delayed_refs->lock);
- return ret;
-}
-
int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
struct btrfs_trans_handle *trans,
u64 bytenr, u64 num_bytes,
@@ -940,28 +914,28 @@ int btrfs_delayed_ref_init(void)
btrfs_delayed_ref_head_cachep = kmem_cache_create(
"btrfs_delayed_ref_head",
sizeof(struct btrfs_delayed_ref_head), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_delayed_ref_head_cachep)
goto fail;
btrfs_delayed_tree_ref_cachep = kmem_cache_create(
"btrfs_delayed_tree_ref",
sizeof(struct btrfs_delayed_tree_ref), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_delayed_tree_ref_cachep)
goto fail;
btrfs_delayed_data_ref_cachep = kmem_cache_create(
"btrfs_delayed_data_ref",
sizeof(struct btrfs_delayed_data_ref), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_delayed_data_ref_cachep)
goto fail;
btrfs_delayed_extent_op_cachep = kmem_cache_create(
"btrfs_delayed_extent_op",
sizeof(struct btrfs_delayed_extent_op), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_delayed_extent_op_cachep)
goto fail;
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index 5fca9534a271..43f3629760e9 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -250,9 +250,6 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
u64 parent, u64 ref_root,
u64 owner, u64 offset, u64 reserved, int action,
struct btrfs_delayed_extent_op *extent_op);
-int btrfs_add_delayed_qgroup_reserve(struct btrfs_fs_info *fs_info,
- struct btrfs_trans_handle *trans,
- u64 ref_root, u64 bytenr, u64 num_bytes);
int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
struct btrfs_trans_handle *trans,
u64 bytenr, u64 num_bytes,
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 63ef9cdf0144..e9bbff3c0029 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -142,7 +142,7 @@ no_valid_dev_replace_entry_found:
* missing
*/
if (!dev_replace->srcdev &&
- !btrfs_test_opt(dev_root, DEGRADED)) {
+ !btrfs_test_opt(dev_root->fs_info, DEGRADED)) {
ret = -EIO;
btrfs_warn(fs_info,
"cannot mount because device replace operation is ongoing and");
@@ -151,7 +151,7 @@ no_valid_dev_replace_entry_found:
src_devid);
}
if (!dev_replace->tgtdev &&
- !btrfs_test_opt(dev_root, DEGRADED)) {
+ !btrfs_test_opt(dev_root->fs_info, DEGRADED)) {
ret = -EIO;
btrfs_warn(fs_info,
"cannot mount because device replace operation is ongoing and");
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 9a726ded2c6d..59febfb8d04a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -101,7 +101,7 @@ int __init btrfs_end_io_wq_init(void)
btrfs_end_io_wq_cache = kmem_cache_create("btrfs_end_io_wq",
sizeof(struct btrfs_end_io_wq),
0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ SLAB_MEM_SPREAD,
NULL);
if (!btrfs_end_io_wq_cache)
return -ENOMEM;
@@ -870,7 +870,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
atomic_inc(&fs_info->nr_async_submits);
- if (bio->bi_rw & REQ_SYNC)
+ if (bio->bi_opf & REQ_SYNC)
btrfs_set_work_high_priority(&async->work);
btrfs_queue_work(fs_info->workers, &async->work);
@@ -1140,7 +1140,7 @@ struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info,
struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
u64 bytenr)
{
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return alloc_test_extent_buffer(root->fs_info, bytenr,
root->nodesize);
return alloc_extent_buffer(root->fs_info, bytenr);
@@ -1227,6 +1227,7 @@ static void __setup_root(u32 nodesize, u32 sectorsize, u32 stripesize,
struct btrfs_root *root, struct btrfs_fs_info *fs_info,
u64 objectid)
{
+ bool dummy = test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
root->node = NULL;
root->commit_root = NULL;
root->sectorsize = sectorsize;
@@ -1281,14 +1282,14 @@ static void __setup_root(u32 nodesize, u32 sectorsize, u32 stripesize,
root->log_transid = 0;
root->log_transid_committed = -1;
root->last_log_commit = 0;
- if (fs_info)
+ if (!dummy)
extent_io_tree_init(&root->dirty_log_pages,
fs_info->btree_inode->i_mapping);
memset(&root->root_key, 0, sizeof(root->root_key));
memset(&root->root_item, 0, sizeof(root->root_item));
memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
- if (fs_info)
+ if (!dummy)
root->defrag_trans_start = fs_info->generation;
else
root->defrag_trans_start = 0;
@@ -1309,17 +1310,20 @@ static struct btrfs_root *btrfs_alloc_root(struct btrfs_fs_info *fs_info,
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
/* Should only be used by the testing infrastructure */
-struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize)
+struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info,
+ u32 sectorsize, u32 nodesize)
{
struct btrfs_root *root;
- root = btrfs_alloc_root(NULL, GFP_KERNEL);
+ if (!fs_info)
+ return ERR_PTR(-EINVAL);
+
+ root = btrfs_alloc_root(fs_info, GFP_KERNEL);
if (!root)
return ERR_PTR(-ENOMEM);
/* We don't use the stripesize in selftest, set it as sectorsize */
- __setup_root(nodesize, sectorsize, sectorsize, root, NULL,
+ __setup_root(nodesize, sectorsize, sectorsize, root, fs_info,
BTRFS_ROOT_TREE_OBJECTID);
- set_bit(BTRFS_ROOT_DUMMY_ROOT, &root->state);
root->alloc_bytenr = 0;
return root;
@@ -1594,14 +1598,14 @@ int btrfs_init_fs_root(struct btrfs_root *root)
ret = get_anon_bdev(&root->anon_dev);
if (ret)
- goto free_writers;
+ goto fail;
mutex_lock(&root->objectid_mutex);
ret = btrfs_find_highest_objectid(root,
&root->highest_objectid);
if (ret) {
mutex_unlock(&root->objectid_mutex);
- goto free_root_dev;
+ goto fail;
}
ASSERT(root->highest_objectid <= BTRFS_LAST_FREE_OBJECTID);
@@ -1609,14 +1613,8 @@ int btrfs_init_fs_root(struct btrfs_root *root)
mutex_unlock(&root->objectid_mutex);
return 0;
-
-free_root_dev:
- free_anon_bdev(root->anon_dev);
-free_writers:
- btrfs_free_subvolume_writers(root->subv_writers);
fail:
- kfree(root->free_ino_ctl);
- kfree(root->free_ino_pinned);
+ /* the caller is responsible to call free_fs_root */
return ret;
}
@@ -2310,17 +2308,19 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
unsigned int flags = WQ_MEM_RECLAIM | WQ_FREEZABLE | WQ_UNBOUND;
fs_info->workers =
- btrfs_alloc_workqueue("worker", flags | WQ_HIGHPRI,
- max_active, 16);
+ btrfs_alloc_workqueue(fs_info, "worker",
+ flags | WQ_HIGHPRI, max_active, 16);
fs_info->delalloc_workers =
- btrfs_alloc_workqueue("delalloc", flags, max_active, 2);
+ btrfs_alloc_workqueue(fs_info, "delalloc",
+ flags, max_active, 2);
fs_info->flush_workers =
- btrfs_alloc_workqueue("flush_delalloc", flags, max_active, 0);
+ btrfs_alloc_workqueue(fs_info, "flush_delalloc",
+ flags, max_active, 0);
fs_info->caching_workers =
- btrfs_alloc_workqueue("cache", flags, max_active, 0);
+ btrfs_alloc_workqueue(fs_info, "cache", flags, max_active, 0);
/*
* a higher idle thresh on the submit workers makes it much more
@@ -2328,41 +2328,48 @@ static int btrfs_init_workqueues(struct btrfs_fs_info *fs_info,
* devices
*/
fs_info->submit_workers =
- btrfs_alloc_workqueue("submit", flags,
+ btrfs_alloc_workqueue(fs_info, "submit", flags,
min_t(u64, fs_devices->num_devices,
max_active), 64);
fs_info->fixup_workers =
- btrfs_alloc_workqueue("fixup", flags, 1, 0);
+ btrfs_alloc_workqueue(fs_info, "fixup", flags, 1, 0);
/*
* endios are largely parallel and should have a very
* low idle thresh
*/
fs_info->endio_workers =
- btrfs_alloc_workqueue("endio", flags, max_active, 4);
+ btrfs_alloc_workqueue(fs_info, "endio", flags, max_active, 4);
fs_info->endio_meta_workers =
- btrfs_alloc_workqueue("endio-meta", flags, max_active, 4);
+ btrfs_alloc_workqueue(fs_info, "endio-meta", flags,
+ max_active, 4);
fs_info->endio_meta_write_workers =
- btrfs_alloc_workqueue("endio-meta-write", flags, max_active, 2);
+ btrfs_alloc_workqueue(fs_info, "endio-meta-write", flags,
+ max_active, 2);
fs_info->endio_raid56_workers =
- btrfs_alloc_workqueue("endio-raid56", flags, max_active, 4);
+ btrfs_alloc_workqueue(fs_info, "endio-raid56", flags,
+ max_active, 4);
fs_info->endio_repair_workers =
- btrfs_alloc_workqueue("endio-repair", flags, 1, 0);
+ btrfs_alloc_workqueue(fs_info, "endio-repair", flags, 1, 0);
fs_info->rmw_workers =
- btrfs_alloc_workqueue("rmw", flags, max_active, 2);
+ btrfs_alloc_workqueue(fs_info, "rmw", flags, max_active, 2);
fs_info->endio_write_workers =
- btrfs_alloc_workqueue("endio-write", flags, max_active, 2);
+ btrfs_alloc_workqueue(fs_info, "endio-write", flags,
+ max_active, 2);
fs_info->endio_freespace_worker =
- btrfs_alloc_workqueue("freespace-write", flags, max_active, 0);
+ btrfs_alloc_workqueue(fs_info, "freespace-write", flags,
+ max_active, 0);
fs_info->delayed_workers =
- btrfs_alloc_workqueue("delayed-meta", flags, max_active, 0);
+ btrfs_alloc_workqueue(fs_info, "delayed-meta", flags,
+ max_active, 0);
fs_info->readahead_workers =
- btrfs_alloc_workqueue("readahead", flags, max_active, 2);
+ btrfs_alloc_workqueue(fs_info, "readahead", flags,
+ max_active, 2);
fs_info->qgroup_rescan_workers =
- btrfs_alloc_workqueue("qgroup-rescan", flags, 1, 0);
+ btrfs_alloc_workqueue(fs_info, "qgroup-rescan", flags, 1, 0);
fs_info->extent_workers =
- btrfs_alloc_workqueue("extent-refs", flags,
+ btrfs_alloc_workqueue(fs_info, "extent-refs", flags,
min_t(u64, fs_devices->num_devices,
max_active), 8);
@@ -3010,8 +3017,8 @@ retry_root_backup:
if (IS_ERR(fs_info->transaction_kthread))
goto fail_cleaner;
- if (!btrfs_test_opt(tree_root, SSD) &&
- !btrfs_test_opt(tree_root, NOSSD) &&
+ if (!btrfs_test_opt(tree_root->fs_info, SSD) &&
+ !btrfs_test_opt(tree_root->fs_info, NOSSD) &&
!fs_info->fs_devices->rotating) {
btrfs_info(fs_info, "detected SSD devices, enabling SSD mode");
btrfs_set_opt(fs_info->mount_opt, SSD);
@@ -3024,9 +3031,9 @@ retry_root_backup:
btrfs_apply_pending_changes(fs_info);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
+ if (btrfs_test_opt(tree_root->fs_info, CHECK_INTEGRITY)) {
ret = btrfsic_mount(tree_root, fs_devices,
- btrfs_test_opt(tree_root,
+ btrfs_test_opt(tree_root->fs_info,
CHECK_INTEGRITY_INCLUDING_EXTENT_DATA) ?
1 : 0,
fs_info->check_integrity_print_mask);
@@ -3042,7 +3049,7 @@ retry_root_backup:
/* do not make disk changes in broken FS or nologreplay is given */
if (btrfs_super_log_root(disk_super) != 0 &&
- !btrfs_test_opt(tree_root, NOLOGREPLAY)) {
+ !btrfs_test_opt(tree_root->fs_info, NOLOGREPLAY)) {
ret = btrfs_replay_log(fs_info, fs_devices);
if (ret) {
err = ret;
@@ -3083,7 +3090,7 @@ retry_root_backup:
if (sb->s_flags & MS_RDONLY)
return 0;
- if (btrfs_test_opt(tree_root, FREE_SPACE_TREE) &&
+ if (btrfs_test_opt(tree_root->fs_info, FREE_SPACE_TREE) &&
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
btrfs_info(fs_info, "creating free space tree");
ret = btrfs_create_free_space_tree(fs_info);
@@ -3120,7 +3127,7 @@ retry_root_backup:
btrfs_qgroup_rescan_resume(fs_info);
- if (btrfs_test_opt(tree_root, CLEAR_CACHE) &&
+ if (btrfs_test_opt(tree_root->fs_info, CLEAR_CACHE) &&
btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
btrfs_info(fs_info, "clearing free space tree");
ret = btrfs_clear_free_space_tree(fs_info);
@@ -3141,7 +3148,7 @@ retry_root_backup:
close_ctree(tree_root);
return ret;
}
- } else if (btrfs_test_opt(tree_root, RESCAN_UUID_TREE) ||
+ } else if (btrfs_test_opt(tree_root->fs_info, RESCAN_UUID_TREE) ||
fs_info->generation !=
btrfs_super_uuid_tree_generation(disk_super)) {
btrfs_info(fs_info, "checking UUID tree");
@@ -3218,7 +3225,7 @@ fail:
return err;
recovery_tree_root:
- if (!btrfs_test_opt(tree_root, USEBACKUPROOT))
+ if (!btrfs_test_opt(tree_root->fs_info, USEBACKUPROOT))
goto fail_tree_roots;
free_root_pointers(fs_info, 0);
@@ -3634,7 +3641,7 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
int total_errors = 0;
u64 flags;
- do_barriers = !btrfs_test_opt(root, NOBARRIER);
+ do_barriers = !btrfs_test_opt(root->fs_info, NOBARRIER);
backup_super_roots(root->fs_info);
sb = root->fs_info->super_for_commit;
@@ -3918,7 +3925,7 @@ void close_ctree(struct btrfs_root *root)
iput(fs_info->btree_inode);
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- if (btrfs_test_opt(root, CHECK_INTEGRITY))
+ if (btrfs_test_opt(root->fs_info, CHECK_INTEGRITY))
btrfsic_unmount(root, fs_info->fs_devices);
#endif
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index dbf3e1aab69e..b3207a0e09f7 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -90,7 +90,8 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
void btrfs_free_fs_root(struct btrfs_root *root);
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
-struct btrfs_root *btrfs_alloc_dummy_root(u32 sectorsize, u32 nodesize);
+struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info,
+ u32 sectorsize, u32 nodesize);
#endif
/*
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e9376b1657e2..61b494e8e604 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2180,7 +2180,7 @@ static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
path, bytenr, parent, root_objectid,
owner, offset, refs_to_add);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
out:
btrfs_free_path(path);
return ret;
@@ -2204,7 +2204,7 @@ static int run_delayed_data_ref(struct btrfs_trans_handle *trans,
ins.type = BTRFS_EXTENT_ITEM_KEY;
ref = btrfs_delayed_node_to_data_ref(node);
- trace_run_delayed_data_ref(node, ref, node->action);
+ trace_run_delayed_data_ref(root->fs_info, node, ref, node->action);
if (node->type == BTRFS_SHARED_DATA_REF_KEY)
parent = ref->parent;
@@ -2359,7 +2359,7 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans,
SKINNY_METADATA);
ref = btrfs_delayed_node_to_tree_ref(node);
- trace_run_delayed_tree_ref(node, ref, node->action);
+ trace_run_delayed_tree_ref(root->fs_info, node, ref, node->action);
if (node->type == BTRFS_SHARED_BLOCK_REF_KEY)
parent = ref->parent;
@@ -2423,7 +2423,8 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
*/
BUG_ON(extent_op);
head = btrfs_delayed_node_to_head(node);
- trace_run_delayed_ref_head(node, head, node->action);
+ trace_run_delayed_ref_head(root->fs_info, node, head,
+ node->action);
if (insert_reserved) {
btrfs_pin_extent(root, node->bytenr,
@@ -2778,7 +2779,7 @@ u64 btrfs_csum_bytes_to_leaves(struct btrfs_root *root, u64 csum_bytes)
u64 num_csums_per_leaf;
u64 num_csums;
- csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
+ csum_size = BTRFS_MAX_ITEM_SIZE(root);
num_csums_per_leaf = div64_u64(csum_size,
(u64)btrfs_super_csum_size(root->fs_info->super_copy));
num_csums = div64_u64(csum_bytes, root->sectorsize);
@@ -2970,7 +2971,7 @@ again:
trans->can_flush_pending_bgs = false;
ret = __btrfs_run_delayed_refs(trans, root, count);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -3234,7 +3235,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
u64, u64, u64, u64, u64, u64);
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return 0;
ref_root = btrfs_header_owner(buf);
@@ -3429,7 +3430,7 @@ again:
* transaction, this only happens in really bad situations
* anyway.
*/
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_put;
}
WARN_ON(ret);
@@ -3447,7 +3448,7 @@ again:
spin_lock(&block_group->lock);
if (block_group->cached != BTRFS_CACHE_FINISHED ||
- !btrfs_test_opt(root, SPACE_CACHE)) {
+ !btrfs_test_opt(root->fs_info, SPACE_CACHE)) {
/*
* don't bother trying to write stuff out _if_
* a) we're not cached,
@@ -3524,7 +3525,7 @@ int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
struct btrfs_path *path;
if (list_empty(&cur_trans->dirty_bgs) ||
- !btrfs_test_opt(root, SPACE_CACHE))
+ !btrfs_test_opt(root->fs_info, SPACE_CACHE))
return 0;
path = btrfs_alloc_path();
@@ -3669,7 +3670,7 @@ again:
}
spin_unlock(&cur_trans->dirty_bgs_lock);
} else if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
}
}
@@ -3815,7 +3816,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
cache);
}
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
}
/* if its not on the io list, we need to put the block group */
@@ -4443,7 +4444,7 @@ void check_system_chunk(struct btrfs_trans_handle *trans,
thresh = btrfs_calc_trunc_metadata_size(root, num_devs) +
btrfs_calc_trans_metadata_size(root, 1);
- if (left < thresh && btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ if (left < thresh && btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
btrfs_info(root->fs_info, "left=%llu, need=%llu, flags=%llu",
left, thresh, type);
dump_space_info(info, 0, 0);
@@ -4588,7 +4589,7 @@ out:
*/
if (trans->can_flush_pending_bgs &&
trans->chunk_bytes_reserved >= (u64)SZ_2M) {
- btrfs_create_pending_block_groups(trans, trans->root);
+ btrfs_create_pending_block_groups(trans, extent_root);
btrfs_trans_release_chunk_metadata(trans);
}
return ret;
@@ -5729,7 +5730,7 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
*/
void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
{
- struct btrfs_fs_info *fs_info = trans->root->fs_info;
+ struct btrfs_fs_info *fs_info = trans->fs_info;
if (!trans->chunk_bytes_reserved)
return;
@@ -6100,7 +6101,7 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
if (dropped > 0)
to_free += btrfs_calc_trans_metadata_size(root, dropped);
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return;
trace_btrfs_space_reservation(root->fs_info, "delalloc",
@@ -6215,7 +6216,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
spin_lock(&cache->space_info->lock);
spin_lock(&cache->lock);
- if (btrfs_test_opt(root, SPACE_CACHE) &&
+ if (btrfs_test_opt(root->fs_info, SPACE_CACHE) &&
cache->disk_cache_state < BTRFS_DC_CLEAR)
cache->disk_cache_state = BTRFS_DC_CLEAR;
@@ -6597,7 +6598,7 @@ fetch_cluster_info(struct btrfs_root *root, struct btrfs_space_info *space_info,
u64 *empty_cluster)
{
struct btrfs_free_cluster *ret = NULL;
- bool ssd = btrfs_test_opt(root, SSD);
+ bool ssd = btrfs_test_opt(root->fs_info, SSD);
*empty_cluster = 0;
if (btrfs_mixed_space_info(space_info))
@@ -6742,7 +6743,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
break;
}
- if (btrfs_test_opt(root, DISCARD))
+ if (btrfs_test_opt(root->fs_info, DISCARD))
ret = btrfs_discard_extent(root, start,
end + 1 - start, NULL);
@@ -6880,7 +6881,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
NULL, refs_to_drop,
is_data, &last_ref);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
btrfs_release_path(path);
@@ -6929,7 +6930,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
path->nodes[0]);
}
if (ret < 0) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
extent_slot = path->slots[0];
@@ -6940,10 +6941,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
"unable to find ref byte nr %llu parent %llu root %llu owner %llu offset %llu",
bytenr, parent, root_objectid, owner_objectid,
owner_offset);
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
} else {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -6955,7 +6956,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
ret = convert_extent_item_v0(trans, extent_root, path,
owner_objectid, 0);
if (ret < 0) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -6974,7 +6975,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
btrfs_print_leaf(extent_root, path->nodes[0]);
}
if (ret < 0) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -6999,7 +7000,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
btrfs_err(info, "trying to drop %d refs but we only have %Lu "
"for bytenr %Lu", refs_to_drop, refs, bytenr);
ret = -EINVAL;
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
refs -= refs_to_drop;
@@ -7022,7 +7023,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
iref, refs_to_drop,
is_data, &last_ref);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
@@ -7045,7 +7046,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
num_to_del);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
btrfs_release_path(path);
@@ -7053,7 +7054,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
if (is_data) {
ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
@@ -7061,13 +7062,13 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
ret = add_to_free_space_tree(trans, root->fs_info, bytenr,
num_bytes);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
ret = update_block_group(trans, root, bytenr, num_bytes, 0);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
@@ -7216,7 +7217,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int ret;
struct btrfs_fs_info *fs_info = root->fs_info;
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(fs_info))
return 0;
add_pinned_bytes(root->fs_info, num_bytes, owner, root_objectid);
@@ -7851,8 +7852,7 @@ loop:
* can do more things.
*/
if (ret < 0 && ret != -ENOSPC)
- btrfs_abort_transaction(trans,
- root, ret);
+ btrfs_abort_transaction(trans, ret);
else
ret = 0;
if (!exist)
@@ -7906,8 +7906,8 @@ static void dump_space_info(struct btrfs_space_info *info, u64 bytes,
printk(KERN_INFO "BTRFS: space_info %llu has %llu free, is %sfull\n",
info->flags,
info->total_bytes - info->bytes_used - info->bytes_pinned -
- info->bytes_reserved - info->bytes_readonly,
- (info->full) ? "" : "not ");
+ info->bytes_reserved - info->bytes_readonly -
+ info->bytes_may_use, (info->full) ? "" : "not ");
printk(KERN_INFO "BTRFS: space_info total=%llu, used=%llu, pinned=%llu, "
"reserved=%llu, may_use=%llu, readonly=%llu\n",
info->total_bytes, info->bytes_used, info->bytes_pinned,
@@ -7961,7 +7961,7 @@ again:
if (num_bytes == min_alloc_size)
final_tried = true;
goto again;
- } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ } else if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
struct btrfs_space_info *sinfo;
sinfo = __find_space_info(root->fs_info, flags);
@@ -7992,7 +7992,7 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
if (pin)
pin_down_extent(root, cache, start, len, 1);
else {
- if (btrfs_test_opt(root, DISCARD))
+ if (btrfs_test_opt(root->fs_info, DISCARD))
ret = btrfs_discard_extent(root, start, len, NULL);
btrfs_add_free_space(cache, start, len);
btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc);
@@ -8300,7 +8300,7 @@ again:
goto again;
}
- if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
static DEFINE_RATELIMIT_STATE(_rs,
DEFAULT_RATELIMIT_INTERVAL * 10,
/*DEFAULT_RATELIMIT_BURST*/ 1);
@@ -8354,13 +8354,15 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
bool skinny_metadata = btrfs_fs_incompat(root->fs_info,
SKINNY_METADATA);
- if (btrfs_test_is_dummy_root(root)) {
+#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+ if (btrfs_is_testing(root->fs_info)) {
buf = btrfs_init_new_buffer(trans, root, root->alloc_bytenr,
level);
if (!IS_ERR(buf))
root->alloc_bytenr += blocksize;
return buf;
}
+#endif
block_rsv = use_block_rsv(trans, root, blocksize);
if (IS_ERR(block_rsv))
@@ -8540,7 +8542,8 @@ static int record_one_subtree_extent(struct btrfs_trans_handle *trans,
delayed_refs = &trans->transaction->delayed_refs;
spin_lock(&delayed_refs->lock);
- if (btrfs_qgroup_insert_dirty_extent(delayed_refs, qrecord))
+ if (btrfs_qgroup_insert_dirty_extent(trans->fs_info,
+ delayed_refs, qrecord))
kfree(qrecord);
spin_unlock(&delayed_refs->lock);
@@ -9325,7 +9328,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
&root->root_key,
root_item);
if (ret) {
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
err = ret;
goto out_end_trans;
}
@@ -9352,7 +9355,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
ret = btrfs_del_root(trans, tree_root, &root->root_key);
if (ret) {
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_end_trans;
}
@@ -9360,7 +9363,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
ret = btrfs_find_root(tree_root, &root->root_key, path,
NULL, NULL);
if (ret < 0) {
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
err = ret;
goto out_end_trans;
} else if (ret > 0) {
@@ -9731,7 +9734,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
int full = 0;
int ret = 0;
- debug = btrfs_test_opt(root, ENOSPC_DEBUG);
+ debug = btrfs_test_opt(root->fs_info, ENOSPC_DEBUG);
block_group = btrfs_lookup_block_group(root->fs_info, bytenr);
@@ -9887,7 +9890,22 @@ static int find_first_block_group(struct btrfs_root *root,
if (found_key.objectid >= key->objectid &&
found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
- ret = 0;
+ struct extent_map_tree *em_tree;
+ struct extent_map *em;
+
+ em_tree = &root->fs_info->mapping_tree.map_tree;
+ read_lock(&em_tree->lock);
+ em = lookup_extent_mapping(em_tree, found_key.objectid,
+ found_key.offset);
+ read_unlock(&em_tree->lock);
+ if (!em) {
+ btrfs_err(root->fs_info,
+ "logical %llu len %llu found bg but no related chunk",
+ found_key.objectid, found_key.offset);
+ ret = -ENOENT;
+ } else {
+ ret = 0;
+ }
goto out;
}
path->slots[0]++;
@@ -10129,10 +10147,10 @@ int btrfs_read_block_groups(struct btrfs_root *root)
path->reada = READA_FORWARD;
cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
- if (btrfs_test_opt(root, SPACE_CACHE) &&
+ if (btrfs_test_opt(root->fs_info, SPACE_CACHE) &&
btrfs_super_generation(root->fs_info->super_copy) != cache_gen)
need_clear = 1;
- if (btrfs_test_opt(root, CLEAR_CACHE))
+ if (btrfs_test_opt(root->fs_info, CLEAR_CACHE))
need_clear = 1;
while (1) {
@@ -10163,7 +10181,7 @@ int btrfs_read_block_groups(struct btrfs_root *root)
* b) Setting 'dirty flag' makes sure that we flush
* the new space cache info onto disk.
*/
- if (btrfs_test_opt(root, SPACE_CACHE))
+ if (btrfs_test_opt(root->fs_info, SPACE_CACHE))
cache->disk_cache_state = BTRFS_DC_CLEAR;
}
@@ -10305,11 +10323,11 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans,
ret = btrfs_insert_item(trans, extent_root, &key, &item,
sizeof(item));
if (ret)
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
ret = btrfs_finish_chunk_alloc(trans, extent_root,
key.objectid, key.offset);
if (ret)
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
add_block_group_free_space(trans, root->fs_info, block_group);
/* already aborted the transaction if it failed. */
next:
@@ -10622,7 +10640,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
spin_lock(&block_group->space_info->lock);
list_del_init(&block_group->ro_list);
- if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ if (btrfs_test_opt(root->fs_info, ENOSPC_DEBUG)) {
WARN_ON(block_group->space_info->total_bytes
< block_group->key.offset);
WARN_ON(block_group->space_info->bytes_readonly
@@ -10890,7 +10908,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
spin_unlock(&space_info->lock);
/* DISCARD can flip during remount */
- trimming = btrfs_test_opt(root, DISCARD);
+ trimming = btrfs_test_opt(root->fs_info, DISCARD);
/* Implicit trim during transaction commit. */
if (trimming)
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index cee4cb99b8ce..44fe66b53c8b 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -163,13 +163,13 @@ int __init extent_io_init(void)
{
extent_state_cache = kmem_cache_create("btrfs_extent_state",
sizeof(struct extent_state), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!extent_state_cache)
return -ENOMEM;
extent_buffer_cache = kmem_cache_create("btrfs_extent_buffer",
sizeof(struct extent_buffer), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!extent_buffer_cache)
goto free_state_cache;
@@ -2049,7 +2049,7 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical,
return -EIO;
}
bio->bi_bdev = dev->bdev;
- bio->bi_rw = WRITE_SYNC;
+ bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC);
bio_add_page(bio, page, length, pg_offset);
if (btrfsic_submit_bio_wait(bio)) {
@@ -2697,12 +2697,6 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
btrfs_bio->csum = NULL;
btrfs_bio->csum_allocated = NULL;
btrfs_bio->end_io = NULL;
-
-#ifdef CONFIG_BLK_CGROUP
- /* FIXME, put this into bio_clone_bioset */
- if (bio->bi_css)
- bio_associate_blkcg(new, bio->bi_css);
-#endif
}
return new;
}
@@ -2756,7 +2750,6 @@ static int merge_bio(struct extent_io_tree *tree, struct page *page,
if (tree->ops && tree->ops->merge_bio_hook)
ret = tree->ops->merge_bio_hook(page, offset, size, bio,
bio_flags);
- BUG_ON(ret < 0);
return ret;
}
@@ -2879,6 +2872,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
* into the tree that are removed when the IO is done (by the end_io
* handlers)
* XXX JDM: This needs looking at to ensure proper page locking
+ * return 0 on success, otherwise return error
*/
static int __do_readpage(struct extent_io_tree *tree,
struct page *page,
@@ -2900,7 +2894,7 @@ static int __do_readpage(struct extent_io_tree *tree,
sector_t sector;
struct extent_map *em;
struct block_device *bdev;
- int ret;
+ int ret = 0;
int nr = 0;
size_t pg_offset = 0;
size_t iosize;
@@ -3081,6 +3075,7 @@ static int __do_readpage(struct extent_io_tree *tree,
} else {
SetPageError(page);
unlock_extent(tree, cur, cur + iosize - 1);
+ goto out;
}
cur = cur + iosize;
pg_offset += iosize;
@@ -3091,7 +3086,7 @@ out:
SetPageUptodate(page);
unlock_page(page);
}
- return 0;
+ return ret;
}
static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
@@ -5230,14 +5225,31 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
atomic_set(&eb->io_pages, num_reads);
for (i = start_i; i < num_pages; i++) {
page = eb->pages[i];
+
if (!PageUptodate(page)) {
+ if (ret) {
+ atomic_dec(&eb->io_pages);
+ unlock_page(page);
+ continue;
+ }
+
ClearPageError(page);
err = __extent_read_full_page(tree, page,
get_extent, &bio,
mirror_num, &bio_flags,
REQ_META);
- if (err)
+ if (err) {
ret = err;
+ /*
+ * We use &bio in above __extent_read_full_page,
+ * so we ensure that if it returns error, the
+ * current page fails to add itself to bio and
+ * it's been unlocked.
+ *
+ * We must dec io_pages by ourselves.
+ */
+ atomic_dec(&eb->io_pages);
+ }
} else {
unlock_page(page);
}
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index e0715fcfb11e..26f9ac719d20 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -13,7 +13,7 @@ int __init extent_map_init(void)
{
extent_map_cache = kmem_cache_create("btrfs_extent_map",
sizeof(struct extent_map), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!extent_map_cache)
return -ENOMEM;
return 0;
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 62a81ee13a5f..d0d571c47d33 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -250,7 +250,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
offset + root->sectorsize - 1,
EXTENT_NODATASUM);
} else {
- btrfs_info(BTRFS_I(inode)->root->fs_info,
+ btrfs_info_rl(BTRFS_I(inode)->root->fs_info,
"no csum found for inode %llu start %llu",
btrfs_ino(inode), offset);
}
@@ -699,7 +699,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
*/
ret = btrfs_split_item(trans, root, path, &key, offset);
if (ret && ret != -EAGAIN) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index bcfb4a27ddd4..5842423f8f47 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -132,7 +132,7 @@ static int __btrfs_add_inode_defrag(struct inode *inode,
static inline int __need_auto_defrag(struct btrfs_root *root)
{
- if (!btrfs_test_opt(root, AUTO_DEFRAG))
+ if (!btrfs_test_opt(root->fs_info, AUTO_DEFRAG))
return 0;
if (btrfs_fs_closing(root->fs_info))
@@ -950,7 +950,7 @@ delete_extent_item:
ret = btrfs_del_items(trans, root, path, del_slot,
del_nr);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
break;
}
@@ -974,7 +974,7 @@ delete_extent_item:
path->slots[0] = del_slot;
ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
}
leaf = path->nodes[0];
@@ -1190,7 +1190,7 @@ again:
goto again;
}
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -1278,7 +1278,7 @@ again:
ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
@@ -2033,6 +2033,14 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
*/
clear_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
&BTRFS_I(inode)->runtime_flags);
+ /*
+ * An ordered extent might have started before and completed
+ * already with io errors, in which case the inode was not
+ * updated and we end up here. So check the inode's mapping
+ * flags for any errors that might have happened while doing
+ * writeback of file data.
+ */
+ ret = btrfs_inode_check_errors(inode);
inode_unlock(inode);
goto out;
}
@@ -2975,7 +2983,7 @@ int btrfs_auto_defrag_init(void)
{
btrfs_inode_defrag_cachep = kmem_cache_create("btrfs_inode_defrag",
sizeof(struct inode_defrag), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ SLAB_MEM_SPREAD,
NULL);
if (!btrfs_inode_defrag_cachep)
return -ENOMEM;
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 69d270f6602c..d571bd2b697b 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -280,7 +280,7 @@ fail:
if (locked)
mutex_unlock(&trans->transaction->cache_write_mutex);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -3026,7 +3026,7 @@ int btrfs_find_space_cluster(struct btrfs_root *root,
* For metadata, allow allocates with smaller extents. For
* data, keep it dense.
*/
- if (btrfs_test_opt(root, SSD_SPREAD)) {
+ if (btrfs_test_opt(root->fs_info, SSD_SPREAD)) {
cont1_bytes = min_bytes = bytes + empty_size;
} else if (block_group->flags & BTRFS_BLOCK_GROUP_METADATA) {
cont1_bytes = bytes;
@@ -3470,7 +3470,7 @@ int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
int ret = 0;
u64 root_gen = btrfs_root_generation(&root->root_item);
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return 0;
/*
@@ -3514,7 +3514,7 @@ int btrfs_write_out_ino_cache(struct btrfs_root *root,
struct btrfs_io_ctl io_ctl;
bool release_metadata = true;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return 0;
memset(&io_ctl, 0, sizeof(io_ctl));
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index 53dbeaf6ce94..87e7e3d3e676 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -305,7 +305,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
out:
kvfree(bitmap);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -454,7 +454,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
out:
kvfree(bitmap);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -851,7 +851,7 @@ int remove_from_free_space_tree(struct btrfs_trans_handle *trans,
out:
btrfs_free_path(path);
if (ret)
- btrfs_abort_transaction(trans, fs_info->free_space_root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -1047,7 +1047,7 @@ int add_to_free_space_tree(struct btrfs_trans_handle *trans,
out:
btrfs_free_path(path);
if (ret)
- btrfs_abort_transaction(trans, fs_info->free_space_root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -1193,7 +1193,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
abort:
fs_info->creating_free_space_tree = 0;
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, tree_root);
return ret;
}
@@ -1280,7 +1280,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
return 0;
abort:
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, tree_root);
return ret;
}
@@ -1333,7 +1333,7 @@ out:
btrfs_free_path(path);
mutex_unlock(&block_group->free_space_lock);
if (ret)
- btrfs_abort_transaction(trans, fs_info->free_space_root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -1410,7 +1410,7 @@ int remove_block_group_free_space(struct btrfs_trans_handle *trans,
out:
btrfs_free_path(path);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index 70107f7c9307..aa6fabaee72e 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -38,7 +38,7 @@ static int caching_kthread(void *data)
int slot;
int ret;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return 0;
path = btrfs_alloc_path();
@@ -141,7 +141,7 @@ static void start_caching(struct btrfs_root *root)
int ret;
u64 objectid;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return;
spin_lock(&root->ino_cache_lock);
@@ -185,7 +185,7 @@ static void start_caching(struct btrfs_root *root)
int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid)
{
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return btrfs_find_free_objectid(root, objectid);
again:
@@ -211,7 +211,7 @@ void btrfs_return_ino(struct btrfs_root *root, u64 objectid)
{
struct btrfs_free_space_ctl *pinned = root->free_ino_pinned;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return;
again:
if (root->ino_cache_state == BTRFS_CACHE_FINISHED) {
@@ -251,7 +251,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root)
struct rb_node *n;
u64 count;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return;
while (1) {
@@ -412,7 +412,7 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
if (btrfs_root_refs(&root->root_item) == 0)
return 0;
- if (!btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (!btrfs_test_opt(root->fs_info, INODE_MAP_CACHE))
return 0;
path = btrfs_alloc_path();
@@ -458,7 +458,7 @@ again:
BTRFS_I(inode)->generation = 0;
ret = btrfs_update_inode(trans, root, inode);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_put;
}
@@ -466,7 +466,7 @@ again:
ret = btrfs_truncate_free_space_cache(root, trans, NULL, inode);
if (ret) {
if (ret != -ENOSPC)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_put;
}
}
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8078077d1090..08dfc57e2270 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -60,6 +60,7 @@
#include "hash.h"
#include "props.h"
#include "qgroup.h"
+#include "dedupe.h"
struct btrfs_iget_args {
struct btrfs_key *location;
@@ -105,8 +106,9 @@ static int btrfs_truncate(struct inode *inode);
static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
static noinline int cow_file_range(struct inode *inode,
struct page *locked_page,
- u64 start, u64 end, int *page_started,
- unsigned long *nr_written, int unlock);
+ u64 start, u64 end, u64 delalloc_end,
+ int *page_started, unsigned long *nr_written,
+ int unlock, struct btrfs_dedupe_hash *hash);
static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
u64 len, u64 orig_start,
u64 block_start, u64 block_len,
@@ -294,7 +296,7 @@ static noinline int cow_file_range_inline(struct btrfs_root *root,
start, aligned_end, NULL,
1, 1, extent_item_size, &extent_inserted);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -305,7 +307,7 @@ static noinline int cow_file_range_inline(struct btrfs_root *root,
inline_len, compressed_size,
compress_type, compressed_pages);
if (ret && ret != -ENOSPC) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
} else if (ret == -ENOSPC) {
ret = 1;
@@ -374,12 +376,12 @@ static inline int inode_need_compress(struct inode *inode)
struct btrfs_root *root = BTRFS_I(inode)->root;
/* force compress */
- if (btrfs_test_opt(root, FORCE_COMPRESS))
+ if (btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
return 1;
/* bad compression ratios */
if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS)
return 0;
- if (btrfs_test_opt(root, COMPRESS) ||
+ if (btrfs_test_opt(root->fs_info, COMPRESS) ||
BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS ||
BTRFS_I(inode)->force_compress)
return 1;
@@ -585,9 +587,27 @@ cont:
will_compress = 0;
} else {
num_bytes = total_in;
+ *num_added += 1;
+
+ /*
+ * The async work queues will take care of doing actual
+ * allocation on disk for these compressed pages, and
+ * will submit them to the elevator.
+ */
+ add_async_extent(async_cow, start, num_bytes,
+ total_compressed, pages, nr_pages_ret,
+ compress_type);
+
+ if (start + num_bytes < end) {
+ start += num_bytes;
+ pages = NULL;
+ cond_resched();
+ goto again;
+ }
+ return;
}
}
- if (!will_compress && pages) {
+ if (pages) {
/*
* the compression code ran but failed to make things smaller,
* free any pages it allocated and our page pointer array
@@ -602,48 +622,28 @@ cont:
nr_pages_ret = 0;
/* flag the file so we don't compress in the future */
- if (!btrfs_test_opt(root, FORCE_COMPRESS) &&
+ if (!btrfs_test_opt(root->fs_info, FORCE_COMPRESS) &&
!(BTRFS_I(inode)->force_compress)) {
BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
}
}
- if (will_compress) {
- *num_added += 1;
-
- /* the async work queues will take care of doing actual
- * allocation on disk for these compressed pages,
- * and will submit them to the elevator.
- */
- add_async_extent(async_cow, start, num_bytes,
- total_compressed, pages, nr_pages_ret,
- compress_type);
-
- if (start + num_bytes < end) {
- start += num_bytes;
- pages = NULL;
- cond_resched();
- goto again;
- }
- } else {
cleanup_and_bail_uncompressed:
- /*
- * No compression, but we still need to write the pages in
- * the file we've been given so far. redirty the locked
- * page if it corresponds to our extent and set things up
- * for the async work queue to run cow_file_range to do
- * the normal delalloc dance
- */
- if (page_offset(locked_page) >= start &&
- page_offset(locked_page) <= end) {
- __set_page_dirty_nobuffers(locked_page);
- /* unlocked later on in the async handlers */
- }
- if (redirty)
- extent_range_redirty_for_io(inode, start, end);
- add_async_extent(async_cow, start, end - start + 1,
- 0, NULL, 0, BTRFS_COMPRESS_NONE);
- *num_added += 1;
- }
+ /*
+ * No compression, but we still need to write the pages in the file
+ * we've been given so far. redirty the locked page if it corresponds
+ * to our extent and set things up for the async work queue to run
+ * cow_file_range to do the normal delalloc dance.
+ */
+ if (page_offset(locked_page) >= start &&
+ page_offset(locked_page) <= end)
+ __set_page_dirty_nobuffers(locked_page);
+ /* unlocked later on in the async handlers */
+
+ if (redirty)
+ extent_range_redirty_for_io(inode, start, end);
+ add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0,
+ BTRFS_COMPRESS_NONE);
+ *num_added += 1;
return;
@@ -712,7 +712,10 @@ retry:
async_extent->start,
async_extent->start +
async_extent->ram_size - 1,
- &page_started, &nr_written, 0);
+ async_extent->start +
+ async_extent->ram_size - 1,
+ &page_started, &nr_written, 0,
+ NULL);
/* JDM XXX */
@@ -925,9 +928,9 @@ static u64 get_extent_allocation_hint(struct inode *inode, u64 start,
*/
static noinline int cow_file_range(struct inode *inode,
struct page *locked_page,
- u64 start, u64 end, int *page_started,
- unsigned long *nr_written,
- int unlock)
+ u64 start, u64 end, u64 delalloc_end,
+ int *page_started, unsigned long *nr_written,
+ int unlock, struct btrfs_dedupe_hash *hash)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 alloc_hint = 0;
@@ -1156,7 +1159,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
async_cow->start = start;
if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS &&
- !btrfs_test_opt(root, FORCE_COMPRESS))
+ !btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
cur_end = end;
else
cur_end = min(end, start + SZ_512K - 1);
@@ -1418,7 +1421,8 @@ out_check:
if (cow_start != (u64)-1) {
ret = cow_file_range(inode, locked_page,
cow_start, found_key.offset - 1,
- page_started, nr_written, 1);
+ end, page_started, nr_written, 1,
+ NULL);
if (ret) {
if (!nolock && nocow)
btrfs_end_write_no_snapshoting(root);
@@ -1501,8 +1505,8 @@ out_check:
}
if (cow_start != (u64)-1) {
- ret = cow_file_range(inode, locked_page, cow_start, end,
- page_started, nr_written, 1);
+ ret = cow_file_range(inode, locked_page, cow_start, end, end,
+ page_started, nr_written, 1, NULL);
if (ret)
goto error;
}
@@ -1561,8 +1565,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
ret = run_delalloc_nocow(inode, locked_page, start, end,
page_started, 0, nr_written);
} else if (!inode_need_compress(inode)) {
- ret = cow_file_range(inode, locked_page, start, end,
- page_started, nr_written, 1);
+ ret = cow_file_range(inode, locked_page, start, end, end,
+ page_started, nr_written, 1, NULL);
} else {
set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
&BTRFS_I(inode)->runtime_flags);
@@ -1740,7 +1744,7 @@ static void btrfs_set_bit_hook(struct inode *inode,
}
/* For sanity tests */
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return;
__percpu_counter_add(&root->fs_info->delalloc_bytes, len,
@@ -1799,7 +1803,7 @@ static void btrfs_clear_bit_hook(struct inode *inode,
btrfs_delalloc_release_metadata(inode, len);
/* For sanity tests. */
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return;
if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
@@ -1822,6 +1826,10 @@ static void btrfs_clear_bit_hook(struct inode *inode,
/*
* extent_io.c merge_bio_hook, this must check the chunk tree to make sure
* we don't create bios that span stripes or chunks
+ *
+ * return 1 if page cannot be merged to bio
+ * return 0 if page can be merged to bio
+ * return error otherwise
*/
int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio,
@@ -1840,8 +1848,8 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
map_length = length;
ret = btrfs_map_block(root->fs_info, bio_op(bio), logical,
&map_length, NULL, 0);
- /* Will always return 0 with map_multi == NULL */
- BUG_ON(ret < 0);
+ if (ret < 0)
+ return ret;
if (map_length < length + size)
return 1;
return 0;
@@ -2594,7 +2602,7 @@ again:
ret = btrfs_insert_empty_item(trans, root, path, &key,
sizeof(*extent));
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_free_path;
}
@@ -2621,7 +2629,7 @@ again:
backref->root_id, backref->inum,
new->file_pos); /* start - extent_offset */
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_free_path;
}
@@ -2890,7 +2898,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
ret = btrfs_update_inode_fallback(trans, root, inode);
if (ret) /* -ENOMEM or corruption */
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -2950,7 +2958,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
ordered_extent->file_offset, ordered_extent->len,
trans->transid);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_unlock;
}
@@ -2960,7 +2968,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
btrfs_ordered_update_i_size(inode, 0, ordered_extent);
ret = btrfs_update_inode_fallback(trans, root, inode);
if (ret) { /* -ENOMEM or corruption */
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_unlock;
}
ret = 0;
@@ -3204,7 +3212,7 @@ void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
ret = btrfs_del_orphan_item(trans, root->fs_info->tree_root,
root->root_key.objectid);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
else
clear_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED,
&root->state);
@@ -3295,7 +3303,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
if (ret != -EEXIST) {
clear_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
&BTRFS_I(inode)->runtime_flags);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
}
@@ -3307,7 +3315,7 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode)
ret = btrfs_insert_orphan_item(trans, root->fs_info->tree_root,
root->root_key.objectid);
if (ret && ret != -EEXIST) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
}
@@ -3427,10 +3435,10 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
found_key.offset = 0;
inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
ret = PTR_ERR_OR_ZERO(inode);
- if (ret && ret != -ESTALE)
+ if (ret && ret != -ENOENT)
goto out;
- if (ret == -ESTALE && root == root->fs_info->tree_root) {
+ if (ret == -ENOENT && root == root->fs_info->tree_root) {
struct btrfs_root *dead_root;
struct btrfs_fs_info *fs_info = root->fs_info;
int is_dead_root = 0;
@@ -3466,7 +3474,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
* Inode is already gone but the orphan item is still there,
* kill the orphan item.
*/
- if (ret == -ESTALE) {
+ if (ret == -ENOENT) {
trans = btrfs_start_transaction(root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
@@ -3625,7 +3633,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
/*
* read an inode from the btree into the in-memory inode
*/
-static void btrfs_read_locked_inode(struct inode *inode)
+static int btrfs_read_locked_inode(struct inode *inode)
{
struct btrfs_path *path;
struct extent_buffer *leaf;
@@ -3644,14 +3652,19 @@ static void btrfs_read_locked_inode(struct inode *inode)
filled = true;
path = btrfs_alloc_path();
- if (!path)
+ if (!path) {
+ ret = -ENOMEM;
goto make_bad;
+ }
memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
ret = btrfs_lookup_inode(NULL, root, path, &location, 0);
- if (ret)
+ if (ret) {
+ if (ret > 0)
+ ret = -ENOENT;
goto make_bad;
+ }
leaf = path->nodes[0];
@@ -3804,11 +3817,12 @@ cache_acl:
}
btrfs_update_iflags(inode);
- return;
+ return 0;
make_bad:
btrfs_free_path(path);
make_bad_inode(inode);
+ return ret;
}
/*
@@ -4006,20 +4020,20 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
btrfs_info(root->fs_info,
"failed to delete reference to %.*s, inode %llu parent %llu",
name_len, name, ino, dir_ino);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto err;
}
skip_backref:
ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto err;
}
ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
inode, dir_ino);
if (ret != 0 && ret != -ENOENT) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto err;
}
@@ -4028,7 +4042,7 @@ skip_backref:
if (ret == -ENOENT)
ret = 0;
else if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
err:
btrfs_free_path(path);
if (ret)
@@ -4142,7 +4156,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid);
ret = btrfs_delete_one_dir_name(trans, root, path, di);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
btrfs_release_path(path);
@@ -4152,7 +4166,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
dir_ino, &index, name, name_len);
if (ret < 0) {
if (ret != -ENOENT) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
di = btrfs_search_dir_index_item(root, path, dir_ino,
@@ -4162,7 +4176,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
ret = -ENOENT;
else
ret = PTR_ERR(di);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -4175,7 +4189,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
ret = btrfs_delete_delayed_dir_index(trans, root, dir, index);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -4184,7 +4198,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
dir->i_mtime = dir->i_ctime = current_fs_time(dir->i_sb);
ret = btrfs_update_inode_fallback(trans, root, dir);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
out:
btrfs_free_path(path);
return ret;
@@ -4196,6 +4210,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
int err = 0;
struct btrfs_root *root = BTRFS_I(dir)->root;
struct btrfs_trans_handle *trans;
+ u64 last_unlink_trans;
if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
return -ENOTEMPTY;
@@ -4218,11 +4233,27 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
if (err)
goto out;
+ last_unlink_trans = BTRFS_I(inode)->last_unlink_trans;
+
/* now the directory is empty */
err = btrfs_unlink_inode(trans, root, dir, d_inode(dentry),
dentry->d_name.name, dentry->d_name.len);
- if (!err)
+ if (!err) {
btrfs_i_size_write(inode, 0);
+ /*
+ * Propagate the last_unlink_trans value of the deleted dir to
+ * its parent directory. This is to prevent an unrecoverable
+ * log tree in the case we do something like this:
+ * 1) create dir foo
+ * 2) create snapshot under dir foo
+ * 3) delete the snapshot
+ * 4) rmdir foo
+ * 5) mkdir foo
+ * 6) fsync foo or some file inside foo
+ */
+ if (last_unlink_trans >= trans->transid)
+ BTRFS_I(dir)->last_unlink_trans = last_unlink_trans;
+ }
out:
btrfs_end_transaction(trans, root);
btrfs_btree_balance_dirty(root);
@@ -4505,7 +4536,6 @@ search_again:
pending_del_nr);
if (err) {
btrfs_abort_transaction(trans,
- root,
err);
goto error;
}
@@ -4517,8 +4547,7 @@ search_again:
item_end,
new_size);
if (err) {
- btrfs_abort_transaction(trans,
- root, err);
+ btrfs_abort_transaction(trans, err);
goto error;
}
} else if (test_bit(BTRFS_ROOT_REF_COWS,
@@ -4582,8 +4611,7 @@ delete:
pending_del_slot,
pending_del_nr);
if (ret) {
- btrfs_abort_transaction(trans,
- root, ret);
+ btrfs_abort_transaction(trans, ret);
goto error;
}
pending_del_nr = 0;
@@ -4616,7 +4644,7 @@ out:
ret = btrfs_del_items(trans, root, path, pending_del_slot,
pending_del_nr);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
}
error:
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
@@ -4785,7 +4813,7 @@ static int maybe_insert_hole(struct btrfs_root *root, struct inode *inode,
ret = btrfs_drop_extents(trans, root, inode, offset, offset + len, 1);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, root);
return ret;
}
@@ -4793,7 +4821,7 @@ static int maybe_insert_hole(struct btrfs_root *root, struct inode *inode,
ret = btrfs_insert_file_extent(trans, root, btrfs_ino(inode), offset,
0, 0, len, 0, len, 0, 0, 0);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
else
btrfs_update_inode(trans, root, inode);
btrfs_end_transaction(trans, root);
@@ -5020,7 +5048,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
i_size_write(inode, BTRFS_I(inode)->disk_i_size);
err = btrfs_orphan_del(trans, inode);
if (err)
- btrfs_abort_transaction(trans, root, err);
+ btrfs_abort_transaction(trans, err);
btrfs_end_transaction(trans, root);
}
}
@@ -5158,11 +5186,18 @@ void btrfs_evict_inode(struct inode *inode)
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_block_rsv *rsv, *global_rsv;
int steal_from_global = 0;
- u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
+ u64 min_size;
int ret;
trace_btrfs_inode_evict(inode);
+ if (!root) {
+ kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
+ return;
+ }
+
+ min_size = btrfs_calc_trunc_metadata_size(root, 1);
+
evict_inode_truncate_pages(inode);
if (inode->i_nlink &&
@@ -5594,7 +5629,9 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
return ERR_PTR(-ENOMEM);
if (inode->i_state & I_NEW) {
- btrfs_read_locked_inode(inode);
+ int ret;
+
+ ret = btrfs_read_locked_inode(inode);
if (!is_bad_inode(inode)) {
inode_tree_add(inode);
unlock_new_inode(inode);
@@ -5603,7 +5640,8 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
} else {
unlock_new_inode(inode);
iput(inode);
- inode = ERR_PTR(-ESTALE);
+ ASSERT(ret < 0);
+ inode = ERR_PTR(ret < 0 ? ret : -ESTALE);
}
}
@@ -6239,9 +6277,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
btrfs_inherit_iflags(inode, dir);
if (S_ISREG(mode)) {
- if (btrfs_test_opt(root, NODATASUM))
+ if (btrfs_test_opt(root->fs_info, NODATASUM))
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
- if (btrfs_test_opt(root, NODATACOW))
+ if (btrfs_test_opt(root->fs_info, NODATACOW))
BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW |
BTRFS_INODE_NODATASUM;
}
@@ -6319,7 +6357,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
if (ret == -EEXIST || ret == -EOVERFLOW)
goto fail_dir_item;
else if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
}
@@ -6330,7 +6368,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
current_fs_time(parent_inode->i_sb);
ret = btrfs_update_inode(trans, root, parent_inode);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
return ret;
fail_dir_item:
@@ -8197,7 +8235,7 @@ static void btrfs_end_dio_bio(struct bio *bio)
if (err)
btrfs_warn(BTRFS_I(dip->inode)->root->fs_info,
"direct IO failed ino %llu rw %d,%u sector %#Lx len %u err no %d",
- btrfs_ino(dip->inode), bio_op(bio), bio->bi_rw,
+ btrfs_ino(dip->inode), bio_op(bio), bio->bi_opf,
(unsigned long long)bio->bi_iter.bi_sector,
bio->bi_iter.bi_size, err);
@@ -8361,7 +8399,7 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip,
if (!bio)
return -ENOMEM;
- bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw);
+ bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
@@ -8399,7 +8437,7 @@ next_block:
start_sector, GFP_NOFS);
if (!bio)
goto out_err;
- bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw);
+ bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_opf);
bio->bi_private = dip;
bio->bi_end_io = btrfs_end_dio_bio;
btrfs_io_bio(bio)->logical = file_offset;
@@ -9385,25 +9423,25 @@ int btrfs_init_cachep(void)
btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle",
sizeof(struct btrfs_trans_handle), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
if (!btrfs_trans_handle_cachep)
goto fail;
btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction",
sizeof(struct btrfs_transaction), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
if (!btrfs_transaction_cachep)
goto fail;
btrfs_path_cachep = kmem_cache_create("btrfs_path",
sizeof(struct btrfs_path), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_path_cachep)
goto fail;
btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space",
sizeof(struct btrfs_free_space), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+ SLAB_MEM_SPREAD, NULL);
if (!btrfs_free_space_cachep)
goto fail;
@@ -9553,7 +9591,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
ret = btrfs_update_inode(trans, root, old_inode);
}
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9573,7 +9611,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
ret = btrfs_update_inode(trans, dest, new_inode);
}
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9581,7 +9619,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
new_dentry->d_name.name,
new_dentry->d_name.len, 0, old_idx);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9589,7 +9627,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
old_dentry->d_name.name,
old_dentry->d_name.len, 0, new_idx);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9828,7 +9866,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
ret = btrfs_update_inode(trans, root, old_inode);
}
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9852,7 +9890,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (!ret && new_inode->i_nlink == 0)
ret = btrfs_orphan_add(trans, d_inode(new_dentry));
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
}
@@ -9861,7 +9899,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
new_dentry->d_name.name,
new_dentry->d_name.len, 0, index);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
@@ -9881,7 +9919,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
old_dentry);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_fail;
}
}
@@ -10307,7 +10345,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
if (ret) {
btrfs_free_reserved_extent(root, ins.objectid,
ins.offset, 0);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
if (own_trans)
btrfs_end_transaction(trans, root);
break;
@@ -10367,7 +10405,7 @@ next:
ret = btrfs_update_inode(trans, root, inode);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
if (own_trans)
btrfs_end_transaction(trans, root);
break;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 05173563e4a6..14ed1e9e6bc8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -561,7 +561,7 @@ static noinline int create_subvol(struct inode *dir,
new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
if (IS_ERR(new_root)) {
ret = PTR_ERR(new_root);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -570,7 +570,7 @@ static noinline int create_subvol(struct inode *dir,
ret = btrfs_create_subvol_root(trans, new_root, root, new_dirid);
if (ret) {
/* We potentially lose an unused inode item here */
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -583,7 +583,7 @@ static noinline int create_subvol(struct inode *dir,
*/
ret = btrfs_set_inode_index(dir, &index);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -591,7 +591,7 @@ static noinline int create_subvol(struct inode *dir,
name, namelen, dir, &key,
BTRFS_FT_DIR, index);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -608,7 +608,7 @@ static noinline int create_subvol(struct inode *dir,
root_item->uuid, BTRFS_UUID_KEY_SUBVOL,
objectid);
if (ret)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
fail:
kfree(root_item);
@@ -1948,8 +1948,7 @@ static noinline int key_in_sk(struct btrfs_key *key,
return 1;
}
-static noinline int copy_to_sk(struct btrfs_root *root,
- struct btrfs_path *path,
+static noinline int copy_to_sk(struct btrfs_path *path,
struct btrfs_key *key,
struct btrfs_ioctl_search_key *sk,
size_t *buf_size,
@@ -2120,7 +2119,7 @@ static noinline int search_ioctl(struct inode *inode,
ret = 0;
goto err;
}
- ret = copy_to_sk(root, path, &key, sk, buf_size, ubuf,
+ ret = copy_to_sk(path, &key, sk, buf_size, ubuf,
&sk_offset, &num_found);
btrfs_release_path(path);
if (ret)
@@ -2406,7 +2405,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
* rmdir(2).
*/
err = -EPERM;
- if (!btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
+ if (!btrfs_test_opt(root->fs_info, USER_SUBVOL_RM_ALLOWED))
goto out_dput;
/*
@@ -2489,7 +2488,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
dentry->d_name.len);
if (ret) {
err = ret;
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_end_trans;
}
@@ -2505,7 +2504,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
root->fs_info->tree_root,
dest->root_key.objectid);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
err = ret;
goto out_end_trans;
}
@@ -2515,7 +2514,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
dest->root_item.uuid, BTRFS_UUID_KEY_SUBVOL,
dest->root_key.objectid);
if (ret && ret != -ENOENT) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
err = ret;
goto out_end_trans;
}
@@ -2525,7 +2524,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
BTRFS_UUID_KEY_RECEIVED_SUBVOL,
dest->root_key.objectid);
if (ret && ret != -ENOENT) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
err = ret;
goto out_end_trans;
}
@@ -3292,7 +3291,7 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
ret = btrfs_update_inode(trans, root, inode);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, root);
goto out;
}
@@ -3694,7 +3693,7 @@ process_slot:
if (ret) {
if (ret != -EOPNOTSUPP)
btrfs_abort_transaction(trans,
- root, ret);
+ ret);
btrfs_end_transaction(trans, root);
goto out;
}
@@ -3702,8 +3701,7 @@ process_slot:
ret = btrfs_insert_empty_item(trans, root, path,
&new_key, size);
if (ret) {
- btrfs_abort_transaction(trans, root,
- ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, root);
goto out;
}
@@ -3735,7 +3733,6 @@ process_slot:
new_key.offset - datao);
if (ret) {
btrfs_abort_transaction(trans,
- root,
ret);
btrfs_end_transaction(trans,
root);
@@ -3772,7 +3769,6 @@ process_slot:
if (ret) {
if (ret != -EOPNOTSUPP)
btrfs_abort_transaction(trans,
- root,
ret);
btrfs_end_transaction(trans, root);
goto out;
@@ -3828,7 +3824,7 @@ process_slot:
last_dest_end, destoff + len, 1);
if (ret) {
if (ret != -EOPNOTSUPP)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, root);
goto out;
}
@@ -5164,13 +5160,13 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
BTRFS_UUID_KEY_RECEIVED_SUBVOL,
root->root_key.objectid);
if (ret < 0 && ret != -EEXIST) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
ret = btrfs_commit_transaction(trans, root);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index aca8264f4a49..3b78d38173b3 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -1122,7 +1122,7 @@ int __init ordered_data_init(void)
{
btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent",
sizeof(struct btrfs_ordered_extent), 0,
- SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
+ SLAB_MEM_SPREAD,
NULL);
if (!btrfs_ordered_extent_cache)
return -ENOMEM;
diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
index 36992128c746..cf0b444ac4f3 100644
--- a/fs/btrfs/props.c
+++ b/fs/btrfs/props.c
@@ -350,6 +350,7 @@ int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
struct btrfs_root *parent_root)
{
+ struct super_block *sb = root->fs_info->sb;
struct btrfs_key key;
struct inode *parent_inode, *child_inode;
int ret;
@@ -358,12 +359,11 @@ int btrfs_subvol_inherit_props(struct btrfs_trans_handle *trans,
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
- parent_inode = btrfs_iget(parent_root->fs_info->sb, &key,
- parent_root, NULL);
+ parent_inode = btrfs_iget(sb, &key, parent_root, NULL);
if (IS_ERR(parent_inode))
return PTR_ERR(parent_inode);
- child_inode = btrfs_iget(root->fs_info->sb, &key, root, NULL);
+ child_inode = btrfs_iget(sb, &key, root, NULL);
if (IS_ERR(child_inode)) {
iput(parent_inode);
return PTR_ERR(child_inode);
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 9d4c05b14f6e..93ee1c18ef9d 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -571,7 +571,7 @@ static int add_qgroup_item(struct btrfs_trans_handle *trans,
struct extent_buffer *leaf;
struct btrfs_key key;
- if (btrfs_test_is_dummy_root(quota_root))
+ if (btrfs_is_testing(quota_root->fs_info))
return 0;
path = btrfs_alloc_path();
@@ -728,7 +728,7 @@ static int update_qgroup_info_item(struct btrfs_trans_handle *trans,
int ret;
int slot;
- if (btrfs_test_is_dummy_root(root))
+ if (btrfs_is_testing(root->fs_info))
return 0;
key.objectid = 0;
@@ -1453,9 +1453,10 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
return ret;
}
-struct btrfs_qgroup_extent_record
-*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
- struct btrfs_qgroup_extent_record *record)
+struct btrfs_qgroup_extent_record *
+btrfs_qgroup_insert_dirty_extent(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_qgroup_extent_record *record)
{
struct rb_node **p = &delayed_refs->dirty_extent_root.rb_node;
struct rb_node *parent_node = NULL;
@@ -1463,7 +1464,7 @@ struct btrfs_qgroup_extent_record
u64 bytenr = record->bytenr;
assert_spin_locked(&delayed_refs->lock);
- trace_btrfs_qgroup_insert_dirty_extent(record);
+ trace_btrfs_qgroup_insert_dirty_extent(fs_info, record);
while (*p) {
parent_node = *p;
@@ -1595,8 +1596,8 @@ static int qgroup_update_counters(struct btrfs_fs_info *fs_info,
cur_old_count = btrfs_qgroup_get_old_refcnt(qg, seq);
cur_new_count = btrfs_qgroup_get_new_refcnt(qg, seq);
- trace_qgroup_update_counters(qg->qgroupid, cur_old_count,
- cur_new_count);
+ trace_qgroup_update_counters(fs_info, qg->qgroupid,
+ cur_old_count, cur_new_count);
/* Rfer update part */
if (cur_old_count == 0 && cur_new_count > 0) {
@@ -1687,8 +1688,8 @@ btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
goto out_free;
BUG_ON(!fs_info->quota_root);
- trace_btrfs_qgroup_account_extent(bytenr, num_bytes, nr_old_roots,
- nr_new_roots);
+ trace_btrfs_qgroup_account_extent(fs_info, bytenr, num_bytes,
+ nr_old_roots, nr_new_roots);
qgroups = ulist_alloc(GFP_NOFS);
if (!qgroups) {
@@ -1759,7 +1760,7 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,
record = rb_entry(node, struct btrfs_qgroup_extent_record,
node);
- trace_btrfs_qgroup_account_extents(record);
+ trace_btrfs_qgroup_account_extents(fs_info, record);
if (!ret) {
/*
@@ -2195,7 +2196,7 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
{
if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
return;
- btrfs_err(trans->root->fs_info,
+ btrfs_err(trans->fs_info,
"qgroups not uptodate in trans handle %p: list is%s empty, "
"seq is %#x.%x",
trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index ecb2c143ef75..710887c06aaf 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -63,9 +63,10 @@ void btrfs_free_qgroup_config(struct btrfs_fs_info *fs_info);
struct btrfs_delayed_extent_op;
int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info);
-struct btrfs_qgroup_extent_record
-*btrfs_qgroup_insert_dirty_extent(struct btrfs_delayed_ref_root *delayed_refs,
- struct btrfs_qgroup_extent_record *record);
+struct btrfs_qgroup_extent_record *
+btrfs_qgroup_insert_dirty_extent(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_root *delayed_refs,
+ struct btrfs_qgroup_extent_record *record);
int
btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans,
struct btrfs_fs_info *fs_info,
@@ -88,7 +89,7 @@ static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info,
u64 ref_root, u64 num_bytes)
{
btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes);
- trace_btrfs_qgroup_free_delayed_ref(ref_root, num_bytes);
+ trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes);
}
void assert_qgroups_uptodate(struct btrfs_trans_handle *trans);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index fc067b07e31f..b26a5aea41b4 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -235,12 +235,12 @@ static void backref_cache_cleanup(struct backref_cache *cache)
cache->last_trans = 0;
for (i = 0; i < BTRFS_MAX_LEVEL; i++)
- BUG_ON(!list_empty(&cache->pending[i]));
- BUG_ON(!list_empty(&cache->changed));
- BUG_ON(!list_empty(&cache->detached));
- BUG_ON(!RB_EMPTY_ROOT(&cache->rb_root));
- BUG_ON(cache->nr_nodes);
- BUG_ON(cache->nr_edges);
+ ASSERT(list_empty(&cache->pending[i]));
+ ASSERT(list_empty(&cache->changed));
+ ASSERT(list_empty(&cache->detached));
+ ASSERT(RB_EMPTY_ROOT(&cache->rb_root));
+ ASSERT(!cache->nr_nodes);
+ ASSERT(!cache->nr_edges);
}
static struct backref_node *alloc_backref_node(struct backref_cache *cache)
@@ -1171,8 +1171,12 @@ out:
lower = list_entry(useless.next,
struct backref_node, list);
list_del_init(&lower->list);
+ if (lower == node)
+ node = NULL;
free_backref_node(cache, lower);
}
+
+ free_backref_node(cache, node);
return ERR_PTR(err);
}
ASSERT(!node || !node->detached);
@@ -1719,7 +1723,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
btrfs_header_owner(leaf),
key.objectid, key.offset);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
break;
}
@@ -1727,7 +1731,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
parent, btrfs_header_owner(leaf),
key.objectid, key.offset);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
break;
}
}
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index f1c30861d062..7fd7e1830cfe 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -150,7 +150,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -176,20 +176,20 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
ret = btrfs_search_slot(trans, root, key, path,
-1, 1);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
ret = btrfs_del_item(trans, root, path);
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
btrfs_release_path(path);
ret = btrfs_insert_empty_item(trans, root, path,
key, sizeof(*item));
if (ret < 0) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
l = path->nodes[0];
@@ -448,7 +448,7 @@ again:
ret = btrfs_insert_empty_item(trans, tree_root, path, &key,
sizeof(*ref) + name_len);
if (ret) {
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_free_path(path);
return ret;
}
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index e08b6bc676e3..1d195d2b32c6 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3785,27 +3785,27 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info,
if (fs_info->scrub_workers_refcnt == 0) {
if (is_dev_replace)
fs_info->scrub_workers =
- btrfs_alloc_workqueue("scrub", flags,
+ btrfs_alloc_workqueue(fs_info, "scrub", flags,
1, 4);
else
fs_info->scrub_workers =
- btrfs_alloc_workqueue("scrub", flags,
+ btrfs_alloc_workqueue(fs_info, "scrub", flags,
max_active, 4);
if (!fs_info->scrub_workers)
goto fail_scrub_workers;
fs_info->scrub_wr_completion_workers =
- btrfs_alloc_workqueue("scrubwrc", flags,
+ btrfs_alloc_workqueue(fs_info, "scrubwrc", flags,
max_active, 2);
if (!fs_info->scrub_wr_completion_workers)
goto fail_scrub_wr_completion_workers;
fs_info->scrub_nocow_workers =
- btrfs_alloc_workqueue("scrubnc", flags, 1, 0);
+ btrfs_alloc_workqueue(fs_info, "scrubnc", flags, 1, 0);
if (!fs_info->scrub_nocow_workers)
goto fail_scrub_nocow_workers;
fs_info->scrub_parity_workers =
- btrfs_alloc_workqueue("scrubparity", flags,
+ btrfs_alloc_workqueue(fs_info, "scrubparity", flags,
max_active, 2);
if (!fs_info->scrub_parity_workers)
goto fail_scrub_parity_workers;
@@ -3860,7 +3860,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
if (fs_info->chunk_root->sectorsize != PAGE_SIZE) {
/* not supported for data w/o checksums */
- btrfs_err(fs_info,
+ btrfs_err_rl(fs_info,
"scrub: size assumption sectorsize != PAGE_SIZE "
"(%d != %lu) fails",
fs_info->chunk_root->sectorsize, PAGE_SIZE);
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index b71dd298385c..efe129fe2678 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -231,7 +231,6 @@ struct pending_dir_move {
u64 parent_ino;
u64 ino;
u64 gen;
- bool is_orphan;
struct list_head update_refs;
};
@@ -274,6 +273,39 @@ struct name_cache_entry {
char name[];
};
+static void inconsistent_snapshot_error(struct send_ctx *sctx,
+ enum btrfs_compare_tree_result result,
+ const char *what)
+{
+ const char *result_string;
+
+ switch (result) {
+ case BTRFS_COMPARE_TREE_NEW:
+ result_string = "new";
+ break;
+ case BTRFS_COMPARE_TREE_DELETED:
+ result_string = "deleted";
+ break;
+ case BTRFS_COMPARE_TREE_CHANGED:
+ result_string = "updated";
+ break;
+ case BTRFS_COMPARE_TREE_SAME:
+ ASSERT(0);
+ result_string = "unchanged";
+ break;
+ default:
+ ASSERT(0);
+ result_string = "unexpected";
+ }
+
+ btrfs_err(sctx->send_root->fs_info,
+ "Send: inconsistent snapshot, found %s %s for inode %llu without updated inode item, send root is %llu, parent root is %llu",
+ result_string, what, sctx->cmp_key->objectid,
+ sctx->send_root->root_key.objectid,
+ (sctx->parent_root ?
+ sctx->parent_root->root_key.objectid : 0));
+}
+
static int is_waiting_for_move(struct send_ctx *sctx, u64 ino);
static struct waiting_dir_move *
@@ -1861,7 +1893,8 @@ static int will_overwrite_ref(struct send_ctx *sctx, u64 dir, u64 dir_gen,
* was already unlinked/moved, so we can safely assume that we will not
* overwrite anything at this point in time.
*/
- if (other_inode > sctx->send_progress) {
+ if (other_inode > sctx->send_progress ||
+ is_waiting_for_move(sctx, other_inode)) {
ret = get_inode_info(sctx->parent_root, other_inode, NULL,
who_gen, NULL, NULL, NULL, NULL);
if (ret < 0)
@@ -2502,6 +2535,8 @@ verbose_printk("btrfs: send_utimes %llu\n", ino);
key.type = BTRFS_INODE_ITEM_KEY;
key.offset = 0;
ret = btrfs_search_slot(NULL, sctx->send_root, &key, path, 0, 0);
+ if (ret > 0)
+ ret = -ENOENT;
if (ret < 0)
goto out;
@@ -2947,6 +2982,10 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen,
}
if (loc.objectid > send_progress) {
+ struct orphan_dir_info *odi;
+
+ odi = get_orphan_dir_info(sctx, dir);
+ free_orphan_dir_info(sctx, odi);
ret = 0;
goto out;
}
@@ -3047,7 +3086,6 @@ static int add_pending_dir_move(struct send_ctx *sctx,
pm->parent_ino = parent_ino;
pm->ino = ino;
pm->gen = ino_gen;
- pm->is_orphan = is_orphan;
INIT_LIST_HEAD(&pm->list);
INIT_LIST_HEAD(&pm->update_refs);
RB_CLEAR_NODE(&pm->node);
@@ -3113,6 +3151,48 @@ static struct pending_dir_move *get_pending_dir_moves(struct send_ctx *sctx,
return NULL;
}
+static int path_loop(struct send_ctx *sctx, struct fs_path *name,
+ u64 ino, u64 gen, u64 *ancestor_ino)
+{
+ int ret = 0;
+ u64 parent_inode = 0;
+ u64 parent_gen = 0;
+ u64 start_ino = ino;
+
+ *ancestor_ino = 0;
+ while (ino != BTRFS_FIRST_FREE_OBJECTID) {
+ fs_path_reset(name);
+
+ if (is_waiting_for_rm(sctx, ino))
+ break;
+ if (is_waiting_for_move(sctx, ino)) {
+ if (*ancestor_ino == 0)
+ *ancestor_ino = ino;
+ ret = get_first_ref(sctx->parent_root, ino,
+ &parent_inode, &parent_gen, name);
+ } else {
+ ret = __get_cur_name_and_parent(sctx, ino, gen,
+ &parent_inode,
+ &parent_gen, name);
+ if (ret > 0) {
+ ret = 0;
+ break;
+ }
+ }
+ if (ret < 0)
+ break;
+ if (parent_inode == start_ino) {
+ ret = 1;
+ if (*ancestor_ino == 0)
+ *ancestor_ino = ino;
+ break;
+ }
+ ino = parent_inode;
+ gen = parent_gen;
+ }
+ return ret;
+}
+
static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
{
struct fs_path *from_path = NULL;
@@ -3123,6 +3203,8 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
u64 parent_ino, parent_gen;
struct waiting_dir_move *dm = NULL;
u64 rmdir_ino = 0;
+ u64 ancestor;
+ bool is_orphan;
int ret;
name = fs_path_alloc();
@@ -3135,9 +3217,10 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
dm = get_waiting_dir_move(sctx, pm->ino);
ASSERT(dm);
rmdir_ino = dm->rmdir_ino;
+ is_orphan = dm->orphanized;
free_waiting_dir_move(sctx, dm);
- if (pm->is_orphan) {
+ if (is_orphan) {
ret = gen_unique_name(sctx, pm->ino,
pm->gen, from_path);
} else {
@@ -3155,6 +3238,24 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
goto out;
sctx->send_progress = sctx->cur_ino + 1;
+ ret = path_loop(sctx, name, pm->ino, pm->gen, &ancestor);
+ if (ret < 0)
+ goto out;
+ if (ret) {
+ LIST_HEAD(deleted_refs);
+ ASSERT(ancestor > BTRFS_FIRST_FREE_OBJECTID);
+ ret = add_pending_dir_move(sctx, pm->ino, pm->gen, ancestor,
+ &pm->update_refs, &deleted_refs,
+ is_orphan);
+ if (ret < 0)
+ goto out;
+ if (rmdir_ino) {
+ dm = get_waiting_dir_move(sctx, pm->ino);
+ ASSERT(dm);
+ dm->rmdir_ino = rmdir_ino;
+ }
+ goto out;
+ }
fs_path_reset(name);
to_path = name;
name = NULL;
@@ -3174,7 +3275,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
/* already deleted */
goto finish;
}
- ret = can_rmdir(sctx, rmdir_ino, odi->gen, sctx->cur_ino + 1);
+ ret = can_rmdir(sctx, rmdir_ino, odi->gen, sctx->cur_ino);
if (ret < 0)
goto out;
if (!ret)
@@ -3204,8 +3305,18 @@ finish:
* and old parent(s).
*/
list_for_each_entry(cur, &pm->update_refs, list) {
- if (cur->dir == rmdir_ino)
+ /*
+ * The parent inode might have been deleted in the send snapshot
+ */
+ ret = get_inode_info(sctx->send_root, cur->dir, NULL,
+ NULL, NULL, NULL, NULL, NULL);
+ if (ret == -ENOENT) {
+ ret = 0;
continue;
+ }
+ if (ret < 0)
+ goto out;
+
ret = send_utimes(sctx, cur->dir, cur->dir_gen);
if (ret < 0)
goto out;
@@ -3325,6 +3436,7 @@ static int wait_for_dest_dir_move(struct send_ctx *sctx,
u64 left_gen;
u64 right_gen;
int ret = 0;
+ struct waiting_dir_move *wdm;
if (RB_EMPTY_ROOT(&sctx->waiting_dir_moves))
return 0;
@@ -3383,7 +3495,8 @@ static int wait_for_dest_dir_move(struct send_ctx *sctx,
goto out;
}
- if (is_waiting_for_move(sctx, di_key.objectid)) {
+ wdm = get_waiting_dir_move(sctx, di_key.objectid);
+ if (wdm && !wdm->orphanized) {
ret = add_pending_dir_move(sctx,
sctx->cur_ino,
sctx->cur_inode_gen,
@@ -3470,7 +3583,8 @@ static int wait_for_parent_move(struct send_ctx *sctx,
ret = is_ancestor(sctx->parent_root,
sctx->cur_ino, sctx->cur_inode_gen,
ino, path_before);
- break;
+ if (ret)
+ break;
}
fs_path_reset(path_before);
@@ -3643,11 +3757,26 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
goto out;
if (ret) {
struct name_cache_entry *nce;
+ struct waiting_dir_move *wdm;
ret = orphanize_inode(sctx, ow_inode, ow_gen,
cur->full_path);
if (ret < 0)
goto out;
+
+ /*
+ * If ow_inode has its rename operation delayed
+ * make sure that its orphanized name is used in
+ * the source path when performing its rename
+ * operation.
+ */
+ if (is_waiting_for_move(sctx, ow_inode)) {
+ wdm = get_waiting_dir_move(sctx,
+ ow_inode);
+ ASSERT(wdm);
+ wdm->orphanized = true;
+ }
+
/*
* Make sure we clear our orphanized inode's
* name from the name cache. This is because the
@@ -3663,6 +3792,19 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
name_cache_delete(sctx, nce);
kfree(nce);
}
+
+ /*
+ * ow_inode might currently be an ancestor of
+ * cur_ino, therefore compute valid_path (the
+ * current path of cur_ino) again because it
+ * might contain the pre-orphanization name of
+ * ow_inode, which is no longer valid.
+ */
+ fs_path_reset(valid_path);
+ ret = get_cur_path(sctx, sctx->cur_ino,
+ sctx->cur_inode_gen, valid_path);
+ if (ret < 0)
+ goto out;
} else {
ret = send_unlink(sctx, cur->full_path);
if (ret < 0)
@@ -5602,7 +5744,10 @@ static int changed_ref(struct send_ctx *sctx,
{
int ret = 0;
- BUG_ON(sctx->cur_ino != sctx->cmp_key->objectid);
+ if (sctx->cur_ino != sctx->cmp_key->objectid) {
+ inconsistent_snapshot_error(sctx, result, "reference");
+ return -EIO;
+ }
if (!sctx->cur_inode_new_gen &&
sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) {
@@ -5627,7 +5772,10 @@ static int changed_xattr(struct send_ctx *sctx,
{
int ret = 0;
- BUG_ON(sctx->cur_ino != sctx->cmp_key->objectid);
+ if (sctx->cur_ino != sctx->cmp_key->objectid) {
+ inconsistent_snapshot_error(sctx, result, "xattr");
+ return -EIO;
+ }
if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
if (result == BTRFS_COMPARE_TREE_NEW)
@@ -5651,7 +5799,10 @@ static int changed_extent(struct send_ctx *sctx,
{
int ret = 0;
- BUG_ON(sctx->cur_ino != sctx->cmp_key->objectid);
+ if (sctx->cur_ino != sctx->cmp_key->objectid) {
+ inconsistent_snapshot_error(sctx, result, "extent");
+ return -EIO;
+ }
if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
if (result != BTRFS_COMPARE_TREE_DELETED)
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 60e7179ed4b7..864ce334f696 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -184,6 +184,22 @@ static const char * const logtypes[] = {
"debug",
};
+
+/*
+ * Use one ratelimit state per log level so that a flood of less important
+ * messages doesn't cause more important ones to be dropped.
+ */
+static struct ratelimit_state printk_limits[] = {
+ RATELIMIT_STATE_INIT(printk_limits[0], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[1], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[2], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[3], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[4], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[5], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[6], DEFAULT_RATELIMIT_INTERVAL, 100),
+ RATELIMIT_STATE_INIT(printk_limits[7], DEFAULT_RATELIMIT_INTERVAL, 100),
+};
+
void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
{
struct super_block *sb = fs_info->sb;
@@ -192,6 +208,7 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
va_list args;
const char *type = logtypes[4];
int kern_level;
+ struct ratelimit_state *ratelimit;
va_start(args, fmt);
@@ -202,13 +219,18 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
lvl[size] = '\0';
fmt += size;
type = logtypes[kern_level - '0'];
- } else
+ ratelimit = &printk_limits[kern_level - '0'];
+ } else {
*lvl = '\0';
+ /* Default to debug output */
+ ratelimit = &printk_limits[7];
+ }
vaf.fmt = fmt;
vaf.va = &args;
- printk("%sBTRFS %s (device %s): %pV\n", lvl, type, sb->s_id, &vaf);
+ if (__ratelimit(ratelimit))
+ printk("%sBTRFS %s (device %s): %pV\n", lvl, type, sb->s_id, &vaf);
va_end(args);
}
@@ -229,9 +251,11 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
*/
__cold
void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
- struct btrfs_root *root, const char *function,
+ const char *function,
unsigned int line, int errno)
{
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+
trans->aborted = errno;
/* Nothing used. The other threads that have joined this
* transaction may be able to continue. */
@@ -239,16 +263,16 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
const char *errstr;
errstr = btrfs_decode_error(errno);
- btrfs_warn(root->fs_info,
+ btrfs_warn(fs_info,
"%s:%d: Aborting unused transaction(%s).",
function, line, errstr);
return;
}
ACCESS_ONCE(trans->transaction->aborted) = errno;
/* Wake up anybody who may be waiting on this transaction */
- wake_up(&root->fs_info->transaction_wait);
- wake_up(&root->fs_info->transaction_blocked_wait);
- __btrfs_handle_fs_error(root->fs_info, function, line, errno, NULL);
+ wake_up(&fs_info->transaction_wait);
+ wake_up(&fs_info->transaction_blocked_wait);
+ __btrfs_handle_fs_error(fs_info, function, line, errno, NULL);
}
/*
* __btrfs_panic decodes unexpected, fatal errors from the caller,
@@ -432,12 +456,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
*/
break;
case Opt_nodatasum:
- btrfs_set_and_info(root, NODATASUM,
+ btrfs_set_and_info(info, NODATASUM,
"setting nodatasum");
break;
case Opt_datasum:
- if (btrfs_test_opt(root, NODATASUM)) {
- if (btrfs_test_opt(root, NODATACOW))
+ if (btrfs_test_opt(info, NODATASUM)) {
+ if (btrfs_test_opt(info, NODATACOW))
btrfs_info(root->fs_info, "setting datasum, datacow enabled");
else
btrfs_info(root->fs_info, "setting datasum");
@@ -446,9 +470,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
btrfs_clear_opt(info->mount_opt, NODATASUM);
break;
case Opt_nodatacow:
- if (!btrfs_test_opt(root, NODATACOW)) {
- if (!btrfs_test_opt(root, COMPRESS) ||
- !btrfs_test_opt(root, FORCE_COMPRESS)) {
+ if (!btrfs_test_opt(info, NODATACOW)) {
+ if (!btrfs_test_opt(info, COMPRESS) ||
+ !btrfs_test_opt(info, FORCE_COMPRESS)) {
btrfs_info(root->fs_info,
"setting nodatacow, compression disabled");
} else {
@@ -461,7 +485,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
btrfs_set_opt(info->mount_opt, NODATASUM);
break;
case Opt_datacow:
- btrfs_clear_and_info(root, NODATACOW,
+ btrfs_clear_and_info(info, NODATACOW,
"setting datacow");
break;
case Opt_compress_force:
@@ -470,10 +494,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
/* Fallthrough */
case Opt_compress:
case Opt_compress_type:
- saved_compress_type = btrfs_test_opt(root, COMPRESS) ?
+ saved_compress_type = btrfs_test_opt(info,
+ COMPRESS) ?
info->compress_type : BTRFS_COMPRESS_NONE;
saved_compress_force =
- btrfs_test_opt(root, FORCE_COMPRESS);
+ btrfs_test_opt(info, FORCE_COMPRESS);
if (token == Opt_compress ||
token == Opt_compress_force ||
strcmp(args[0].from, "zlib") == 0) {
@@ -513,10 +538,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
*/
btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
}
- if ((btrfs_test_opt(root, COMPRESS) &&
+ if ((btrfs_test_opt(info, COMPRESS) &&
(info->compress_type != saved_compress_type ||
compress_force != saved_compress_force)) ||
- (!btrfs_test_opt(root, COMPRESS) &&
+ (!btrfs_test_opt(info, COMPRESS) &&
no_compress == 1)) {
btrfs_info(root->fs_info,
"%s %s compression",
@@ -526,25 +551,25 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
compress_force = false;
break;
case Opt_ssd:
- btrfs_set_and_info(root, SSD,
+ btrfs_set_and_info(info, SSD,
"use ssd allocation scheme");
break;
case Opt_ssd_spread:
- btrfs_set_and_info(root, SSD_SPREAD,
+ btrfs_set_and_info(info, SSD_SPREAD,
"use spread ssd allocation scheme");
btrfs_set_opt(info->mount_opt, SSD);
break;
case Opt_nossd:
- btrfs_set_and_info(root, NOSSD,
+ btrfs_set_and_info(info, NOSSD,
"not using ssd allocation scheme");
btrfs_clear_opt(info->mount_opt, SSD);
break;
case Opt_barrier:
- btrfs_clear_and_info(root, NOBARRIER,
+ btrfs_clear_and_info(info, NOBARRIER,
"turning on barriers");
break;
case Opt_nobarrier:
- btrfs_set_and_info(root, NOBARRIER,
+ btrfs_set_and_info(info, NOBARRIER,
"turning off barriers");
break;
case Opt_thread_pool:
@@ -604,24 +629,24 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
root->fs_info->sb->s_flags &= ~MS_POSIXACL;
break;
case Opt_notreelog:
- btrfs_set_and_info(root, NOTREELOG,
+ btrfs_set_and_info(info, NOTREELOG,
"disabling tree log");
break;
case Opt_treelog:
- btrfs_clear_and_info(root, NOTREELOG,
+ btrfs_clear_and_info(info, NOTREELOG,
"enabling tree log");
break;
case Opt_norecovery:
case Opt_nologreplay:
- btrfs_set_and_info(root, NOLOGREPLAY,
+ btrfs_set_and_info(info, NOLOGREPLAY,
"disabling log replay at mount time");
break;
case Opt_flushoncommit:
- btrfs_set_and_info(root, FLUSHONCOMMIT,
+ btrfs_set_and_info(info, FLUSHONCOMMIT,
"turning on flush-on-commit");
break;
case Opt_noflushoncommit:
- btrfs_clear_and_info(root, FLUSHONCOMMIT,
+ btrfs_clear_and_info(info, FLUSHONCOMMIT,
"turning off flush-on-commit");
break;
case Opt_ratio:
@@ -638,11 +663,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
}
break;
case Opt_discard:
- btrfs_set_and_info(root, DISCARD,
+ btrfs_set_and_info(info, DISCARD,
"turning on discard");
break;
case Opt_nodiscard:
- btrfs_clear_and_info(root, DISCARD,
+ btrfs_clear_and_info(info, DISCARD,
"turning off discard");
break;
case Opt_space_cache:
@@ -651,12 +676,13 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
strcmp(args[0].from, "v1") == 0) {
btrfs_clear_opt(root->fs_info->mount_opt,
FREE_SPACE_TREE);
- btrfs_set_and_info(root, SPACE_CACHE,
+ btrfs_set_and_info(info, SPACE_CACHE,
"enabling disk space caching");
} else if (strcmp(args[0].from, "v2") == 0) {
btrfs_clear_opt(root->fs_info->mount_opt,
SPACE_CACHE);
- btrfs_set_and_info(root, FREE_SPACE_TREE,
+ btrfs_set_and_info(info,
+ FREE_SPACE_TREE,
"enabling free space tree");
} else {
ret = -EINVAL;
@@ -667,12 +693,14 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
btrfs_set_opt(info->mount_opt, RESCAN_UUID_TREE);
break;
case Opt_no_space_cache:
- if (btrfs_test_opt(root, SPACE_CACHE)) {
- btrfs_clear_and_info(root, SPACE_CACHE,
+ if (btrfs_test_opt(info, SPACE_CACHE)) {
+ btrfs_clear_and_info(info,
+ SPACE_CACHE,
"disabling disk space caching");
}
- if (btrfs_test_opt(root, FREE_SPACE_TREE)) {
- btrfs_clear_and_info(root, FREE_SPACE_TREE,
+ if (btrfs_test_opt(info, FREE_SPACE_TREE)) {
+ btrfs_clear_and_info(info,
+ FREE_SPACE_TREE,
"disabling free space tree");
}
break;
@@ -685,7 +713,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
"disabling inode map caching");
break;
case Opt_clear_cache:
- btrfs_set_and_info(root, CLEAR_CACHE,
+ btrfs_set_and_info(info, CLEAR_CACHE,
"force clearing of disk cache");
break;
case Opt_user_subvol_rm_allowed:
@@ -698,11 +726,11 @@ int btrfs_parse_options(struct btrfs_root *root, char *options,
btrfs_clear_opt(info->mount_opt, ENOSPC_DEBUG);
break;
case Opt_defrag:
- btrfs_set_and_info(root, AUTO_DEFRAG,
+ btrfs_set_and_info(info, AUTO_DEFRAG,
"enabling auto defrag");
break;
case Opt_nodefrag:
- btrfs_clear_and_info(root, AUTO_DEFRAG,
+ btrfs_clear_and_info(info, AUTO_DEFRAG,
"disabling auto defrag");
break;
case Opt_recovery:
@@ -810,22 +838,22 @@ check:
/*
* Extra check for current option against current flag
*/
- if (btrfs_test_opt(root, NOLOGREPLAY) && !(new_flags & MS_RDONLY)) {
+ if (btrfs_test_opt(info, NOLOGREPLAY) && !(new_flags & MS_RDONLY)) {
btrfs_err(root->fs_info,
"nologreplay must be used with ro mount option");
ret = -EINVAL;
}
out:
if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) &&
- !btrfs_test_opt(root, FREE_SPACE_TREE) &&
- !btrfs_test_opt(root, CLEAR_CACHE)) {
+ !btrfs_test_opt(info, FREE_SPACE_TREE) &&
+ !btrfs_test_opt(info, CLEAR_CACHE)) {
btrfs_err(root->fs_info, "cannot disable free space tree");
ret = -EINVAL;
}
- if (!ret && btrfs_test_opt(root, SPACE_CACHE))
+ if (!ret && btrfs_test_opt(info, SPACE_CACHE))
btrfs_info(root->fs_info, "disk space caching is enabled");
- if (!ret && btrfs_test_opt(root, FREE_SPACE_TREE))
+ if (!ret && btrfs_test_opt(info, FREE_SPACE_TREE))
btrfs_info(root->fs_info, "using free space tree");
kfree(orig);
return ret;
@@ -1149,7 +1177,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
struct btrfs_root *root = fs_info->tree_root;
- trace_btrfs_sync_fs(wait);
+ trace_btrfs_sync_fs(fs_info, wait);
if (!wait) {
filemap_flush(fs_info->btree_inode->i_mapping);
@@ -1192,13 +1220,13 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
struct btrfs_root *root = info->tree_root;
char *compress_type;
- if (btrfs_test_opt(root, DEGRADED))
+ if (btrfs_test_opt(info, DEGRADED))
seq_puts(seq, ",degraded");
- if (btrfs_test_opt(root, NODATASUM))
+ if (btrfs_test_opt(info, NODATASUM))
seq_puts(seq, ",nodatasum");
- if (btrfs_test_opt(root, NODATACOW))
+ if (btrfs_test_opt(info, NODATACOW))
seq_puts(seq, ",nodatacow");
- if (btrfs_test_opt(root, NOBARRIER))
+ if (btrfs_test_opt(info, NOBARRIER))
seq_puts(seq, ",nobarrier");
if (info->max_inline != BTRFS_DEFAULT_MAX_INLINE)
seq_printf(seq, ",max_inline=%llu", info->max_inline);
@@ -1207,56 +1235,56 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
if (info->thread_pool_size != min_t(unsigned long,
num_online_cpus() + 2, 8))
seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
- if (btrfs_test_opt(root, COMPRESS)) {
+ if (btrfs_test_opt(info, COMPRESS)) {
if (info->compress_type == BTRFS_COMPRESS_ZLIB)
compress_type = "zlib";
else
compress_type = "lzo";
- if (btrfs_test_opt(root, FORCE_COMPRESS))
+ if (btrfs_test_opt(info, FORCE_COMPRESS))
seq_printf(seq, ",compress-force=%s", compress_type);
else
seq_printf(seq, ",compress=%s", compress_type);
}
- if (btrfs_test_opt(root, NOSSD))
+ if (btrfs_test_opt(info, NOSSD))
seq_puts(seq, ",nossd");
- if (btrfs_test_opt(root, SSD_SPREAD))
+ if (btrfs_test_opt(info, SSD_SPREAD))
seq_puts(seq, ",ssd_spread");
- else if (btrfs_test_opt(root, SSD))
+ else if (btrfs_test_opt(info, SSD))
seq_puts(seq, ",ssd");
- if (btrfs_test_opt(root, NOTREELOG))
+ if (btrfs_test_opt(info, NOTREELOG))
seq_puts(seq, ",notreelog");
- if (btrfs_test_opt(root, NOLOGREPLAY))
+ if (btrfs_test_opt(info, NOLOGREPLAY))
seq_puts(seq, ",nologreplay");
- if (btrfs_test_opt(root, FLUSHONCOMMIT))
+ if (btrfs_test_opt(info, FLUSHONCOMMIT))
seq_puts(seq, ",flushoncommit");
- if (btrfs_test_opt(root, DISCARD))
+ if (btrfs_test_opt(info, DISCARD))
seq_puts(seq, ",discard");
if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
seq_puts(seq, ",noacl");
- if (btrfs_test_opt(root, SPACE_CACHE))
+ if (btrfs_test_opt(info, SPACE_CACHE))
seq_puts(seq, ",space_cache");
- else if (btrfs_test_opt(root, FREE_SPACE_TREE))
+ else if (btrfs_test_opt(info, FREE_SPACE_TREE))
seq_puts(seq, ",space_cache=v2");
else
seq_puts(seq, ",nospace_cache");
- if (btrfs_test_opt(root, RESCAN_UUID_TREE))
+ if (btrfs_test_opt(info, RESCAN_UUID_TREE))
seq_puts(seq, ",rescan_uuid_tree");
- if (btrfs_test_opt(root, CLEAR_CACHE))
+ if (btrfs_test_opt(info, CLEAR_CACHE))
seq_puts(seq, ",clear_cache");
- if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
+ if (btrfs_test_opt(info, USER_SUBVOL_RM_ALLOWED))
seq_puts(seq, ",user_subvol_rm_allowed");
- if (btrfs_test_opt(root, ENOSPC_DEBUG))
+ if (btrfs_test_opt(info, ENOSPC_DEBUG))
seq_puts(seq, ",enospc_debug");
- if (btrfs_test_opt(root, AUTO_DEFRAG))
+ if (btrfs_test_opt(info, AUTO_DEFRAG))
seq_puts(seq, ",autodefrag");
- if (btrfs_test_opt(root, INODE_MAP_CACHE))
+ if (btrfs_test_opt(info, INODE_MAP_CACHE))
seq_puts(seq, ",inode_cache");
- if (btrfs_test_opt(root, SKIP_BALANCE))
+ if (btrfs_test_opt(info, SKIP_BALANCE))
seq_puts(seq, ",skip_balance");
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
- if (btrfs_test_opt(root, CHECK_INTEGRITY_INCLUDING_EXTENT_DATA))
+ if (btrfs_test_opt(info, CHECK_INTEGRITY_INCLUDING_EXTENT_DATA))
seq_puts(seq, ",check_int_data");
- else if (btrfs_test_opt(root, CHECK_INTEGRITY))
+ else if (btrfs_test_opt(info, CHECK_INTEGRITY))
seq_puts(seq, ",check_int");
if (info->check_integrity_print_mask)
seq_printf(seq, ",check_int_print_mask=%d",
@@ -1265,14 +1293,14 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
if (info->metadata_ratio)
seq_printf(seq, ",metadata_ratio=%d",
info->metadata_ratio);
- if (btrfs_test_opt(root, PANIC_ON_FATAL_ERROR))
+ if (btrfs_test_opt(info, PANIC_ON_FATAL_ERROR))
seq_puts(seq, ",fatal_errors=panic");
if (info->commit_interval != BTRFS_DEFAULT_COMMIT_INTERVAL)
seq_printf(seq, ",commit=%d", info->commit_interval);
#ifdef CONFIG_BTRFS_DEBUG
- if (btrfs_test_opt(root, FRAGMENT_DATA))
+ if (btrfs_test_opt(info, FRAGMENT_DATA))
seq_puts(seq, ",fragment=data");
- if (btrfs_test_opt(root, FRAGMENT_METADATA))
+ if (btrfs_test_opt(info, FRAGMENT_METADATA))
seq_puts(seq, ",fragment=metadata");
#endif
seq_printf(seq, ",subvolid=%llu",
@@ -2030,9 +2058,6 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
* chunk).
*
* If metadata is exhausted, f_bavail will be 0.
- *
- * FIXME: not accurate for mixed block groups, total and free/used are ok,
- * available appears slightly larger.
*/
static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
{
@@ -2319,49 +2344,6 @@ static void btrfs_print_mod_info(void)
btrfs_crc32c_impl());
}
-static int btrfs_run_sanity_tests(void)
-{
- int ret, i;
- u32 sectorsize, nodesize;
- u32 test_sectorsize[] = {
- PAGE_SIZE,
- };
- ret = btrfs_init_test_fs();
- if (ret)
- return ret;
- for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
- sectorsize = test_sectorsize[i];
- for (nodesize = sectorsize;
- nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
- nodesize <<= 1) {
- pr_info("BTRFS: selftest: sectorsize: %u nodesize: %u\n",
- sectorsize, nodesize);
- ret = btrfs_test_free_space_cache(sectorsize, nodesize);
- if (ret)
- goto out;
- ret = btrfs_test_extent_buffer_operations(sectorsize,
- nodesize);
- if (ret)
- goto out;
- ret = btrfs_test_extent_io(sectorsize, nodesize);
- if (ret)
- goto out;
- ret = btrfs_test_inodes(sectorsize, nodesize);
- if (ret)
- goto out;
- ret = btrfs_test_qgroups(sectorsize, nodesize);
- if (ret)
- goto out;
- ret = btrfs_test_free_space_tree(sectorsize, nodesize);
- if (ret)
- goto out;
- }
- }
-out:
- btrfs_destroy_test_fs();
- return ret;
-}
-
static int __init init_btrfs_fs(void)
{
int err;
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 4879656bda3c..c6569905d3d1 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -326,6 +326,7 @@ SPACE_INFO_ATTR(bytes_used);
SPACE_INFO_ATTR(bytes_pinned);
SPACE_INFO_ATTR(bytes_reserved);
SPACE_INFO_ATTR(bytes_may_use);
+SPACE_INFO_ATTR(bytes_readonly);
SPACE_INFO_ATTR(disk_used);
SPACE_INFO_ATTR(disk_total);
BTRFS_ATTR(total_bytes_pinned, btrfs_space_info_show_total_bytes_pinned);
@@ -337,6 +338,7 @@ static struct attribute *space_info_attrs[] = {
BTRFS_ATTR_PTR(bytes_pinned),
BTRFS_ATTR_PTR(bytes_reserved),
BTRFS_ATTR_PTR(bytes_may_use),
+ BTRFS_ATTR_PTR(bytes_readonly),
BTRFS_ATTR_PTR(disk_used),
BTRFS_ATTR_PTR(disk_total),
BTRFS_ATTR_PTR(total_bytes_pinned),
diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c
index 02223f3f78f4..bf62ad919a95 100644
--- a/fs/btrfs/tests/btrfs-tests.c
+++ b/fs/btrfs/tests/btrfs-tests.c
@@ -54,7 +54,7 @@ struct inode *btrfs_new_test_inode(void)
return new_inode(test_mnt->mnt_sb);
}
-int btrfs_init_test_fs(void)
+static int btrfs_init_test_fs(void)
{
int ret;
@@ -73,7 +73,7 @@ int btrfs_init_test_fs(void)
return 0;
}
-void btrfs_destroy_test_fs(void)
+static void btrfs_destroy_test_fs(void)
{
kern_unmount(test_mnt);
unregister_filesystem(&test_type);
@@ -128,14 +128,27 @@ struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void)
extent_io_tree_init(&fs_info->freed_extents[0], NULL);
extent_io_tree_init(&fs_info->freed_extents[1], NULL);
fs_info->pinned_extents = &fs_info->freed_extents[0];
+ set_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
+
+ test_mnt->mnt_sb->s_fs_info = fs_info;
+
return fs_info;
}
-static void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
+void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info)
{
struct radix_tree_iter iter;
void **slot;
+ if (!fs_info)
+ return;
+
+ if (WARN_ON(!test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO,
+ &fs_info->fs_state)))
+ return;
+
+ test_mnt->mnt_sb->s_fs_info = NULL;
+
spin_lock(&fs_info->buffer_lock);
radix_tree_for_each_slot(slot, &fs_info->buffer_radix, &iter, 0) {
struct extent_buffer *eb;
@@ -167,10 +180,11 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
{
if (!root)
return;
+ /* Will be freed by btrfs_free_fs_roots */
+ if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
+ return;
if (root->node)
free_extent_buffer(root->node);
- if (root->fs_info)
- btrfs_free_dummy_fs_info(root->fs_info);
kfree(root);
}
@@ -220,3 +234,46 @@ void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans)
INIT_LIST_HEAD(&trans->qgroup_ref_list);
trans->type = __TRANS_DUMMY;
}
+
+int btrfs_run_sanity_tests(void)
+{
+ int ret, i;
+ u32 sectorsize, nodesize;
+ u32 test_sectorsize[] = {
+ PAGE_SIZE,
+ };
+ ret = btrfs_init_test_fs();
+ if (ret)
+ return ret;
+ for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
+ sectorsize = test_sectorsize[i];
+ for (nodesize = sectorsize;
+ nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
+ nodesize <<= 1) {
+ pr_info("BTRFS: selftest: sectorsize: %u nodesize: %u\n",
+ sectorsize, nodesize);
+ ret = btrfs_test_free_space_cache(sectorsize, nodesize);
+ if (ret)
+ goto out;
+ ret = btrfs_test_extent_buffer_operations(sectorsize,
+ nodesize);
+ if (ret)
+ goto out;
+ ret = btrfs_test_extent_io(sectorsize, nodesize);
+ if (ret)
+ goto out;
+ ret = btrfs_test_inodes(sectorsize, nodesize);
+ if (ret)
+ goto out;
+ ret = btrfs_test_qgroups(sectorsize, nodesize);
+ if (ret)
+ goto out;
+ ret = btrfs_test_free_space_tree(sectorsize, nodesize);
+ if (ret)
+ goto out;
+ }
+ }
+out:
+ btrfs_destroy_test_fs();
+ return ret;
+}
diff --git a/fs/btrfs/tests/btrfs-tests.h b/fs/btrfs/tests/btrfs-tests.h
index 66fb6b701eb7..b17ffbe8f9f3 100644
--- a/fs/btrfs/tests/btrfs-tests.h
+++ b/fs/btrfs/tests/btrfs-tests.h
@@ -20,57 +20,29 @@
#define __BTRFS_TESTS
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+int btrfs_run_sanity_tests(void);
#define test_msg(fmt, ...) pr_info("BTRFS: selftest: " fmt, ##__VA_ARGS__)
struct btrfs_root;
struct btrfs_trans_handle;
-int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize);
int btrfs_test_extent_buffer_operations(u32 sectorsize, u32 nodesize);
+int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize);
int btrfs_test_extent_io(u32 sectorsize, u32 nodesize);
int btrfs_test_inodes(u32 sectorsize, u32 nodesize);
int btrfs_test_qgroups(u32 sectorsize, u32 nodesize);
int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize);
-int btrfs_init_test_fs(void);
-void btrfs_destroy_test_fs(void);
struct inode *btrfs_new_test_inode(void);
struct btrfs_fs_info *btrfs_alloc_dummy_fs_info(void);
+void btrfs_free_dummy_fs_info(struct btrfs_fs_info *fs_info);
void btrfs_free_dummy_root(struct btrfs_root *root);
struct btrfs_block_group_cache *
btrfs_alloc_dummy_block_group(unsigned long length, u32 sectorsize);
void btrfs_free_dummy_block_group(struct btrfs_block_group_cache *cache);
void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans);
#else
-static inline int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
-{
- return 0;
-}
-static inline int btrfs_test_extent_buffer_operations(u32 sectorsize,
- u32 nodesize)
-{
- return 0;
-}
-static inline int btrfs_init_test_fs(void)
-{
- return 0;
-}
-static inline void btrfs_destroy_test_fs(void)
-{
-}
-static inline int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
-{
- return 0;
-}
-static inline int btrfs_test_inodes(u32 sectorsize, u32 nodesize)
-{
- return 0;
-}
-static inline int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
-{
- return 0;
-}
-static inline int btrfs_test_free_space_tree(u32 sectorsize, u32 nodesize)
+static inline int btrfs_run_sanity_tests(void)
{
return 0;
}
diff --git a/fs/btrfs/tests/extent-buffer-tests.c b/fs/btrfs/tests/extent-buffer-tests.c
index 4f8cbd1ec5ee..199569174637 100644
--- a/fs/btrfs/tests/extent-buffer-tests.c
+++ b/fs/btrfs/tests/extent-buffer-tests.c
@@ -24,8 +24,9 @@
static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
{
- struct btrfs_path *path;
- struct btrfs_root *root;
+ struct btrfs_fs_info *fs_info;
+ struct btrfs_path *path = NULL;
+ struct btrfs_root *root = NULL;
struct extent_buffer *eb;
struct btrfs_item *item;
char *value = "mary had a little lamb";
@@ -40,17 +41,24 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
test_msg("Running btrfs_split_item tests\n");
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Could not allocate fs_info\n");
+ return -ENOMEM;
+ }
+
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
if (IS_ERR(root)) {
test_msg("Could not allocate root\n");
- return PTR_ERR(root);
+ ret = PTR_ERR(root);
+ goto out;
}
path = btrfs_alloc_path();
if (!path) {
test_msg("Could not allocate path\n");
- kfree(root);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
path->nodes[0] = eb = alloc_dummy_extent_buffer(NULL, nodesize,
@@ -219,7 +227,8 @@ static int test_btrfs_split_item(u32 sectorsize, u32 nodesize)
}
out:
btrfs_free_path(path);
- kfree(root);
+ btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
diff --git a/fs/btrfs/tests/free-space-tests.c b/fs/btrfs/tests/free-space-tests.c
index 3956bb2ff84c..3221c8dee272 100644
--- a/fs/btrfs/tests/free-space-tests.c
+++ b/fs/btrfs/tests/free-space-tests.c
@@ -837,6 +837,7 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group_cache *cache,
int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info;
struct btrfs_block_group_cache *cache;
struct btrfs_root *root = NULL;
int ret = -ENOMEM;
@@ -855,15 +856,17 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
return 0;
}
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- ret = PTR_ERR(root);
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ ret = -ENOMEM;
goto out;
}
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info)
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ ret = PTR_ERR(root);
goto out;
+ }
root->fs_info->extent_root = root;
cache->fs_info = root->fs_info;
@@ -882,6 +885,7 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
out:
btrfs_free_dummy_block_group(cache);
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
test_msg("Free space cache tests finished\n");
return ret;
}
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c
index aac507085ab0..7508d3b42780 100644
--- a/fs/btrfs/tests/free-space-tree-tests.c
+++ b/fs/btrfs/tests/free-space-tree-tests.c
@@ -443,23 +443,24 @@ typedef int (*test_func_t)(struct btrfs_trans_handle *,
static int run_test(test_func_t test_func, int bitmaps,
u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info;
struct btrfs_root *root = NULL;
struct btrfs_block_group_cache *cache = NULL;
struct btrfs_trans_handle trans;
struct btrfs_path *path = NULL;
int ret;
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- test_msg("Couldn't allocate dummy root\n");
- ret = PTR_ERR(root);
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Couldn't allocate dummy fs info\n");
+ ret = -ENOMEM;
goto out;
}
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info) {
- test_msg("Couldn't allocate dummy fs info\n");
- ret = -ENOMEM;
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ test_msg("Couldn't allocate dummy root\n");
+ ret = PTR_ERR(root);
goto out;
}
@@ -534,6 +535,7 @@ out:
btrfs_free_path(path);
btrfs_free_dummy_block_group(cache);
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
diff --git a/fs/btrfs/tests/inode-tests.c b/fs/btrfs/tests/inode-tests.c
index 29648c0a39f1..9f72aeda9220 100644
--- a/fs/btrfs/tests/inode-tests.c
+++ b/fs/btrfs/tests/inode-tests.c
@@ -230,6 +230,7 @@ static unsigned long vacancy_only = 0;
static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info = NULL;
struct inode *inode = NULL;
struct btrfs_root *root = NULL;
struct extent_map *em = NULL;
@@ -248,19 +249,15 @@ static noinline int test_btrfs_get_extent(u32 sectorsize, u32 nodesize)
BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID;
BTRFS_I(inode)->location.offset = 0;
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- test_msg("Couldn't allocate root\n");
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Couldn't allocate dummy fs info\n");
goto out;
}
- /*
- * We do this since btrfs_get_extent wants to assign em->bdev to
- * root->fs_info->fs_devices->latest_bdev.
- */
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info) {
- test_msg("Couldn't allocate dummy fs info\n");
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ test_msg("Couldn't allocate root\n");
goto out;
}
@@ -835,11 +832,13 @@ out:
free_extent_map(em);
iput(inode);
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
static int test_hole_first(u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info = NULL;
struct inode *inode = NULL;
struct btrfs_root *root = NULL;
struct extent_map *em = NULL;
@@ -855,15 +854,15 @@ static int test_hole_first(u32 sectorsize, u32 nodesize)
BTRFS_I(inode)->location.objectid = BTRFS_FIRST_FREE_OBJECTID;
BTRFS_I(inode)->location.offset = 0;
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- test_msg("Couldn't allocate root\n");
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Couldn't allocate dummy fs info\n");
goto out;
}
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info) {
- test_msg("Couldn't allocate dummy fs info\n");
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ test_msg("Couldn't allocate root\n");
goto out;
}
@@ -934,11 +933,13 @@ out:
free_extent_map(em);
iput(inode);
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
static int test_extent_accounting(u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info = NULL;
struct inode *inode = NULL;
struct btrfs_root *root = NULL;
int ret = -ENOMEM;
@@ -949,15 +950,15 @@ static int test_extent_accounting(u32 sectorsize, u32 nodesize)
return ret;
}
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- test_msg("Couldn't allocate root\n");
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Couldn't allocate dummy fs info\n");
goto out;
}
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info) {
- test_msg("Couldn't allocate dummy fs info\n");
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ test_msg("Couldn't allocate root\n");
goto out;
}
@@ -1132,6 +1133,7 @@ out:
NULL, GFP_KERNEL);
iput(inode);
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
index 57a12c0d680b..4407fef7c16c 100644
--- a/fs/btrfs/tests/qgroup-tests.c
+++ b/fs/btrfs/tests/qgroup-tests.c
@@ -453,22 +453,24 @@ static int test_multiple_refs(struct btrfs_root *root,
int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
{
+ struct btrfs_fs_info *fs_info = NULL;
struct btrfs_root *root;
struct btrfs_root *tmp_root;
int ret = 0;
- root = btrfs_alloc_dummy_root(sectorsize, nodesize);
- if (IS_ERR(root)) {
- test_msg("Couldn't allocate root\n");
- return PTR_ERR(root);
+ fs_info = btrfs_alloc_dummy_fs_info();
+ if (!fs_info) {
+ test_msg("Couldn't allocate dummy fs info\n");
+ return -ENOMEM;
}
- root->fs_info = btrfs_alloc_dummy_fs_info();
- if (!root->fs_info) {
- test_msg("Couldn't allocate dummy fs info\n");
- ret = -ENOMEM;
+ root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
+ if (IS_ERR(root)) {
+ test_msg("Couldn't allocate root\n");
+ ret = PTR_ERR(root);
goto out;
}
+
/* We are using this root as our extent root */
root->fs_info->extent_root = root;
@@ -495,7 +497,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
btrfs_set_header_nritems(root->node, 0);
root->alloc_bytenr += 2 * nodesize;
- tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
+ tmp_root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
if (IS_ERR(tmp_root)) {
test_msg("Couldn't allocate a fs root\n");
ret = PTR_ERR(tmp_root);
@@ -510,7 +512,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
goto out;
}
- tmp_root = btrfs_alloc_dummy_root(sectorsize, nodesize);
+ tmp_root = btrfs_alloc_dummy_root(fs_info, sectorsize, nodesize);
if (IS_ERR(tmp_root)) {
test_msg("Couldn't allocate a fs root\n");
ret = PTR_ERR(tmp_root);
@@ -531,5 +533,6 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
ret = test_multiple_refs(root, sectorsize, nodesize);
out:
btrfs_free_dummy_root(root);
+ btrfs_free_dummy_fs_info(fs_info);
return ret;
}
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 948aa186b353..9cca0a721961 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -561,6 +561,7 @@ again:
h->transaction = cur_trans;
h->root = root;
h->use_count = 1;
+ h->fs_info = root->fs_info;
h->type = type;
h->can_flush_pending_bgs = true;
@@ -1491,7 +1492,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
goto dir_item_existed;
} else if (IS_ERR(dir_item)) {
ret = PTR_ERR(dir_item);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
btrfs_release_path(path);
@@ -1504,7 +1505,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
*/
ret = btrfs_run_delayed_items(trans, root);
if (ret) { /* Transaction aborted */
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1543,7 +1544,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
if (ret) {
btrfs_tree_unlock(old);
free_extent_buffer(old);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1554,7 +1555,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_tree_unlock(old);
free_extent_buffer(old);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
/* see comments in should_cow_block() */
@@ -1568,7 +1569,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_tree_unlock(tmp);
free_extent_buffer(tmp);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1580,7 +1581,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_ino(parent_inode), index,
dentry->d_name.name, dentry->d_name.len);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1588,19 +1589,19 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key);
if (IS_ERR(pending->snap)) {
ret = PTR_ERR(pending->snap);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
ret = btrfs_reloc_post_snapshot(trans, pending);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1622,7 +1623,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
/* We have check then name at the beginning, so it is impossible. */
BUG_ON(ret == -EEXIST || ret == -EOVERFLOW);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1632,13 +1633,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
current_fs_time(parent_inode->i_sb);
ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
ret = btrfs_uuid_tree_add(trans, fs_info->uuid_root, new_uuid.b,
BTRFS_UUID_KEY_SUBVOL, objectid);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
if (!btrfs_is_empty_uuid(new_root_item->received_uuid)) {
@@ -1647,14 +1648,14 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
BTRFS_UUID_KEY_RECEIVED_SUBVOL,
objectid);
if (ret && ret != -EEXIST) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
}
ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto fail;
}
@@ -1709,7 +1710,7 @@ static void update_super_roots(struct btrfs_root *root)
super->root = root_item->bytenr;
super->generation = root_item->generation;
super->root_level = root_item->level;
- if (btrfs_test_opt(root, SPACE_CACHE))
+ if (btrfs_test_opt(root->fs_info, SPACE_CACHE))
super->cache_generation = root_item->generation;
if (root->fs_info->update_uuid_tree_gen)
super->uuid_tree_generation = root_item->generation;
@@ -1850,7 +1851,7 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans,
WARN_ON(trans->use_count > 1);
- btrfs_abort_transaction(trans, root, err);
+ btrfs_abort_transaction(trans, err);
spin_lock(&root->fs_info->trans_lock);
@@ -1895,14 +1896,14 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans,
static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
{
- if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT))
+ if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
return btrfs_start_delalloc_roots(fs_info, 1, -1);
return 0;
}
static inline void btrfs_wait_delalloc_flush(struct btrfs_fs_info *fs_info)
{
- if (btrfs_test_opt(fs_info->tree_root, FLUSHONCOMMIT))
+ if (btrfs_test_opt(fs_info, FLUSHONCOMMIT))
btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1);
}
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index c5abee4f01ad..efb122643380 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -128,6 +128,7 @@ struct btrfs_trans_handle {
* Subvolume quota depends on this
*/
struct btrfs_root *root;
+ struct btrfs_fs_info *fs_info;
struct seq_list delayed_ref_elem;
struct list_head qgroup_ref_list;
struct list_head new_bgs;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index c05f69a8ec42..fff3f3efa436 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2757,7 +2757,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
while (1) {
int batch = atomic_read(&root->log_batch);
/* when we're on an ssd, just kick the log commit out */
- if (!btrfs_test_opt(root, SSD) &&
+ if (!btrfs_test_opt(root->fs_info, SSD) &&
test_bit(BTRFS_ROOT_MULTI_LOG_TASKS, &root->state)) {
mutex_unlock(&root->log_mutex);
schedule_timeout_uninterruptible(1);
@@ -2788,7 +2788,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
ret = btrfs_write_marked_extents(log, &log->dirty_log_pages, mark);
if (ret) {
blk_finish_plug(&plug);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_free_logged_extents(log, log_transid);
btrfs_set_log_full_commit(root->fs_info, trans);
mutex_unlock(&root->log_mutex);
@@ -2838,7 +2838,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
btrfs_set_log_full_commit(root->fs_info, trans);
if (ret != -ENOSPC) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
mutex_unlock(&log_root_tree->log_mutex);
goto out;
}
@@ -2898,7 +2898,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
blk_finish_plug(&plug);
if (ret) {
btrfs_set_log_full_commit(root->fs_info, trans);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_free_logged_extents(log, log_transid);
mutex_unlock(&log_root_tree->log_mutex);
goto out_wake_log_root;
@@ -2934,7 +2934,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
ret = write_ctree_super(trans, root->fs_info->tree_root, 1);
if (ret) {
btrfs_set_log_full_commit(root->fs_info, trans);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out_wake_log_root;
}
@@ -2991,7 +2991,7 @@ static void free_log_tree(struct btrfs_trans_handle *trans,
ret = walk_log_tree(trans, log, &wc);
/* I don't think this can happen but just in case */
if (ret)
- btrfs_abort_transaction(trans, log, ret);
+ btrfs_abort_transaction(trans, ret);
while (1) {
ret = find_first_extent_bit(&log->dirty_log_pages,
@@ -3160,7 +3160,7 @@ out_unlock:
btrfs_set_log_full_commit(root->fs_info, trans);
ret = 0;
} else if (ret < 0)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_log_trans(root);
@@ -3193,7 +3193,7 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
btrfs_set_log_full_commit(root->fs_info, trans);
ret = 0;
} else if (ret < 0 && ret != -ENOENT)
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_log_trans(root);
return ret;
@@ -4469,7 +4469,8 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans,
static int btrfs_check_ref_name_override(struct extent_buffer *eb,
const int slot,
const struct btrfs_key *key,
- struct inode *inode)
+ struct inode *inode,
+ u64 *other_ino)
{
int ret;
struct btrfs_path *search_path;
@@ -4528,7 +4529,16 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
search_path, parent,
name, this_name_len, 0);
if (di && !IS_ERR(di)) {
- ret = 1;
+ struct btrfs_key di_key;
+
+ btrfs_dir_item_key_to_cpu(search_path->nodes[0],
+ di, &di_key);
+ if (di_key.type == BTRFS_INODE_ITEM_KEY) {
+ ret = 1;
+ *other_ino = di_key.objectid;
+ } else {
+ ret = -EAGAIN;
+ }
goto out;
} else if (IS_ERR(di)) {
ret = PTR_ERR(di);
@@ -4703,6 +4713,10 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
ins_nr = 0;
ret = btrfs_search_forward(root, &min_key,
path, trans->transid);
+ if (ret < 0) {
+ err = ret;
+ goto out_unlock;
+ }
if (ret != 0)
break;
again:
@@ -4718,16 +4732,71 @@ again:
if ((min_key.type == BTRFS_INODE_REF_KEY ||
min_key.type == BTRFS_INODE_EXTREF_KEY) &&
BTRFS_I(inode)->generation == trans->transid) {
+ u64 other_ino = 0;
+
ret = btrfs_check_ref_name_override(path->nodes[0],
path->slots[0],
- &min_key, inode);
+ &min_key, inode,
+ &other_ino);
if (ret < 0) {
err = ret;
goto out_unlock;
} else if (ret > 0) {
- err = 1;
- btrfs_set_log_full_commit(root->fs_info, trans);
- goto out_unlock;
+ struct btrfs_key inode_key;
+ struct inode *other_inode;
+
+ if (ins_nr > 0) {
+ ins_nr++;
+ } else {
+ ins_nr = 1;
+ ins_start_slot = path->slots[0];
+ }
+ ret = copy_items(trans, inode, dst_path, path,
+ &last_extent, ins_start_slot,
+ ins_nr, inode_only,
+ logged_isize);
+ if (ret < 0) {
+ err = ret;
+ goto out_unlock;
+ }
+ ins_nr = 0;
+ btrfs_release_path(path);
+ inode_key.objectid = other_ino;
+ inode_key.type = BTRFS_INODE_ITEM_KEY;
+ inode_key.offset = 0;
+ other_inode = btrfs_iget(root->fs_info->sb,
+ &inode_key, root,
+ NULL);
+ /*
+ * If the other inode that had a conflicting dir
+ * entry was deleted in the current transaction,
+ * we don't need to do more work nor fallback to
+ * a transaction commit.
+ */
+ if (IS_ERR(other_inode) &&
+ PTR_ERR(other_inode) == -ENOENT) {
+ goto next_key;
+ } else if (IS_ERR(other_inode)) {
+ err = PTR_ERR(other_inode);
+ goto out_unlock;
+ }
+ /*
+ * We are safe logging the other inode without
+ * acquiring its i_mutex as long as we log with
+ * the LOG_INODE_EXISTS mode. We're safe against
+ * concurrent renames of the other inode as well
+ * because during a rename we pin the log and
+ * update the log with the new name before we
+ * unpin it.
+ */
+ err = btrfs_log_inode(trans, root, other_inode,
+ LOG_INODE_EXISTS,
+ 0, LLONG_MAX, ctx);
+ iput(other_inode);
+ if (err)
+ goto out_unlock;
+ else
+ goto next_key;
}
}
@@ -4795,7 +4864,7 @@ next_slot:
ins_nr = 0;
}
btrfs_release_path(path);
-
+next_key:
if (min_key.offset < (u64)-1) {
min_key.offset++;
} else if (min_key.type < max_key.type) {
@@ -4989,8 +5058,12 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
break;
- if (IS_ROOT(parent))
+ if (IS_ROOT(parent)) {
+ inode = d_inode(parent);
+ if (btrfs_must_commit_transaction(trans, inode))
+ ret = 1;
break;
+ }
parent = dget_parent(parent);
dput(old_parent);
@@ -5301,7 +5374,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
sb = inode->i_sb;
- if (btrfs_test_opt(root, NOTREELOG)) {
+ if (btrfs_test_opt(root->fs_info, NOTREELOG)) {
ret = 1;
goto end_no_trans;
}
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 0fb4a959012e..51f125508771 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -140,7 +140,6 @@ static int btrfs_relocate_sys_chunks(struct btrfs_root *root);
static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
-static void btrfs_close_one_device(struct btrfs_device *device);
DEFINE_MUTEX(uuid_mutex);
static LIST_HEAD(fs_uuids);
@@ -853,6 +852,46 @@ static void free_device(struct rcu_head *head)
schedule_work(&device->rcu_work);
}
+static void btrfs_close_one_device(struct btrfs_device *device)
+{
+ struct btrfs_fs_devices *fs_devices = device->fs_devices;
+ struct btrfs_device *new_device;
+ struct rcu_string *name;
+
+ if (device->bdev)
+ fs_devices->open_devices--;
+
+ if (device->writeable &&
+ device->devid != BTRFS_DEV_REPLACE_DEVID) {
+ list_del_init(&device->dev_alloc_list);
+ fs_devices->rw_devices--;
+ }
+
+ if (device->missing)
+ fs_devices->missing_devices--;
+
+ if (device->bdev && device->writeable) {
+ sync_blockdev(device->bdev);
+ invalidate_bdev(device->bdev);
+ }
+
+ new_device = btrfs_alloc_device(NULL, &device->devid,
+ device->uuid);
+ BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
+
+ /* Safe because we are under uuid_mutex */
+ if (device->name) {
+ name = rcu_string_strdup(device->name->str, GFP_NOFS);
+ BUG_ON(!name); /* -ENOMEM */
+ rcu_assign_pointer(new_device->name, name);
+ }
+
+ list_replace_rcu(&device->dev_list, &new_device->dev_list);
+ new_device->fs_devices = device->fs_devices;
+
+ call_rcu(&device->rcu, free_device);
+}
+
static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
{
struct btrfs_device *device, *tmp;
@@ -2399,14 +2438,14 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
ret = init_first_rw_device(trans, root, device);
unlock_chunks(root);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto error_trans;
}
}
ret = btrfs_add_device(trans, root, device);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto error_trans;
}
@@ -2415,7 +2454,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
ret = btrfs_finish_sprout(trans, root);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto error_trans;
}
@@ -2801,7 +2840,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
&dev_extent_len);
if (ret) {
mutex_unlock(&fs_devices->device_list_mutex);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -2820,7 +2859,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
ret = btrfs_update_device(trans, map->stripes[i].dev);
if (ret) {
mutex_unlock(&fs_devices->device_list_mutex);
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
@@ -2829,7 +2868,7 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
ret = btrfs_free_chunk(trans, root, chunk_objectid, chunk_offset);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -2838,14 +2877,14 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
if (map->type & BTRFS_BLOCK_GROUP_SYSTEM) {
ret = btrfs_del_sys_chunk(root, chunk_objectid, chunk_offset);
if (ret) {
- btrfs_abort_transaction(trans, root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
}
ret = btrfs_remove_block_group(trans, extent_root, chunk_offset, em);
if (ret) {
- btrfs_abort_transaction(trans, extent_root, ret);
+ btrfs_abort_transaction(trans, ret);
goto out;
}
@@ -2902,7 +2941,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset)
* chunk tree entries
*/
ret = btrfs_remove_chunk(trans, root, chunk_offset);
- btrfs_end_transaction(trans, root);
+ btrfs_end_transaction(trans, extent_root);
return ret;
}
@@ -3421,7 +3460,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
u64 size_to_free;
u64 chunk_type;
struct btrfs_chunk *chunk;
- struct btrfs_path *path;
+ struct btrfs_path *path = NULL;
struct btrfs_key key;
struct btrfs_key found_key;
struct btrfs_trans_handle *trans;
@@ -3455,13 +3494,33 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
ret = btrfs_shrink_device(device, old_size - size_to_free);
if (ret == -ENOSPC)
break;
- BUG_ON(ret);
+ if (ret) {
+ /* btrfs_shrink_device never returns ret > 0 */
+ WARN_ON(ret > 0);
+ goto error;
+ }
trans = btrfs_start_transaction(dev_root, 0);
- BUG_ON(IS_ERR(trans));
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ btrfs_info_in_rcu(fs_info,
+ "resize: unable to start transaction after shrinking device %s (error %d), old size %llu, new size %llu",
+ rcu_str_deref(device->name), ret,
+ old_size, old_size - size_to_free);
+ goto error;
+ }
ret = btrfs_grow_device(trans, device, old_size);
- BUG_ON(ret);
+ if (ret) {
+ btrfs_end_transaction(trans, dev_root);
+ /* btrfs_grow_device never returns ret > 0 */
+ WARN_ON(ret > 0);
+ btrfs_info_in_rcu(fs_info,
+ "resize: unable to grow device after shrinking device %s (error %d), old size %llu, new size %llu",
+ rcu_str_deref(device->name), ret,
+ old_size, old_size - size_to_free);
+ goto error;
+ }
btrfs_end_transaction(trans, dev_root);
}
@@ -3885,7 +3944,7 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
}
spin_unlock(&fs_info->balance_lock);
- if (btrfs_test_opt(fs_info->tree_root, SKIP_BALANCE)) {
+ if (btrfs_test_opt(fs_info, SKIP_BALANCE)) {
btrfs_info(fs_info, "force skipping balance");
return 0;
}
@@ -4240,7 +4299,7 @@ int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
BTRFS_UUID_TREE_OBJECTID);
if (IS_ERR(uuid_root)) {
ret = PTR_ERR(uuid_root);
- btrfs_abort_transaction(trans, tree_root, ret);
+ btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans, tree_root);
return ret;
}
@@ -4514,8 +4573,7 @@ static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type)
btrfs_set_fs_incompat(info, RAID56);
}
-#define BTRFS_MAX_DEVS(r) ((BTRFS_LEAF_DATA_SIZE(r) \
- - sizeof(struct btrfs_item) \
+#define BTRFS_MAX_DEVS(r) ((BTRFS_MAX_ITEM_SIZE(r) \
- sizeof(struct btrfs_chunk)) \
/ sizeof(struct btrfs_stripe) + 1)
@@ -5954,7 +6012,7 @@ static void btrfs_end_bio(struct bio *bio)
else
btrfs_dev_stat_inc(dev,
BTRFS_DEV_STAT_READ_ERRS);
- if ((bio->bi_rw & WRITE_FLUSH) == WRITE_FLUSH)
+ if ((bio->bi_opf & WRITE_FLUSH) == WRITE_FLUSH)
btrfs_dev_stat_inc(dev,
BTRFS_DEV_STAT_FLUSH_ERRS);
btrfs_dev_stat_print_on_error(dev);
@@ -6031,7 +6089,7 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root,
bio->bi_next = NULL;
spin_lock(&device->io_lock);
- if (bio->bi_rw & REQ_SYNC)
+ if (bio->bi_opf & REQ_SYNC)
pending_bios = &device->pending_sync_bios;
else
pending_bios = &device->pending_bios;
@@ -6069,7 +6127,7 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,
rcu_read_lock();
name = rcu_dereference(dev->name);
pr_debug("btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu "
- "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_rw,
+ "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_opf,
(u64)bio->bi_iter.bi_sector, (u_long)dev->bdev->bd_dev,
name->str, dev->devid, bio->bi_iter.bi_size);
rcu_read_unlock();
@@ -6401,7 +6459,8 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
BTRFS_UUID_SIZE);
map->stripes[i].dev = btrfs_find_device(root->fs_info, devid,
uuid, NULL);
- if (!map->stripes[i].dev && !btrfs_test_opt(root, DEGRADED)) {
+ if (!map->stripes[i].dev &&
+ !btrfs_test_opt(root->fs_info, DEGRADED)) {
free_extent_map(em);
return -EIO;
}
@@ -6469,7 +6528,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_root *root,
fs_devices = find_fsid(fsid);
if (!fs_devices) {
- if (!btrfs_test_opt(root, DEGRADED))
+ if (!btrfs_test_opt(root->fs_info, DEGRADED))
return ERR_PTR(-ENOENT);
fs_devices = alloc_fs_devices(fsid);
@@ -6531,7 +6590,7 @@ static int read_one_dev(struct btrfs_root *root,
device = btrfs_find_device(root->fs_info, devid, dev_uuid, fs_uuid);
if (!device) {
- if (!btrfs_test_opt(root, DEGRADED))
+ if (!btrfs_test_opt(root->fs_info, DEGRADED))
return -EIO;
device = add_missing_dev(root, fs_devices, devid, dev_uuid);
@@ -6540,7 +6599,7 @@ static int read_one_dev(struct btrfs_root *root,
btrfs_warn(root->fs_info, "devid %llu uuid %pU missing",
devid, dev_uuid);
} else {
- if (!device->bdev && !btrfs_test_opt(root, DEGRADED))
+ if (!device->bdev && !btrfs_test_opt(root->fs_info, DEGRADED))
return -EIO;
if(!device->bdev && !device->missing) {
@@ -7143,38 +7202,3 @@ void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info)
fs_devices = fs_devices->seed;
}
}
-
-static void btrfs_close_one_device(struct btrfs_device *device)
-{
- struct btrfs_fs_devices *fs_devices = device->fs_devices;
- struct btrfs_device *new_device;
- struct rcu_string *name;
-
- if (device->bdev)
- fs_devices->open_devices--;
-
- if (device->writeable &&
- device->devid != BTRFS_DEV_REPLACE_DEVID) {
- list_del_init(&device->dev_alloc_list);
- fs_devices->rw_devices--;
- }
-
- if (device->missing)
- fs_devices->missing_devices--;
-
- new_device = btrfs_alloc_device(NULL, &device->devid,
- device->uuid);
- BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
-
- /* Safe because we are under uuid_mutex */
- if (device->name) {
- name = rcu_string_strdup(device->name->str, GFP_NOFS);
- BUG_ON(!name); /* -ENOMEM */
- rcu_assign_pointer(new_device->name, name);
- }
-
- list_replace_rcu(&device->dev_list, &new_device->dev_list);
- new_device->fs_devices = device->fs_devices;
-
- call_rcu(&device->rcu, free_device);
-}
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 4ae75006e73b..3f7c2cd41f8f 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -263,6 +263,8 @@ requeue:
void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
struct cachefiles_object *object)
{
+ blkcnt_t i_blocks = d_backing_inode(object->dentry)->i_blocks;
+
write_lock(&cache->active_lock);
rb_erase(&object->active_node, &cache->active_nodes);
clear_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags);
@@ -273,8 +275,7 @@ void cachefiles_mark_object_inactive(struct cachefiles_cache *cache,
/* This object can now be culled, so we need to let the daemon know
* that there is something it can remove if it needs to.
*/
- atomic_long_add(d_backing_inode(object->dentry)->i_blocks,
- &cache->b_released);
+ atomic_long_add(i_blocks, &cache->b_released);
if (atomic_inc_return(&cache->f_released))
cachefiles_state_changed(cache);
}
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 99115cae1652..16e6ded0b7f2 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1347,9 +1347,12 @@ void ceph_flush_snaps(struct ceph_inode_info *ci,
{
struct inode *inode = &ci->vfs_inode;
struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
- struct ceph_mds_session *session = *psession;
+ struct ceph_mds_session *session = NULL;
int mds;
+
dout("ceph_flush_snaps %p\n", inode);
+ if (psession)
+ session = *psession;
retry:
spin_lock(&ci->i_ceph_lock);
if (!(ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS)) {
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index fa59a85226b2..f72d4ae303b2 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2759,6 +2759,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
} else {
path = NULL;
pathlen = 0;
+ pathbase = 0;
}
spin_lock(&ci->i_ceph_lock);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 4e532536cbc6..4716c54dbfc6 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -903,10 +903,10 @@ static int cifs_ci_hash(const struct dentry *dentry, struct qstr *q)
return 0;
}
-static int cifs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
+static int cifs_ci_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
- struct nls_table *codepage = CIFS_SB(parent->d_sb)->local_nls;
+ struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
wchar_t c1, c2;
int i, l1, l2;
diff --git a/fs/dcache.c b/fs/dcache.c
index b90cf8e09d5b..5c7cc953ac81 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -316,20 +316,6 @@ static void dentry_free(struct dentry *dentry)
call_rcu(&dentry->d_u.d_rcu, __d_free);
}
-/**
- * dentry_rcuwalk_invalidate - invalidate in-progress rcu-walk lookups
- * @dentry: the target dentry
- * After this call, in-progress rcu-walk path lookup will fail. This
- * should be called after unhashing, and after changing d_inode (if
- * the dentry has not already been unhashed).
- */
-static inline void dentry_rcuwalk_invalidate(struct dentry *dentry)
-{
- lockdep_assert_held(&dentry->d_lock);
- /* Go through am invalidation barrier */
- write_seqcount_invalidate(&dentry->d_seq);
-}
-
/*
* Release the dentry's inode, using the filesystem
* d_iput() operation if defined.
@@ -468,7 +454,8 @@ void __d_drop(struct dentry *dentry)
__hlist_bl_del(&dentry->d_hash);
dentry->d_hash.pprev = NULL;
hlist_bl_unlock(b);
- dentry_rcuwalk_invalidate(dentry);
+ /* After this call, in-progress rcu-walk path lookup will fail. */
+ write_seqcount_invalidate(&dentry->d_seq);
}
}
EXPORT_SYMBOL(__d_drop);
@@ -2060,7 +2047,7 @@ static inline bool d_same_name(const struct dentry *dentry,
return false;
return dentry_cmp(dentry, name->name, name->len) == 0;
}
- return parent->d_op->d_compare(parent, dentry,
+ return parent->d_op->d_compare(dentry,
dentry->d_name.len, dentry->d_name.name,
name) == 0;
}
@@ -2163,7 +2150,7 @@ seqretry:
cpu_relax();
goto seqretry;
}
- if (parent->d_op->d_compare(parent, dentry,
+ if (parent->d_op->d_compare(dentry,
tlen, tname, name) != 0)
continue;
} else {
@@ -2352,19 +2339,15 @@ again:
}
EXPORT_SYMBOL(d_delete);
-static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
+static void __d_rehash(struct dentry *entry)
{
+ struct hlist_bl_head *b = d_hash(entry->d_name.hash);
BUG_ON(!d_unhashed(entry));
hlist_bl_lock(b);
hlist_bl_add_head_rcu(&entry->d_hash, b);
hlist_bl_unlock(b);
}
-static void _d_rehash(struct dentry * entry)
-{
- __d_rehash(entry, d_hash(entry->d_name.hash));
-}
-
/**
* d_rehash - add an entry back to the hash
* @entry: dentry to add to the hash
@@ -2375,7 +2358,7 @@ static void _d_rehash(struct dentry * entry)
void d_rehash(struct dentry * entry)
{
spin_lock(&entry->d_lock);
- _d_rehash(entry);
+ __d_rehash(entry);
spin_unlock(&entry->d_lock);
}
EXPORT_SYMBOL(d_rehash);
@@ -2549,7 +2532,7 @@ static inline void __d_add(struct dentry *dentry, struct inode *inode)
raw_write_seqcount_end(&dentry->d_seq);
fsnotify_update_flags(dentry);
}
- _d_rehash(dentry);
+ __d_rehash(dentry);
if (dir)
end_dir_add(dir, n);
spin_unlock(&dentry->d_lock);
@@ -2611,7 +2594,7 @@ struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
alias = NULL;
} else {
__dget_dlock(alias);
- _d_rehash(alias);
+ __d_rehash(alias);
spin_unlock(&alias->d_lock);
}
spin_unlock(&inode->i_lock);
@@ -2636,7 +2619,7 @@ EXPORT_SYMBOL(d_exact_alias);
* Parent inode i_mutex must be held over d_lookup and into this call (to
* keep renames and concurrent inserts, and readdir(2) away).
*/
-void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
+void dentry_update_name_case(struct dentry *dentry, const struct qstr *name)
{
BUG_ON(!inode_is_locked(dentry->d_parent->d_inode));
BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */
@@ -2795,23 +2778,10 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
write_seqcount_begin(&dentry->d_seq);
write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);
+ /* unhash both */
/* __d_drop does write_seqcount_barrier, but they're OK to nest. */
-
- /*
- * Move the dentry to the target hash queue. Don't bother checking
- * for the same hash queue because of how unlikely it is.
- */
__d_drop(dentry);
- __d_rehash(dentry, d_hash(target->d_name.hash));
-
- /*
- * Unhash the target (d_delete() is not usable here). If exchanging
- * the two dentries, then rehash onto the other's hash queue.
- */
__d_drop(target);
- if (exchange) {
- __d_rehash(target, d_hash(dentry->d_name.hash));
- }
/* Switch the names.. */
if (exchange)
@@ -2819,6 +2789,11 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
else
copy_name(dentry, target);
+ /* rehash in new place(s) */
+ __d_rehash(dentry);
+ if (exchange)
+ __d_rehash(target);
+
/* ... and switch them in the tree */
if (IS_ROOT(dentry)) {
/* splicing a tree */
@@ -3038,7 +3013,7 @@ static int prepend(char **buffer, int *buflen, const char *str, int namelen)
* Data dependency barrier is needed to make sure that we see that terminating
* NUL. Alpha strikes again, film at 11...
*/
-static int prepend_name(char **buffer, int *buflen, struct qstr *name)
+static int prepend_name(char **buffer, int *buflen, const struct qstr *name)
{
const char *dname = ACCESS_ONCE(name->name);
u32 dlen = ACCESS_ONCE(name->len);
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index a5e607e8f056..688ccc16b702 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -45,8 +45,7 @@ static struct super_block *efivarfs_sb;
* So we need to perform a case-sensitive match on part 1 and a
* case-insensitive match on part 2.
*/
-static int efivarfs_d_compare(const struct dentry *parent,
- const struct dentry *dentry,
+static int efivarfs_d_compare(const struct dentry *dentry,
unsigned int len, const char *str,
const struct qstr *name)
{
diff --git a/fs/exec.c b/fs/exec.c
index a1789cd684bf..6fcfb3f7b137 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -762,6 +762,39 @@ out_unlock:
}
EXPORT_SYMBOL(setup_arg_pages);
+#else
+
+/*
+ * Transfer the program arguments and environment from the holding pages
+ * onto the stack. The provided stack pointer is adjusted accordingly.
+ */
+int transfer_args_to_stack(struct linux_binprm *bprm,
+ unsigned long *sp_location)
+{
+ unsigned long index, stop, sp;
+ int ret = 0;
+
+ stop = bprm->p >> PAGE_SHIFT;
+ sp = *sp_location;
+
+ for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+ unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
+ char *src = kmap(bprm->page[index]) + offset;
+ sp -= PAGE_SIZE - offset;
+ if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
+ ret = -EFAULT;
+ kunmap(bprm->page[index]);
+ if (ret)
+ goto out;
+ }
+
+ *sp_location = sp;
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL(transfer_args_to_stack);
+
#endif /* CONFIG_MMU */
static struct file *do_open_execat(int fd, struct filename *name, int flags)
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index 19efd1197fa5..61ad490ed67b 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -358,8 +358,8 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
* and the entry itself. Page is returned mapped and unlocked.
* Entry is guaranteed to be valid.
*/
-struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir,
- struct qstr *child, struct page ** res_page)
+struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
+ const struct qstr *child, struct page **res_page)
{
const char *name = child->name;
int namelen = child->len;
@@ -435,7 +435,7 @@ struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
return de;
}
-ino_t ext2_inode_by_name(struct inode *dir, struct qstr *child)
+ino_t ext2_inode_by_name(struct inode *dir, const struct qstr *child)
{
ino_t res = 0;
struct ext2_dir_entry_2 *de;
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 3fb93681bf7f..06af2f92226c 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -757,9 +757,9 @@ extern void ext2_rsv_window_add(struct super_block *sb, struct ext2_reserve_wind
/* dir.c */
extern int ext2_add_link (struct dentry *, struct inode *);
-extern ino_t ext2_inode_by_name(struct inode *, struct qstr *);
+extern ino_t ext2_inode_by_name(struct inode *, const struct qstr *);
extern int ext2_make_empty(struct inode *, struct inode *);
-extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct qstr *, struct page **);
+extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,const struct qstr *, struct page **);
extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
extern int ext2_empty_dir (struct inode *);
extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index e2624275d828..d64d2a515cb2 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -245,7 +245,6 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
bio_put(bio);
return -EFAULT;
}
- bio->bi_rw = fio->op_flags;
bio_set_op_attrs(bio, fio->op, fio->op_flags);
__submit_bio(fio->sbi, bio, fio->type);
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index a485f68a76b1..9054aeac8015 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -219,7 +219,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
* Entry is guaranteed to be valid.
*/
struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
- struct qstr *child, struct page **res_page)
+ const struct qstr *child, struct page **res_page)
{
unsigned long npages = dir_blocks(dir);
struct f2fs_dir_entry *de = NULL;
@@ -272,7 +272,7 @@ struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
return f2fs_find_entry(dir, &dotdot, p);
}
-ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr,
+ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr,
struct page **page)
{
ino_t res = 0;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 7890e9071499..675fa79d86f6 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1914,10 +1914,10 @@ struct page *init_inode_metadata(struct inode *, struct inode *,
void update_parent_metadata(struct inode *, struct inode *, unsigned int);
int room_for_filename(const void *, int, int);
void f2fs_drop_nlink(struct inode *, struct inode *);
-struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *,
+struct f2fs_dir_entry *f2fs_find_entry(struct inode *, const struct qstr *,
struct page **);
struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **);
-ino_t f2fs_inode_by_name(struct inode *, struct qstr *, struct page **);
+ino_t f2fs_inode_by_name(struct inode *, const struct qstr *, struct page **);
void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
struct page *, struct inode *);
int update_dent_inode(struct inode *, struct inode *, const struct qstr *);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 1337c0c7527d..664655b2c55f 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -162,10 +162,10 @@ static int msdos_hash(const struct dentry *dentry, struct qstr *qstr)
* Compare two msdos names. If either of the names are invalid,
* we fall back to doing the standard name comparison.
*/
-static int msdos_cmp(const struct dentry *parent, const struct dentry *dentry,
+static int msdos_cmp(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
- struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
+ struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options;
unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
int error;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 6ccdf3f34f90..92b7363dafa9 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -138,10 +138,10 @@ static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr)
/*
* Case insensitive compare of two vfat names.
*/
-static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
+static int vfat_cmpi(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
- struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
+ struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
unsigned int alen, blen;
/* A filename cannot end in '.' or we treat it like it has none */
@@ -157,7 +157,7 @@ static int vfat_cmpi(const struct dentry *parent, const struct dentry *dentry,
/*
* Case sensitive compare of two vfat names.
*/
-static int vfat_cmp(const struct dentry *parent, const struct dentry *dentry,
+static int vfat_cmp(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
unsigned int alen, blen;
@@ -652,8 +652,8 @@ out_free:
return err;
}
-static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
- int cluster, struct timespec *ts,
+static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
+ int is_dir, int cluster, struct timespec *ts,
struct fat_slot_info *sinfo)
{
struct msdos_dir_slot *slots;
@@ -688,7 +688,7 @@ cleanup:
return err;
}
-static int vfat_find(struct inode *dir, struct qstr *qname,
+static int vfat_find(struct inode *dir, const struct qstr *qname,
struct fat_slot_info *sinfo)
{
unsigned int len = vfat_striptail_len(qname);
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 56c8fda436c0..05713a5da083 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1327,6 +1327,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
dirty = inode->i_state & I_DIRTY;
if (inode->i_state & I_DIRTY_TIME) {
if ((dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) ||
+ wbc->sync_mode == WB_SYNC_ALL ||
unlikely(inode->i_state & I_DIRTY_TIME_EXPIRED) ||
unlikely(time_after(jiffies,
(inode->dirtied_time_when +
@@ -1948,6 +1949,12 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
{
struct backing_dev_info *bdi;
+ /*
+ * If we are expecting writeback progress we must submit plugged IO.
+ */
+ if (blk_needs_flush_plug(current))
+ blk_schedule_flush_plug(current);
+
if (!nr_pages)
nr_pages = get_nr_dirty_pages();
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 5f1627725791..c47b7780ce37 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -146,7 +146,7 @@ static void fuse_invalidate_entry(struct dentry *entry)
}
static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
- u64 nodeid, struct qstr *name,
+ u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg)
{
memset(outarg, 0, sizeof(struct fuse_entry_out));
@@ -282,7 +282,7 @@ int fuse_valid_type(int m)
S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
}
-int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg, struct inode **inode)
{
struct fuse_conn *fc = get_fuse_conn_super(sb);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5db5d24f91a5..d98d8cc84def 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -704,7 +704,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
int generation, struct fuse_attr *attr,
u64 attr_valid, u64 attr_version);
-int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
+int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
struct fuse_entry_out *outarg, struct inode **inode);
/**
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9b7cb37b4ba8..4e05b51120f4 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -673,13 +673,11 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid);
if (!inode) {
struct fuse_entry_out outarg;
- struct qstr name;
+ const struct qstr name = QSTR_INIT(".", 1);
if (!fc->export_support)
goto out_err;
- name.len = 1;
- name.name = ".";
err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg,
&inode);
if (err && err != -ENOENT)
@@ -775,14 +773,12 @@ static struct dentry *fuse_get_parent(struct dentry *child)
struct inode *inode;
struct dentry *parent;
struct fuse_entry_out outarg;
- struct qstr name;
+ const struct qstr name = QSTR_INIT("..", 2);
int err;
if (!fc->export_support)
return ERR_PTR(-ESTALE);
- name.len = 2;
- name.name = "..";
err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
&name, &outarg, &inode);
if (err) {
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index e0621cacf134..e4da0ecd3285 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1800,7 +1800,7 @@ int gfs2_permission(struct inode *inode, int mask)
}
if ((mask & MAY_WRITE) && IS_IMMUTABLE(inode))
- error = -EACCES;
+ error = -EPERM;
else
error = generic_permission(inode, mask);
if (gfs2_holder_initialized(&i_gh))
diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c
index 98cde8ba5dc2..8f4afd3f5108 100644
--- a/fs/hfs/catalog.c
+++ b/fs/hfs/catalog.c
@@ -20,7 +20,7 @@
*
* Given the ID of the parent and the name build a search key.
*/
-void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, struct qstr *name)
+void hfs_cat_build_key(struct super_block *sb, btree_key *key, u32 parent, const struct qstr *name)
{
key->cat.reserved = 0;
key->cat.ParID = cpu_to_be32(parent);
@@ -64,7 +64,7 @@ static int hfs_cat_build_record(hfs_cat_rec *rec, u32 cnid, struct inode *inode)
static int hfs_cat_build_thread(struct super_block *sb,
hfs_cat_rec *rec, int type,
- u32 parentid, struct qstr *name)
+ u32 parentid, const struct qstr *name)
{
rec->type = type;
memset(rec->thread.reserved, 0, sizeof(rec->thread.reserved));
@@ -79,7 +79,7 @@ static int hfs_cat_build_thread(struct super_block *sb,
* Add a new file or directory to the catalog B-tree and
* return a (struct hfs_cat_entry) for it in '*result'.
*/
-int hfs_cat_create(u32 cnid, struct inode *dir, struct qstr *str, struct inode *inode)
+int hfs_cat_create(u32 cnid, struct inode *dir, const struct qstr *str, struct inode *inode)
{
struct hfs_find_data fd;
struct super_block *sb;
@@ -210,7 +210,7 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid,
* Delete the indicated file or directory.
* The associated thread is also removed unless ('with_thread'==0).
*/
-int hfs_cat_delete(u32 cnid, struct inode *dir, struct qstr *str)
+int hfs_cat_delete(u32 cnid, struct inode *dir, const struct qstr *str)
{
struct super_block *sb;
struct hfs_find_data fd;
@@ -277,8 +277,8 @@ out:
* If the destination exists it is removed and a
* (struct hfs_cat_entry) for it is returned in '*result'.
*/
-int hfs_cat_move(u32 cnid, struct inode *src_dir, struct qstr *src_name,
- struct inode *dst_dir, struct qstr *dst_name)
+int hfs_cat_move(u32 cnid, struct inode *src_dir, const struct qstr *src_name,
+ struct inode *dst_dir, const struct qstr *dst_name)
{
struct super_block *sb;
struct hfs_find_data src_fd, dst_fd;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index ee2f385811c8..16f5172ee40d 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -178,11 +178,11 @@ extern int hfs_clear_vbm_bits(struct super_block *, u16, u16);
extern int hfs_cat_keycmp(const btree_key *, const btree_key *);
struct hfs_find_data;
extern int hfs_cat_find_brec(struct super_block *, u32, struct hfs_find_data *);
-extern int hfs_cat_create(u32, struct inode *, struct qstr *, struct inode *);
-extern int hfs_cat_delete(u32, struct inode *, struct qstr *);
-extern int hfs_cat_move(u32, struct inode *, struct qstr *,
- struct inode *, struct qstr *);
-extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *);
+extern int hfs_cat_create(u32, struct inode *, const struct qstr *, struct inode *);
+extern int hfs_cat_delete(u32, struct inode *, const struct qstr *);
+extern int hfs_cat_move(u32, struct inode *, const struct qstr *,
+ struct inode *, const struct qstr *);
+extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, const struct qstr *);
/* dir.c */
extern const struct file_operations hfs_dir_operations;
@@ -201,7 +201,7 @@ extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
extern const struct address_space_operations hfs_aops;
extern const struct address_space_operations hfs_btree_aops;
-extern struct inode *hfs_new_inode(struct inode *, struct qstr *, umode_t);
+extern struct inode *hfs_new_inode(struct inode *, const struct qstr *, umode_t);
extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
extern int hfs_write_inode(struct inode *, struct writeback_control *);
extern int hfs_inode_setattr(struct dentry *, struct iattr *);
@@ -233,11 +233,11 @@ extern const struct dentry_operations hfs_dentry_operations;
extern int hfs_hash_dentry(const struct dentry *, struct qstr *);
extern int hfs_strcmp(const unsigned char *, unsigned int,
const unsigned char *, unsigned int);
-extern int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+extern int hfs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
/* trans.c */
-extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
+extern void hfs_asc2mac(struct super_block *, struct hfs_name *, const struct qstr *);
extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
/* super.c */
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 02a3845363f7..c6a32415735b 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -177,7 +177,7 @@ const struct address_space_operations hfs_aops = {
/*
* hfs_new_inode
*/
-struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
+struct inode *hfs_new_inode(struct inode *dir, const struct qstr *name, umode_t mode)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = new_inode(sb);
diff --git a/fs/hfs/string.c b/fs/hfs/string.c
index ec9f164c35a5..3912209153a8 100644
--- a/fs/hfs/string.c
+++ b/fs/hfs/string.c
@@ -92,7 +92,7 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1,
* Test for equality of two strings in the HFS filename character ordering.
* return 1 on failure and 0 on success
*/
-int hfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+int hfs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
const unsigned char *n1, *n2;
diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c
index b1ce4c7ad3fb..39f5e343bf4d 100644
--- a/fs/hfs/trans.c
+++ b/fs/hfs/trans.c
@@ -94,7 +94,7 @@ out:
* This routine is a inverse to hfs_mac2triv().
* A ':' is replaced by a '/'.
*/
-void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, struct qstr *in)
+void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, const struct qstr *in)
{
struct nls_table *nls_disk = HFS_SB(sb)->nls_disk;
struct nls_table *nls_io = HFS_SB(sb)->nls_io;
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index fb707e8f423a..142534d3c2d5 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -40,7 +40,7 @@ int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
/* Generates key for catalog file/folders record. */
int hfsplus_cat_build_key(struct super_block *sb,
- hfsplus_btree_key *key, u32 parent, struct qstr *str)
+ hfsplus_btree_key *key, u32 parent, const struct qstr *str)
{
int len, err;
@@ -174,7 +174,7 @@ static int hfsplus_cat_build_record(hfsplus_cat_entry *entry,
static int hfsplus_fill_cat_thread(struct super_block *sb,
hfsplus_cat_entry *entry, int type,
- u32 parentid, struct qstr *str)
+ u32 parentid, const struct qstr *str)
{
int err;
@@ -250,7 +250,7 @@ static void hfsplus_subfolders_dec(struct inode *dir)
}
int hfsplus_create_cat(u32 cnid, struct inode *dir,
- struct qstr *str, struct inode *inode)
+ const struct qstr *str, struct inode *inode)
{
struct super_block *sb = dir->i_sb;
struct hfs_find_data fd;
@@ -318,7 +318,7 @@ err2:
return err;
}
-int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str)
+int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str)
{
struct super_block *sb = dir->i_sb;
struct hfs_find_data fd;
@@ -415,8 +415,8 @@ out:
}
int hfsplus_rename_cat(u32 cnid,
- struct inode *src_dir, struct qstr *src_name,
- struct inode *dst_dir, struct qstr *dst_name)
+ struct inode *src_dir, const struct qstr *src_name,
+ struct inode *dst_dir, const struct qstr *dst_name)
{
struct super_block *sb = src_dir->i_sb;
struct hfs_find_data src_fd, dst_fd;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 047245bd2cd6..a3f03b247463 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -445,17 +445,17 @@ int hfsplus_cat_case_cmp_key(const hfsplus_btree_key *k1,
int hfsplus_cat_bin_cmp_key(const hfsplus_btree_key *k1,
const hfsplus_btree_key *k2);
int hfsplus_cat_build_key(struct super_block *sb, hfsplus_btree_key *key,
- u32 parent, struct qstr *str);
+ u32 parent, const struct qstr *str);
void hfsplus_cat_build_key_with_cnid(struct super_block *sb,
hfsplus_btree_key *key, u32 parent);
void hfsplus_cat_set_perms(struct inode *inode, struct hfsplus_perm *perms);
int hfsplus_find_cat(struct super_block *sb, u32 cnid,
struct hfs_find_data *fd);
-int hfsplus_create_cat(u32 cnid, struct inode *dir, struct qstr *str,
+int hfsplus_create_cat(u32 cnid, struct inode *dir, const struct qstr *str,
struct inode *inode);
-int hfsplus_delete_cat(u32 cnid, struct inode *dir, struct qstr *str);
-int hfsplus_rename_cat(u32 cnid, struct inode *src_dir, struct qstr *src_name,
- struct inode *dst_dir, struct qstr *dst_name);
+int hfsplus_delete_cat(u32 cnid, struct inode *dir, const struct qstr *str);
+int hfsplus_rename_cat(u32 cnid, struct inode *src_dir, const struct qstr *src_name,
+ struct inode *dst_dir, const struct qstr *dst_name);
/* dir.c */
extern const struct inode_operations hfsplus_dir_inode_operations;
@@ -520,8 +520,7 @@ int hfsplus_uni2asc(struct super_block *sb, const struct hfsplus_unistr *ustr,
int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr,
int max_unistr_len, const char *astr, int len);
int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str);
-int hfsplus_compare_dentry(const struct dentry *parent,
- const struct dentry *dentry, unsigned int len,
+int hfsplus_compare_dentry(const struct dentry *dentry, unsigned int len,
const char *str, const struct qstr *name);
/* wrapper.c */
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index c13c8a240be3..e563939882f3 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -385,10 +385,10 @@ int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
* Composed unicode characters are decomposed and case-folding is performed
* if the appropriate bits are (un)set on the superblock.
*/
-int hfsplus_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+int hfsplus_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
- struct super_block *sb = parent->d_sb;
+ struct super_block *sb = dentry->d_sb;
int casefold, decompose, size;
int dsize1, dsize2, len1, len2;
const u16 *dstr1, *dstr2;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 5c57654927a6..90e46cd752fe 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -959,10 +959,11 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
if (S_ISLNK(root_inode->i_mode)) {
char *name = follow_link(host_root_path);
- if (IS_ERR(name))
+ if (IS_ERR(name)) {
err = PTR_ERR(name);
- else
- err = read_name(root_inode, name);
+ goto out_put;
+ }
+ err = read_name(root_inode, name);
kfree(name);
if (err)
goto out_put;
diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c
index 60e6d334d79a..bb87d65f0d97 100644
--- a/fs/hpfs/dentry.c
+++ b/fs/hpfs/dentry.c
@@ -34,7 +34,7 @@ static int hpfs_hash_dentry(const struct dentry *dentry, struct qstr *qstr)
return 0;
}
-static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+static int hpfs_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
unsigned al = len;
@@ -50,7 +50,7 @@ static int hpfs_compare_dentry(const struct dentry *parent, const struct dentry
if (hpfs_chk_name(name->name, &bl))
return 1;
- if (hpfs_compare_names(parent->d_sb, str, al, name->name, bl, 0))
+ if (hpfs_compare_names(dentry->d_sb, str, al, name->name, bl, 0))
return 1;
return 0;
}
diff --git a/fs/inode.c b/fs/inode.c
index ad445542c285..7e3ef3af3db9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1729,7 +1729,6 @@ int dentry_needs_remove_privs(struct dentry *dentry)
mask |= ATTR_KILL_PRIV;
return mask;
}
-EXPORT_SYMBOL(dentry_needs_remove_privs);
static int __remove_privs(struct dentry *dentry, int kill)
{
@@ -1749,8 +1748,8 @@ static int __remove_privs(struct dentry *dentry, int kill)
*/
int file_remove_privs(struct file *file)
{
- struct dentry *dentry = file->f_path.dentry;
- struct inode *inode = d_inode(dentry);
+ struct dentry *dentry = file_dentry(file);
+ struct inode *inode = file_inode(file);
int kill;
int error = 0;
@@ -1758,7 +1757,7 @@ int file_remove_privs(struct file *file)
if (IS_NOSEC(inode))
return 0;
- kill = file_needs_remove_privs(file);
+ kill = dentry_needs_remove_privs(dentry);
if (kill < 0)
return kill;
if (kill)
diff --git a/fs/internal.h b/fs/internal.h
index cef0913e5d41..ba0737649d4a 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -111,12 +111,14 @@ extern long do_handle_open(int mountdirfd,
struct file_handle __user *ufh, int open_flag);
extern int open_check_o_direct(struct file *f);
extern int vfs_open(const struct path *, struct file *, const struct cred *);
+extern struct file *filp_clone_open(struct file *);
/*
* inode.c
*/
extern long prune_icache_sb(struct super_block *sb, struct shrink_control *sc);
extern void inode_add_lru(struct inode *inode);
+extern int dentry_needs_remove_privs(struct dentry *dentry);
/*
* fs-writeback.c
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 761fade7680f..ad0c745ebad7 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -29,18 +29,15 @@
#define BEQUIET
static int isofs_hashi(const struct dentry *parent, struct qstr *qstr);
-static int isofs_dentry_cmpi(const struct dentry *parent,
- const struct dentry *dentry,
+static int isofs_dentry_cmpi(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
#ifdef CONFIG_JOLIET
static int isofs_hashi_ms(const struct dentry *parent, struct qstr *qstr);
static int isofs_hash_ms(const struct dentry *parent, struct qstr *qstr);
-static int isofs_dentry_cmpi_ms(const struct dentry *parent,
- const struct dentry *dentry,
+static int isofs_dentry_cmpi_ms(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
-static int isofs_dentry_cmp_ms(const struct dentry *parent,
- const struct dentry *dentry,
+static int isofs_dentry_cmp_ms(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name);
#endif
@@ -235,7 +232,7 @@ isofs_hashi(const struct dentry *dentry, struct qstr *qstr)
}
static int
-isofs_dentry_cmpi(const struct dentry *parent, const struct dentry *dentry,
+isofs_dentry_cmpi(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 0, 1);
@@ -276,14 +273,14 @@ isofs_hashi_ms(const struct dentry *dentry, struct qstr *qstr)
}
static int
-isofs_dentry_cmp_ms(const struct dentry *parent, const struct dentry *dentry,
+isofs_dentry_cmp_ms(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 1, 0);
}
static int
-isofs_dentry_cmpi_ms(const struct dentry *parent, const struct dentry *dentry,
+isofs_dentry_cmpi_ms(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
return isofs_dentry_cmp_common(len, str, name, 1, 1);
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 7b543e6b6526..aee592767f1d 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -22,7 +22,7 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
qstr.len = dlen;
if (likely(!dentry->d_op))
return dentry->d_name.len != dlen || memcmp(dentry->d_name.name, compare, dlen);
- return dentry->d_op->d_compare(NULL, NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
+ return dentry->d_op->d_compare(NULL, dentry->d_name.len, dentry->d_name.name, &qstr);
}
/*
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 04baf0dfc40c..814b0c58016c 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1572,7 +1572,7 @@ static int jfs_ci_hash(const struct dentry *dir, struct qstr *this)
return 0;
}
-static int jfs_ci_compare(const struct dentry *parent, const struct dentry *dentry,
+static int jfs_ci_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
int i, result = 1;
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index bcd754d216bd..9568064ecadf 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -156,7 +156,7 @@ static pgoff_t hash_index(u32 hash, int round)
static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry)
{
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
struct page *page;
struct logfs_disk_dentry *dd;
u32 hash = logfs_hash_32(name->name, name->len, 0);
@@ -323,7 +323,7 @@ static int logfs_readdir(struct file *file, struct dir_context *ctx)
return 0;
}
-static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
+static void logfs_set_name(struct logfs_disk_dentry *dd, const struct qstr *name)
{
dd->namelen = cpu_to_be16(name->len);
memcpy(dd->name, name->name, name->len);
diff --git a/fs/mpage.c b/fs/mpage.c
index 2ca1f39c8cba..d2413af0823a 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -50,7 +50,7 @@ static void mpage_end_io(struct bio *bio)
bio_for_each_segment_all(bv, bio, i) {
struct page *page = bv->bv_page;
- page_endio(page, bio_data_dir(bio), bio->bi_error);
+ page_endio(page, op_is_write(bio_op(bio)), bio->bi_error);
}
bio_put(bio);
diff --git a/fs/namei.c b/fs/namei.c
index c386a329ab20..adb04146df09 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -410,7 +410,7 @@ int __inode_permission(struct inode *inode, int mask)
* Nobody gets write access to an immutable file.
*/
if (IS_IMMUTABLE(inode))
- return -EACCES;
+ return -EPERM;
/*
* Updating mtime will likely cause i_uid and i_gid to be
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 9add7ab747a5..17de5c13dfae 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -74,7 +74,7 @@ const struct inode_operations ncp_dir_inode_operations =
*/
static int ncp_lookup_validate(struct dentry *, unsigned int);
static int ncp_hash_dentry(const struct dentry *, struct qstr *);
-static int ncp_compare_dentry(const struct dentry *, const struct dentry *,
+static int ncp_compare_dentry(const struct dentry *,
unsigned int, const char *, const struct qstr *);
static int ncp_delete_dentry(const struct dentry *);
static void ncp_d_prune(struct dentry *dentry);
@@ -154,7 +154,7 @@ ncp_hash_dentry(const struct dentry *dentry, struct qstr *this)
* the callers will handle races.
*/
static int
-ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
+ncp_compare_dentry(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
struct inode *pinode;
@@ -162,7 +162,7 @@ ncp_compare_dentry(const struct dentry *parent, const struct dentry *dentry,
if (len != name->len)
return 1;
- pinode = d_inode_rcu(parent);
+ pinode = d_inode_rcu(dentry->d_parent);
if (!pinode)
return 1;
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index cb28cceefebe..698be9361280 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -144,7 +144,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
}
static int
-nfs3_proc_lookup(struct inode *dir, struct qstr *name,
+nfs3_proc_lookup(struct inode *dir, const struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
@@ -404,7 +404,7 @@ out:
}
static int
-nfs3_proc_remove(struct inode *dir, struct qstr *name)
+nfs3_proc_remove(struct inode *dir, const struct qstr *name)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
@@ -480,7 +480,7 @@ nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
}
static int
-nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs3_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs3_linkargs arg = {
.fromfh = NFS_FH(inode),
@@ -582,7 +582,7 @@ out:
}
static int
-nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs3_proc_rmdir(struct inode *dir, const struct qstr *name)
{
struct nfs_fattr *dir_attr;
struct nfs3_diropargs arg = {
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 33da841a21bb..6f4752734804 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -338,6 +338,8 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
case 0:
break;
case -NFS4ERR_EXPIRED:
+ case -NFS4ERR_ADMIN_REVOKED:
+ case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_OLD_STATEID:
case -NFS4ERR_BAD_STATEID:
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 4be567a54958..9bf64eacba5b 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -225,7 +225,8 @@ int nfs_atomic_open(struct inode *, struct dentry *, struct file *,
extern struct file_system_type nfs4_fs_type;
/* nfs4namespace.c */
-struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *, struct qstr *);
+struct rpc_clnt *nfs4_negotiate_security(struct rpc_clnt *, struct inode *,
+ const struct qstr *);
struct vfsmount *nfs4_submount(struct nfs_server *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *);
int nfs4_replace_transport(struct nfs_server *server,
@@ -252,7 +253,7 @@ extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struc
extern int nfs4_proc_get_locations(struct inode *, struct nfs4_fs_locations *,
struct page *page, struct rpc_cred *);
extern int nfs4_proc_fsid_present(struct inode *, struct rpc_cred *);
-extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
+extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, const struct qstr *,
struct nfs_fh *, struct nfs_fattr *);
extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
extern const struct xattr_handler *nfs4_xattr_handlers[];
@@ -395,6 +396,10 @@ extern void nfs4_schedule_state_renewal(struct nfs_client *);
extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
extern void nfs4_kill_renewd(struct nfs_client *);
extern void nfs4_renew_state(struct work_struct *);
+extern void nfs4_set_lease_period(struct nfs_client *clp,
+ unsigned long lease,
+ unsigned long lastrenewed);
+
/* nfs4state.c */
struct rpc_cred *nfs4_get_clid_cred(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index f592672373cb..d21104912676 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -208,7 +208,7 @@ static struct rpc_clnt *nfs_find_best_sec(struct rpc_clnt *clnt,
*/
struct rpc_clnt *
nfs4_negotiate_security(struct rpc_clnt *clnt, struct inode *inode,
- struct qstr *name)
+ const struct qstr *name)
{
struct page *page;
struct nfs4_secinfo_flavors *flavors;
@@ -397,7 +397,7 @@ struct vfsmount *nfs4_submount(struct nfs_server *server, struct dentry *dentry,
rpc_authflavor_t flavor = server->client->cl_auth->au_flavor;
struct dentry *parent = dget_parent(dentry);
struct inode *dir = d_inode(parent);
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
struct rpc_clnt *client;
struct vfsmount *mnt;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index da5c9e58e907..1949bbd806eb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3538,7 +3538,7 @@ static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
}
static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
- struct qstr *name, struct nfs_fh *fhandle,
+ const struct qstr *name, struct nfs_fh *fhandle,
struct nfs_fattr *fattr, struct nfs4_label *label)
{
struct nfs4_exception exception = { };
@@ -3580,7 +3580,7 @@ out:
return err;
}
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
+static int nfs4_proc_lookup(struct inode *dir, const struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
@@ -3596,7 +3596,7 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
}
struct rpc_clnt *
-nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
+nfs4_proc_lookup_mountpoint(struct inode *dir, const struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
struct rpc_clnt *client = NFS_CLIENT(dir);
@@ -3755,7 +3755,7 @@ out:
return status;
}
-static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int _nfs4_proc_remove(struct inode *dir, const struct qstr *name)
{
struct nfs_server *server = NFS_SERVER(dir);
struct nfs_removeargs args = {
@@ -3778,7 +3778,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
return status;
}
-static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int nfs4_proc_remove(struct inode *dir, const struct qstr *name)
{
struct nfs4_exception exception = { };
int err;
@@ -3861,7 +3861,7 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
return 1;
}
-static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_link_arg arg = {
@@ -3908,7 +3908,7 @@ out:
return status;
}
-static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs4_exception exception = { };
int err;
@@ -3930,7 +3930,7 @@ struct nfs4_createdata {
};
static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
- struct qstr *name, struct iattr *sattr, u32 ftype)
+ const struct qstr *name, struct iattr *sattr, u32 ftype)
{
struct nfs4_createdata *data;
@@ -4237,12 +4237,9 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str
err = _nfs4_do_fsinfo(server, fhandle, fsinfo);
trace_nfs4_fsinfo(server, fhandle, fsinfo->fattr, err);
if (err == 0) {
- struct nfs_client *clp = server->nfs_client;
-
- spin_lock(&clp->cl_lock);
- clp->cl_lease_time = fsinfo->lease_time * HZ;
- clp->cl_last_renewal = now;
- spin_unlock(&clp->cl_lock);
+ nfs4_set_lease_period(server->nfs_client,
+ fsinfo->lease_time * HZ,
+ now);
break;
}
err = nfs4_handle_exception(server, err, &exception);
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index e1ba58c3d1ad..82e77198d17e 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -136,6 +136,26 @@ nfs4_kill_renewd(struct nfs_client *clp)
cancel_delayed_work_sync(&clp->cl_renewd);
}
+/**
+ * nfs4_set_lease_period - Sets the lease period on a nfs_client
+ *
+ * @clp: pointer to nfs_client
+ * @lease: new value for lease period
+ * @lastrenewed: time at which lease was last renewed
+ */
+void nfs4_set_lease_period(struct nfs_client *clp,
+ unsigned long lease,
+ unsigned long lastrenewed)
+{
+ spin_lock(&clp->cl_lock);
+ clp->cl_lease_time = lease;
+ clp->cl_last_renewal = lastrenewed;
+ spin_unlock(&clp->cl_lock);
+
+ /* Cap maximum reconnect timeout at 1/2 lease period */
+ rpc_cap_max_reconnect_timeout(clp->cl_rpcclient, lease >> 1);
+}
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 834b875900d6..cada00aa5096 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -277,20 +277,17 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
{
int status;
struct nfs_fsinfo fsinfo;
+ unsigned long now;
if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) {
nfs4_schedule_state_renewal(clp);
return 0;
}
+ now = jiffies;
status = nfs4_proc_get_lease_time(clp, &fsinfo);
if (status == 0) {
- /* Update lease time and schedule renewal */
- spin_lock(&clp->cl_lock);
- clp->cl_lease_time = fsinfo.lease_time * HZ;
- clp->cl_last_renewal = jiffies;
- spin_unlock(&clp->cl_lock);
-
+ nfs4_set_lease_period(clp, fsinfo.lease_time * HZ, now);
nfs4_schedule_state_renewal(clp);
}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index b417bbcd9704..b7bca8303989 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -145,7 +145,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
}
static int
-nfs_proc_lookup(struct inode *dir, struct qstr *name,
+nfs_proc_lookup(struct inode *dir, const struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr,
struct nfs4_label *label)
{
@@ -299,7 +299,7 @@ out:
}
static int
-nfs_proc_remove(struct inode *dir, struct qstr *name)
+nfs_proc_remove(struct inode *dir, const struct qstr *name)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
@@ -357,7 +357,7 @@ nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
}
static int
-nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs_linkargs arg = {
.fromfh = NFS_FH(inode),
@@ -456,7 +456,7 @@ out:
}
static int
-nfs_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs_proc_rmdir(struct inode *dir, const struct qstr *name)
{
struct nfs_diropargs arg = {
.fh = NFS_FH(dir),
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 1868246f56e6..191aa577dd1f 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -162,7 +162,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
* @dentry: dentry to unlink
*/
static int
-nfs_async_unlink(struct dentry *dentry, struct qstr *name)
+nfs_async_unlink(struct dentry *dentry, const struct qstr *name)
{
struct nfs_unlinkdata *data;
int status = -ENOMEM;
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index c9f583d7bac8..47febcf99185 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -90,6 +90,7 @@ config NFSD_BLOCKLAYOUT
bool "NFSv4.1 server support for pNFS block layouts"
depends on NFSD_V4 && BLOCK
select NFSD_PNFS
+ select EXPORTFS_BLOCK_OPS
help
This option enables support for the exporting pNFS block layouts
in the kernel's NFS server. The pNFS block layout enables NFS
@@ -102,6 +103,7 @@ config NFSD_SCSILAYOUT
bool "NFSv4.1 server support for pNFS SCSI layouts"
depends on NFSD_V4 && BLOCK
select NFSD_PNFS
+ select EXPORTFS_BLOCK_OPS
help
This option enables support for the exporting pNFS SCSI layouts
in the kernel's NFS server. The pNFS SCSI layout enables NFS
@@ -111,6 +113,23 @@ config NFSD_SCSILAYOUT
If unsure, say N.
+config NFSD_FLEXFILELAYOUT
+ bool "NFSv4.1 server support for pNFS Flex File layouts"
+ depends on NFSD_V4
+ select NFSD_PNFS
+ help
+ This option enables support for the exporting pNFS Flex File
+ layouts in the kernel's NFS server. The pNFS Flex File layout
+ enables NFS clients to directly perform I/O to NFSv3 devices
+ accesible to both the server and the clients. See
+ draft-ietf-nfsv4-flex-files for more details.
+
+ Warning, this server implements the bare minimum functionality
+ to be a flex file server - it is for testing the client,
+ not for use in production.
+
+ If unsure, say N.
+
config NFSD_V4_SECURITY_LABEL
bool "Provide Security Label support for NFSv4 server"
depends on NFSD_V4 && SECURITY
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index 3ae5f3c77e28..5f5d3a76980c 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -20,3 +20,4 @@ nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
nfsd-$(CONFIG_NFSD_PNFS) += nfs4layouts.o
nfsd-$(CONFIG_NFSD_BLOCKLAYOUT) += blocklayout.o blocklayoutxdr.o
nfsd-$(CONFIG_NFSD_SCSILAYOUT) += blocklayout.o blocklayoutxdr.o
+nfsd-$(CONFIG_NFSD_FLEXFILELAYOUT) += flexfilelayout.o flexfilelayoutxdr.o
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index ad2c05e80a83..5a1708441510 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -163,6 +163,7 @@ nfsd4_block_get_device_info_simple(struct super_block *sb,
static __be32
nfsd4_block_proc_getdeviceinfo(struct super_block *sb,
+ struct svc_rqst *rqstp,
struct nfs4_client *clp,
struct nfsd4_getdeviceinfo *gdp)
{
@@ -355,6 +356,7 @@ nfsd4_block_get_device_info_scsi(struct super_block *sb,
static __be32
nfsd4_scsi_proc_getdeviceinfo(struct super_block *sb,
+ struct svc_rqst *rqstp,
struct nfs4_client *clp,
struct nfsd4_getdeviceinfo *gdp)
{
diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c
index 4ebaaf4b8d8a..ac6f54546fdd 100644
--- a/fs/nfsd/blocklayoutxdr.c
+++ b/fs/nfsd/blocklayoutxdr.c
@@ -44,7 +44,7 @@ nfsd4_block_encode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
switch (b->type) {
case PNFS_BLOCK_VOLUME_SIMPLE:
- len = 4 + 4 + 8 + 4 + b->simple.sig_len;
+ len = 4 + 4 + 8 + 4 + (XDR_QUADLEN(b->simple.sig_len) << 2);
p = xdr_reserve_space(xdr, len);
if (!p)
return -ETOOSMALL;
@@ -55,7 +55,7 @@ nfsd4_block_encode_volume(struct xdr_stream *xdr, struct pnfs_block_volume *b)
p = xdr_encode_opaque(p, b->simple.sig, b->simple.sig_len);
break;
case PNFS_BLOCK_VOLUME_SCSI:
- len = 4 + 4 + 4 + 4 + b->scsi.designator_len + 8;
+ len = 4 + 4 + 4 + 4 + (XDR_QUADLEN(b->scsi.designator_len) << 2) + 8;
p = xdr_reserve_space(xdr, len);
if (!p)
return -ETOOSMALL;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b4d84b579f20..43e109cc0ccc 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -706,7 +706,7 @@ static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
new->ex_fslocs.locations = NULL;
new->ex_fslocs.locations_count = 0;
new->ex_fslocs.migrated = 0;
- new->ex_layout_type = 0;
+ new->ex_layout_types = 0;
new->ex_uuid = NULL;
new->cd = item->cd;
}
@@ -731,7 +731,7 @@ static void export_update(struct cache_head *cnew, struct cache_head *citem)
item->ex_fslocs.locations_count = 0;
new->ex_fslocs.migrated = item->ex_fslocs.migrated;
item->ex_fslocs.migrated = 0;
- new->ex_layout_type = item->ex_layout_type;
+ new->ex_layout_types = item->ex_layout_types;
new->ex_nflavors = item->ex_nflavors;
for (i = 0; i < MAX_SECINFO_LIST; i++) {
new->ex_flavors[i] = item->ex_flavors[i];
@@ -954,6 +954,16 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)
return 0;
}
+
+ /* If the compound op contains a spo_must_allowed op,
+ * it will be sent with integrity/protection which
+ * will have to be expressly allowed on mounts that
+ * don't support it
+ */
+
+ if (nfsd4_spo_must_allow(rqstp))
+ return 0;
+
return nfserr_wrongsec;
}
diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
index 2e315072bf3f..730f15eeb7ed 100644
--- a/fs/nfsd/export.h
+++ b/fs/nfsd/export.h
@@ -57,7 +57,7 @@ struct svc_export {
struct nfsd4_fs_locations ex_fslocs;
uint32_t ex_nflavors;
struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST];
- enum pnfs_layouttype ex_layout_type;
+ u32 ex_layout_types;
struct nfsd4_deviceid_map *ex_devid_map;
struct cache_detail *cd;
};
diff --git a/fs/nfsd/flexfilelayout.c b/fs/nfsd/flexfilelayout.c
new file mode 100644
index 000000000000..df880e9fa71f
--- /dev/null
+++ b/fs/nfsd/flexfilelayout.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
+ *
+ * The following implements a super-simple flex-file server
+ * where the NFSv4.1 mds is also the ds. And the storage is
+ * the same. I.e., writing to the mds via a NFSv4.1 WRITE
+ * goes to the same location as the NFSv3 WRITE.
+ */
+#include <linux/slab.h>
+
+#include <linux/nfsd/debug.h>
+
+#include <linux/sunrpc/addr.h>
+
+#include "flexfilelayoutxdr.h"
+#include "pnfs.h"
+
+#define NFSDDBG_FACILITY NFSDDBG_PNFS
+
+static __be32
+nfsd4_ff_proc_layoutget(struct inode *inode, const struct svc_fh *fhp,
+ struct nfsd4_layoutget *args)
+{
+ struct nfsd4_layout_seg *seg = &args->lg_seg;
+ u32 device_generation = 0;
+ int error;
+ uid_t u;
+
+ struct pnfs_ff_layout *fl;
+
+ /*
+ * The super simple flex file server has 1 mirror, 1 data server,
+ * and 1 file handle. So instead of 4 allocs, do 1 for now.
+ * Zero it out for the stateid - don't want junk in there!
+ */
+ error = -ENOMEM;
+ fl = kzalloc(sizeof(*fl), GFP_KERNEL);
+ if (!fl)
+ goto out_error;
+ args->lg_content = fl;
+
+ /*
+ * Avoid layout commit, try to force the I/O to the DS,
+ * and for fun, cause all IOMODE_RW layout segments to
+ * effectively be WRITE only.
+ */
+ fl->flags = FF_FLAGS_NO_LAYOUTCOMMIT | FF_FLAGS_NO_IO_THRU_MDS |
+ FF_FLAGS_NO_READ_IO;
+
+ /* Do not allow a IOMODE_READ segment to have write pemissions */
+ if (seg->iomode == IOMODE_READ) {
+ u = from_kuid(&init_user_ns, inode->i_uid) + 1;
+ fl->uid = make_kuid(&init_user_ns, u);
+ } else
+ fl->uid = inode->i_uid;
+ fl->gid = inode->i_gid;
+
+ error = nfsd4_set_deviceid(&fl->deviceid, fhp, device_generation);
+ if (error)
+ goto out_error;
+
+ fl->fh.size = fhp->fh_handle.fh_size;
+ memcpy(fl->fh.data, &fhp->fh_handle.fh_base, fl->fh.size);
+
+ /* Give whole file layout segments */
+ seg->offset = 0;
+ seg->length = NFS4_MAX_UINT64;
+
+ dprintk("GET: 0x%llx:0x%llx %d\n", seg->offset, seg->length,
+ seg->iomode);
+ return 0;
+
+out_error:
+ seg->length = 0;
+ return nfserrno(error);
+}
+
+static __be32
+nfsd4_ff_proc_getdeviceinfo(struct super_block *sb, struct svc_rqst *rqstp,
+ struct nfs4_client *clp, struct nfsd4_getdeviceinfo *gdp)
+{
+ struct pnfs_ff_device_addr *da;
+
+ u16 port;
+ char addr[INET6_ADDRSTRLEN];
+
+ da = kzalloc(sizeof(struct pnfs_ff_device_addr), GFP_KERNEL);
+ if (!da)
+ return nfserrno(-ENOMEM);
+
+ gdp->gd_device = da;
+
+ da->version = 3;
+ da->minor_version = 0;
+
+ da->rsize = svc_max_payload(rqstp);
+ da->wsize = da->rsize;
+
+ rpc_ntop((struct sockaddr *)&rqstp->rq_daddr,
+ addr, INET6_ADDRSTRLEN);
+ if (rqstp->rq_daddr.ss_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)&rqstp->rq_daddr;
+ port = ntohs(sin->sin_port);
+ snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp");
+ da->netaddr.netid_len = 3;
+ } else {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)&rqstp->rq_daddr;
+ port = ntohs(sin6->sin6_port);
+ snprintf(da->netaddr.netid, FF_NETID_LEN + 1, "tcp6");
+ da->netaddr.netid_len = 4;
+ }
+
+ da->netaddr.addr_len =
+ snprintf(da->netaddr.addr, FF_ADDR_LEN + 1,
+ "%s.%hhu.%hhu", addr, port >> 8, port & 0xff);
+
+ da->tightly_coupled = false;
+
+ return 0;
+}
+
+const struct nfsd4_layout_ops ff_layout_ops = {
+ .notify_types =
+ NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
+ .proc_getdeviceinfo = nfsd4_ff_proc_getdeviceinfo,
+ .encode_getdeviceinfo = nfsd4_ff_encode_getdeviceinfo,
+ .proc_layoutget = nfsd4_ff_proc_layoutget,
+ .encode_layoutget = nfsd4_ff_encode_layoutget,
+};
diff --git a/fs/nfsd/flexfilelayoutxdr.c b/fs/nfsd/flexfilelayoutxdr.c
new file mode 100644
index 000000000000..5e3fd7fc1a9f
--- /dev/null
+++ b/fs/nfsd/flexfilelayoutxdr.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
+ */
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs4.h>
+
+#include "nfsd.h"
+#include "flexfilelayoutxdr.h"
+
+#define NFSDDBG_FACILITY NFSDDBG_PNFS
+
+struct ff_idmap {
+ char buf[11];
+ int len;
+};
+
+__be32
+nfsd4_ff_encode_layoutget(struct xdr_stream *xdr,
+ struct nfsd4_layoutget *lgp)
+{
+ struct pnfs_ff_layout *fl = lgp->lg_content;
+ int len, mirror_len, ds_len, fh_len;
+ __be32 *p;
+
+ /*
+ * Unlike nfsd4_encode_user, we know these will
+ * always be stringified.
+ */
+ struct ff_idmap uid;
+ struct ff_idmap gid;
+
+ fh_len = 4 + fl->fh.size;
+
+ uid.len = sprintf(uid.buf, "%u", from_kuid(&init_user_ns, fl->uid));
+ gid.len = sprintf(gid.buf, "%u", from_kgid(&init_user_ns, fl->gid));
+
+ /* 8 + len for recording the length, name, and padding */
+ ds_len = 20 + sizeof(stateid_opaque_t) + 4 + fh_len +
+ 8 + uid.len + 8 + gid.len;
+
+ mirror_len = 4 + ds_len;
+
+ /* The layout segment */
+ len = 20 + mirror_len;
+
+ p = xdr_reserve_space(xdr, sizeof(__be32) + len);
+ if (!p)
+ return nfserr_toosmall;
+
+ *p++ = cpu_to_be32(len);
+ p = xdr_encode_hyper(p, 0); /* stripe unit of 1 */
+
+ *p++ = cpu_to_be32(1); /* single mirror */
+ *p++ = cpu_to_be32(1); /* single data server */
+
+ p = xdr_encode_opaque_fixed(p, &fl->deviceid,
+ sizeof(struct nfsd4_deviceid));
+
+ *p++ = cpu_to_be32(1); /* efficiency */
+
+ *p++ = cpu_to_be32(fl->stateid.si_generation);
+ p = xdr_encode_opaque_fixed(p, &fl->stateid.si_opaque,
+ sizeof(stateid_opaque_t));
+
+ *p++ = cpu_to_be32(1); /* single file handle */
+ p = xdr_encode_opaque(p, fl->fh.data, fl->fh.size);
+
+ p = xdr_encode_opaque(p, uid.buf, uid.len);
+ p = xdr_encode_opaque(p, gid.buf, gid.len);
+
+ *p++ = cpu_to_be32(fl->flags);
+ *p++ = cpu_to_be32(0); /* No stats collect hint */
+
+ return 0;
+}
+
+__be32
+nfsd4_ff_encode_getdeviceinfo(struct xdr_stream *xdr,
+ struct nfsd4_getdeviceinfo *gdp)
+{
+ struct pnfs_ff_device_addr *da = gdp->gd_device;
+ int len;
+ int ver_len;
+ int addr_len;
+ __be32 *p;
+
+ /* len + padding for two strings */
+ addr_len = 16 + da->netaddr.netid_len + da->netaddr.addr_len;
+ ver_len = 20;
+
+ len = 4 + ver_len + 4 + addr_len;
+
+ p = xdr_reserve_space(xdr, len + sizeof(__be32));
+ if (!p)
+ return nfserr_resource;
+
+ /*
+ * Fill in the overall length and number of volumes at the beginning
+ * of the layout.
+ */
+ *p++ = cpu_to_be32(len);
+ *p++ = cpu_to_be32(1); /* 1 netaddr */
+ p = xdr_encode_opaque(p, da->netaddr.netid, da->netaddr.netid_len);
+ p = xdr_encode_opaque(p, da->netaddr.addr, da->netaddr.addr_len);
+
+ *p++ = cpu_to_be32(1); /* 1 versions */
+
+ *p++ = cpu_to_be32(da->version);
+ *p++ = cpu_to_be32(da->minor_version);
+ *p++ = cpu_to_be32(da->rsize);
+ *p++ = cpu_to_be32(da->wsize);
+ *p++ = cpu_to_be32(da->tightly_coupled);
+
+ return 0;
+}
diff --git a/fs/nfsd/flexfilelayoutxdr.h b/fs/nfsd/flexfilelayoutxdr.h
new file mode 100644
index 000000000000..467defd4e563
--- /dev/null
+++ b/fs/nfsd/flexfilelayoutxdr.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Tom Haynes <loghyr@primarydata.com>
+ */
+#ifndef _NFSD_FLEXFILELAYOUTXDR_H
+#define _NFSD_FLEXFILELAYOUTXDR_H 1
+
+#include <linux/inet.h>
+#include "xdr4.h"
+
+#define FF_FLAGS_NO_LAYOUTCOMMIT 1
+#define FF_FLAGS_NO_IO_THRU_MDS 2
+#define FF_FLAGS_NO_READ_IO 4
+
+struct xdr_stream;
+
+#define FF_NETID_LEN (4)
+#define FF_ADDR_LEN (INET6_ADDRSTRLEN + 8)
+struct pnfs_ff_netaddr {
+ char netid[FF_NETID_LEN + 1];
+ char addr[FF_ADDR_LEN + 1];
+ u32 netid_len;
+ u32 addr_len;
+};
+
+struct pnfs_ff_device_addr {
+ struct pnfs_ff_netaddr netaddr;
+ u32 version;
+ u32 minor_version;
+ u32 rsize;
+ u32 wsize;
+ bool tightly_coupled;
+};
+
+struct pnfs_ff_layout {
+ u32 flags;
+ u32 stats_collect_hint;
+ kuid_t uid;
+ kgid_t gid;
+ struct nfsd4_deviceid deviceid;
+ stateid_t stateid;
+ struct nfs_fh fh;
+};
+
+__be32 nfsd4_ff_encode_getdeviceinfo(struct xdr_stream *xdr,
+ struct nfsd4_getdeviceinfo *gdp);
+__be32 nfsd4_ff_encode_layoutget(struct xdr_stream *xdr,
+ struct nfsd4_layoutget *lgp);
+
+#endif /* _NFSD_FLEXFILELAYOUTXDR_H */
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index 953c0755cb37..2be9602b0221 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -27,6 +27,9 @@ static const struct nfsd4_callback_ops nfsd4_cb_layout_ops;
static const struct lock_manager_operations nfsd4_layouts_lm_ops;
const struct nfsd4_layout_ops *nfsd4_layout_ops[LAYOUT_TYPE_MAX] = {
+#ifdef CONFIG_NFSD_FLEXFILELAYOUT
+ [LAYOUT_FLEX_FILES] = &ff_layout_ops,
+#endif
#ifdef CONFIG_NFSD_BLOCKLAYOUT
[LAYOUT_BLOCK_VOLUME] = &bl_layout_ops,
#endif
@@ -122,28 +125,35 @@ nfsd4_set_deviceid(struct nfsd4_deviceid *id, const struct svc_fh *fhp,
void nfsd4_setup_layout_type(struct svc_export *exp)
{
+#if defined(CONFIG_NFSD_BLOCKLAYOUT) || defined(CONFIG_NFSD_SCSILAYOUT)
struct super_block *sb = exp->ex_path.mnt->mnt_sb;
+#endif
if (!(exp->ex_flags & NFSEXP_PNFS))
return;
/*
- * Check if the file system supports exporting a block-like layout.
+ * If flex file is configured, use it by default. Otherwise
+ * check if the file system supports exporting a block-like layout.
* If the block device supports reservations prefer the SCSI layout,
* otherwise advertise the block layout.
*/
+#ifdef CONFIG_NFSD_FLEXFILELAYOUT
+ exp->ex_layout_types |= 1 << LAYOUT_FLEX_FILES;
+#endif
#ifdef CONFIG_NFSD_BLOCKLAYOUT
+ /* overwrite flex file layout selection if needed */
if (sb->s_export_op->get_uuid &&
sb->s_export_op->map_blocks &&
sb->s_export_op->commit_blocks)
- exp->ex_layout_type = LAYOUT_BLOCK_VOLUME;
+ exp->ex_layout_types |= 1 << LAYOUT_BLOCK_VOLUME;
#endif
#ifdef CONFIG_NFSD_SCSILAYOUT
/* overwrite block layout selection if needed */
if (sb->s_export_op->map_blocks &&
sb->s_export_op->commit_blocks &&
sb->s_bdev && sb->s_bdev->bd_disk->fops->pr_ops)
- exp->ex_layout_type = LAYOUT_SCSI;
+ exp->ex_layout_types |= 1 << LAYOUT_SCSI;
#endif
}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index de1ff1d98bb1..1fb222752b2b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -605,8 +605,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
fh_init(&resfh, NFS4_FHSIZE);
- status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
- NFSD_MAY_CREATE);
+ status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
if (status)
return status;
@@ -1219,12 +1218,12 @@ nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
static const struct nfsd4_layout_ops *
nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type)
{
- if (!exp->ex_layout_type) {
+ if (!exp->ex_layout_types) {
dprintk("%s: export does not support pNFS\n", __func__);
return NULL;
}
- if (exp->ex_layout_type != layout_type) {
+ if (!(exp->ex_layout_types & (1 << layout_type))) {
dprintk("%s: layout type %d not supported\n",
__func__, layout_type);
return NULL;
@@ -1270,7 +1269,7 @@ nfsd4_getdeviceinfo(struct svc_rqst *rqstp,
nfserr = nfs_ok;
if (gdp->gd_maxcount != 0) {
nfserr = ops->proc_getdeviceinfo(exp->ex_path.mnt->mnt_sb,
- cstate->session->se_client, gdp);
+ rqstp, cstate->session->se_client, gdp);
}
gdp->gd_notify_types &= ops->notify_types;
@@ -2335,6 +2334,45 @@ static struct nfsd4_operation nfsd4_ops[] = {
},
};
+/**
+ * nfsd4_spo_must_allow - Determine if the compound op contains an
+ * operation that is allowed to be sent with machine credentials
+ *
+ * @rqstp: a pointer to the struct svc_rqst
+ *
+ * Checks to see if the compound contains a spo_must_allow op
+ * and confirms that it was sent with the proper machine creds.
+ */
+
+bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
+{
+ struct nfsd4_compoundres *resp = rqstp->rq_resp;
+ struct nfsd4_compoundargs *argp = rqstp->rq_argp;
+ struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
+ struct nfsd4_compound_state *cstate = &resp->cstate;
+ struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;
+ u32 opiter;
+
+ if (!cstate->minorversion)
+ return false;
+
+ if (cstate->spo_must_allowed == true)
+ return true;
+
+ opiter = resp->opcnt;
+ while (opiter < argp->opcnt) {
+ this = &argp->ops[opiter++];
+ if (test_bit(this->opnum, allow->u.longs) &&
+ cstate->clp->cl_mach_cred &&
+ nfsd4_mach_creds_match(cstate->clp, rqstp)) {
+ cstate->spo_must_allowed = true;
+ return true;
+ }
+ }
+ cstate->spo_must_allowed = false;
+ return false;
+}
+
int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
{
struct nfsd4_operation *opdesc;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 70d0b9b33031..a204d7e109d4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1200,27 +1200,6 @@ free_ol_stateid_reaplist(struct list_head *reaplist)
}
}
-static void release_lockowner(struct nfs4_lockowner *lo)
-{
- struct nfs4_client *clp = lo->lo_owner.so_client;
- struct nfs4_ol_stateid *stp;
- struct list_head reaplist;
-
- INIT_LIST_HEAD(&reaplist);
-
- spin_lock(&clp->cl_lock);
- unhash_lockowner_locked(lo);
- while (!list_empty(&lo->lo_owner.so_stateids)) {
- stp = list_first_entry(&lo->lo_owner.so_stateids,
- struct nfs4_ol_stateid, st_perstateowner);
- WARN_ON(!unhash_lock_stateid(stp));
- put_ol_stateid_locked(stp, &reaplist);
- }
- spin_unlock(&clp->cl_lock);
- free_ol_stateid_reaplist(&reaplist);
- nfs4_put_stateowner(&lo->lo_owner);
-}
-
static void release_open_stateid_locks(struct nfs4_ol_stateid *open_stp,
struct list_head *reaplist)
{
@@ -1972,7 +1951,7 @@ static bool svc_rqst_integrity_protected(struct svc_rqst *rqstp)
service == RPC_GSS_SVC_PRIVACY;
}
-static bool mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
+bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp)
{
struct svc_cred *cr = &rqstp->rq_cred;
@@ -2388,6 +2367,22 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
switch (exid->spa_how) {
case SP4_MACH_CRED:
+ exid->spo_must_enforce[0] = 0;
+ exid->spo_must_enforce[1] = (
+ 1 << (OP_BIND_CONN_TO_SESSION - 32) |
+ 1 << (OP_EXCHANGE_ID - 32) |
+ 1 << (OP_CREATE_SESSION - 32) |
+ 1 << (OP_DESTROY_SESSION - 32) |
+ 1 << (OP_DESTROY_CLIENTID - 32));
+
+ exid->spo_must_allow[0] &= (1 << (OP_CLOSE) |
+ 1 << (OP_OPEN_DOWNGRADE) |
+ 1 << (OP_LOCKU) |
+ 1 << (OP_DELEGRETURN));
+
+ exid->spo_must_allow[1] &= (
+ 1 << (OP_TEST_STATEID - 32) |
+ 1 << (OP_FREE_STATEID - 32));
if (!svc_rqst_integrity_protected(rqstp)) {
status = nfserr_inval;
goto out_nolock;
@@ -2424,7 +2419,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
status = nfserr_inval;
goto out;
}
- if (!mach_creds_match(conf, rqstp)) {
+ if (!nfsd4_mach_creds_match(conf, rqstp)) {
status = nfserr_wrong_cred;
goto out;
}
@@ -2473,6 +2468,8 @@ out_new:
goto out;
}
new->cl_minorversion = cstate->minorversion;
+ new->cl_spo_must_allow.u.words[0] = exid->spo_must_allow[0];
+ new->cl_spo_must_allow.u.words[1] = exid->spo_must_allow[1];
gen_clid(new, nn);
add_to_unconfirmed(new);
@@ -2676,7 +2673,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
if (conf) {
status = nfserr_wrong_cred;
- if (!mach_creds_match(conf, rqstp))
+ if (!nfsd4_mach_creds_match(conf, rqstp))
goto out_free_conn;
cs_slot = &conf->cl_cs_slot;
status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
@@ -2692,7 +2689,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
goto out_free_conn;
}
status = nfserr_wrong_cred;
- if (!mach_creds_match(unconf, rqstp))
+ if (!nfsd4_mach_creds_match(unconf, rqstp))
goto out_free_conn;
cs_slot = &unconf->cl_cs_slot;
status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
@@ -2801,7 +2798,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
if (!session)
goto out_no_session;
status = nfserr_wrong_cred;
- if (!mach_creds_match(session->se_client, rqstp))
+ if (!nfsd4_mach_creds_match(session->se_client, rqstp))
goto out;
status = nfsd4_map_bcts_dir(&bcts->dir);
if (status)
@@ -2848,7 +2845,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
if (!ses)
goto out_client_lock;
status = nfserr_wrong_cred;
- if (!mach_creds_match(ses->se_client, r))
+ if (!nfsd4_mach_creds_match(ses->se_client, r))
goto out_put_session;
status = mark_session_dead_locked(ses, 1 + ref_held_by_me);
if (status)
@@ -3087,7 +3084,7 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
status = nfserr_stale_clientid;
goto out;
}
- if (!mach_creds_match(clp, rqstp)) {
+ if (!nfsd4_mach_creds_match(clp, rqstp)) {
clp = NULL;
status = nfserr_wrong_cred;
goto out;
@@ -3112,7 +3109,7 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
* We don't take advantage of the rca_one_fs case.
* That's OK, it's optional, we can safely ignore it.
*/
- return nfs_ok;
+ return nfs_ok;
}
status = nfserr_complete_already;
@@ -4906,6 +4903,32 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return nfs_ok;
}
+static __be32
+nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
+{
+ struct nfs4_ol_stateid *stp = openlockstateid(s);
+ __be32 ret;
+
+ mutex_lock(&stp->st_mutex);
+
+ ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
+ if (ret)
+ goto out;
+
+ ret = nfserr_locks_held;
+ if (check_for_locks(stp->st_stid.sc_file,
+ lockowner(stp->st_stateowner)))
+ goto out;
+
+ release_lock_stateid(stp);
+ ret = nfs_ok;
+
+out:
+ mutex_unlock(&stp->st_mutex);
+ nfs4_put_stid(s);
+ return ret;
+}
+
__be32
nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_free_stateid *free_stateid)
@@ -4913,7 +4936,6 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
stateid_t *stateid = &free_stateid->fr_stateid;
struct nfs4_stid *s;
struct nfs4_delegation *dp;
- struct nfs4_ol_stateid *stp;
struct nfs4_client *cl = cstate->session->se_client;
__be32 ret = nfserr_bad_stateid;
@@ -4932,18 +4954,9 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
ret = nfserr_locks_held;
break;
case NFS4_LOCK_STID:
- ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
- if (ret)
- break;
- stp = openlockstateid(s);
- ret = nfserr_locks_held;
- if (check_for_locks(stp->st_stid.sc_file,
- lockowner(stp->st_stateowner)))
- break;
- WARN_ON(!unhash_lock_stateid(stp));
+ atomic_inc(&s->sc_count);
spin_unlock(&cl->cl_lock);
- nfs4_put_stid(s);
- ret = nfs_ok;
+ ret = nfsd4_free_lock_stateid(stateid, s);
goto out;
case NFS4_REVOKED_DELEG_STID:
dp = delegstateid(s);
@@ -5510,7 +5523,7 @@ static __be32
lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
struct nfs4_ol_stateid *ost,
struct nfsd4_lock *lock,
- struct nfs4_ol_stateid **lst, bool *new)
+ struct nfs4_ol_stateid **plst, bool *new)
{
__be32 status;
struct nfs4_file *fi = ost->st_stid.sc_file;
@@ -5518,7 +5531,9 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
struct nfs4_client *cl = oo->oo_owner.so_client;
struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
struct nfs4_lockowner *lo;
+ struct nfs4_ol_stateid *lst;
unsigned int strhashval;
+ bool hashed;
lo = find_lockowner_str(cl, &lock->lk_new_owner);
if (!lo) {
@@ -5534,12 +5549,27 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
goto out;
}
- *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
- if (*lst == NULL) {
+retry:
+ lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
+ if (lst == NULL) {
status = nfserr_jukebox;
goto out;
}
+
+ mutex_lock(&lst->st_mutex);
+
+ /* See if it's still hashed to avoid race with FREE_STATEID */
+ spin_lock(&cl->cl_lock);
+ hashed = !list_empty(&lst->st_perfile);
+ spin_unlock(&cl->cl_lock);
+
+ if (!hashed) {
+ mutex_unlock(&lst->st_mutex);
+ nfs4_put_stid(&lst->st_stid);
+ goto retry;
+ }
status = nfs_ok;
+ *plst = lst;
out:
nfs4_put_stateowner(&lo->lo_owner);
return status;
@@ -5606,8 +5636,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
goto out;
status = lookup_or_create_lock_state(cstate, open_stp, lock,
&lock_stp, &new);
- if (status == nfs_ok)
- mutex_lock(&lock_stp->st_mutex);
} else {
status = nfs4_preprocess_seqid_op(cstate,
lock->lk_old_lock_seqid,
@@ -5945,6 +5973,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
__be32 status;
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
struct nfs4_client *clp;
+ LIST_HEAD (reaplist);
dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
clid->cl_boot, clid->cl_id);
@@ -5975,9 +6004,23 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
nfs4_get_stateowner(sop);
break;
}
+ if (!lo) {
+ spin_unlock(&clp->cl_lock);
+ return status;
+ }
+
+ unhash_lockowner_locked(lo);
+ while (!list_empty(&lo->lo_owner.so_stateids)) {
+ stp = list_first_entry(&lo->lo_owner.so_stateids,
+ struct nfs4_ol_stateid,
+ st_perstateowner);
+ WARN_ON(!unhash_lock_stateid(stp));
+ put_ol_stateid_locked(stp, &reaplist);
+ }
spin_unlock(&clp->cl_lock);
- if (lo)
- release_lockowner(lo);
+ free_ol_stateid_reaplist(&reaplist);
+ nfs4_put_stateowner(&lo->lo_owner);
+
return status;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 9df898ba648f..0aa0236a1429 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1299,16 +1299,14 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
break;
case SP4_MACH_CRED:
/* spo_must_enforce */
- READ_BUF(4);
- dummy = be32_to_cpup(p++);
- READ_BUF(dummy * 4);
- p += dummy;
-
+ status = nfsd4_decode_bitmap(argp,
+ exid->spo_must_enforce);
+ if (status)
+ goto out;
/* spo_must_allow */
- READ_BUF(4);
- dummy = be32_to_cpup(p++);
- READ_BUF(dummy * 4);
- p += dummy;
+ status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
+ if (status)
+ goto out;
break;
case SP4_SSV:
/* ssp_ops */
@@ -2164,22 +2162,20 @@ nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
}
static inline __be32
-nfsd4_encode_layout_type(struct xdr_stream *xdr, enum pnfs_layouttype layout_type)
+nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types)
{
- __be32 *p;
+ __be32 *p;
+ unsigned long i = hweight_long(layout_types);
- if (layout_type) {
- p = xdr_reserve_space(xdr, 8);
- if (!p)
- return nfserr_resource;
- *p++ = cpu_to_be32(1);
- *p++ = cpu_to_be32(layout_type);
- } else {
- p = xdr_reserve_space(xdr, 4);
- if (!p)
- return nfserr_resource;
- *p++ = cpu_to_be32(0);
- }
+ p = xdr_reserve_space(xdr, 4 + 4 * i);
+ if (!p)
+ return nfserr_resource;
+
+ *p++ = cpu_to_be32(i);
+
+ for (i = LAYOUT_NFSV4_1_FILES; i < LAYOUT_TYPE_MAX; ++i)
+ if (layout_types & (1 << i))
+ *p++ = cpu_to_be32(i);
return 0;
}
@@ -2754,13 +2750,13 @@ out_acl:
}
#ifdef CONFIG_NFSD_PNFS
if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
- status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+ status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
if (status)
goto out;
}
if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
- status = nfsd4_encode_layout_type(xdr, exp->ex_layout_type);
+ status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
if (status)
goto out;
}
@@ -3867,14 +3863,6 @@ nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_w
return nfserr;
}
-static const u32 nfs4_minimal_spo_must_enforce[2] = {
- [1] = 1 << (OP_BIND_CONN_TO_SESSION - 32) |
- 1 << (OP_EXCHANGE_ID - 32) |
- 1 << (OP_CREATE_SESSION - 32) |
- 1 << (OP_DESTROY_SESSION - 32) |
- 1 << (OP_DESTROY_CLIENTID - 32)
-};
-
static __be32
nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
struct nfsd4_exchange_id *exid)
@@ -3885,6 +3873,7 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
char *server_scope;
int major_id_sz;
int server_scope_sz;
+ int status = 0;
uint64_t minor_id = 0;
if (nfserr)
@@ -3913,18 +3902,20 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
case SP4_NONE:
break;
case SP4_MACH_CRED:
- /* spo_must_enforce, spo_must_allow */
- p = xdr_reserve_space(xdr, 16);
- if (!p)
- return nfserr_resource;
-
/* spo_must_enforce bitmap: */
- *p++ = cpu_to_be32(2);
- *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[0]);
- *p++ = cpu_to_be32(nfs4_minimal_spo_must_enforce[1]);
- /* empty spo_must_allow bitmap: */
- *p++ = cpu_to_be32(0);
-
+ status = nfsd4_encode_bitmap(xdr,
+ exid->spo_must_enforce[0],
+ exid->spo_must_enforce[1],
+ exid->spo_must_enforce[2]);
+ if (status)
+ goto out;
+ /* spo_must_allow bitmap: */
+ status = nfsd4_encode_bitmap(xdr,
+ exid->spo_must_allow[0],
+ exid->spo_must_allow[1],
+ exid->spo_must_allow[2]);
+ if (status)
+ goto out;
break;
default:
WARN_ON_ONCE(1);
@@ -3951,6 +3942,8 @@ nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
/* Implementation id */
*p++ = cpu_to_be32(0); /* zero length nfs_impl_id4 array */
return 0;
+out:
+ return status;
}
static __be32
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index cf980523898b..9446849888d5 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -124,6 +124,7 @@ void nfs4_state_shutdown_net(struct net *net);
void nfs4_reset_lease(time_t leasetime);
int nfs4_reset_recoverydir(char *recdir);
char * nfs4_recoverydir(void);
+bool nfsd4_spo_must_allow(struct svc_rqst *rqstp);
#else
static inline int nfsd4_init_slabs(void) { return 0; }
static inline void nfsd4_free_slabs(void) { }
@@ -134,6 +135,10 @@ static inline void nfs4_state_shutdown_net(struct net *net) { }
static inline void nfs4_reset_lease(time_t leasetime) { }
static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
static inline char * nfs4_recoverydir(void) {return NULL; }
+static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp)
+{
+ return false;
+}
#endif
/*
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index a8919444c460..cfe7500d5847 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -59,14 +59,20 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
* the write call).
*/
static inline __be32
-nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, umode_t requested)
+nfsd_mode_check(struct svc_rqst *rqstp, struct dentry *dentry,
+ umode_t requested)
{
- mode &= S_IFMT;
+ umode_t mode = d_inode(dentry)->i_mode & S_IFMT;
if (requested == 0) /* the caller doesn't care */
return nfs_ok;
- if (mode == requested)
+ if (mode == requested) {
+ if (mode == S_IFDIR && !d_can_lookup(dentry)) {
+ WARN_ON_ONCE(1);
+ return nfserr_notdir;
+ }
return nfs_ok;
+ }
/*
* v4 has an error more specific than err_notdir which we should
* return in preference to err_notdir:
@@ -298,7 +304,7 @@ out:
* that it expects something not of the given type.
*
* @access is formed from the NFSD_MAY_* constants defined in
- * include/linux/nfsd/nfsd.h.
+ * fs/nfsd/vfs.h.
*/
__be32
fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
@@ -340,7 +346,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
if (error)
goto out;
- error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type);
+ error = nfsd_mode_check(rqstp, dentry, type);
if (error)
goto out;
@@ -533,7 +539,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
* the reference filehandle (if it is in the same export)
* or the export options.
*/
- set_version_and_fsid_type(fhp, exp, ref_fh);
+ set_version_and_fsid_type(fhp, exp, ref_fh);
if (ref_fh == fhp)
fh_put(ref_fh);
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 4cd78ef4c95c..e9214768cde9 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -251,9 +251,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
/* Check for NFSD_MAY_WRITE in nfsd_create if necessary */
- nfserr = nfserr_acces;
- if (!argp->len)
- goto done;
nfserr = nfserr_exist;
if (isdotent(argp->name, argp->len))
goto done;
@@ -362,8 +359,8 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
nfserr = 0;
if (!inode) {
/* File doesn't exist. Create it and set attrs */
- nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
- attr, type, rdev, newfhp);
+ nfserr = nfsd_create_locked(rqstp, dirfhp, argp->name,
+ argp->len, attr, type, rdev, newfhp);
} else if (type == S_IFREG) {
dprintk("nfsd: existing %s, valid=%x, size=%ld\n",
argp->name, attr->ia_valid, (long) attr->ia_size);
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 79d964aa8079..41b468a6a90f 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -240,7 +240,7 @@ nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
|| !(p = decode_filename(p, &args->name, &args->len)))
return 0;
- return xdr_argsize_check(rqstp, p);
+ return xdr_argsize_check(rqstp, p);
}
int
diff --git a/fs/nfsd/pnfs.h b/fs/nfsd/pnfs.h
index 7d073b9b1553..0c2a716e8741 100644
--- a/fs/nfsd/pnfs.h
+++ b/fs/nfsd/pnfs.h
@@ -21,6 +21,7 @@ struct nfsd4_layout_ops {
u32 notify_types;
__be32 (*proc_getdeviceinfo)(struct super_block *sb,
+ struct svc_rqst *rqstp,
struct nfs4_client *clp,
struct nfsd4_getdeviceinfo *gdevp);
__be32 (*encode_getdeviceinfo)(struct xdr_stream *xdr,
@@ -44,6 +45,9 @@ extern const struct nfsd4_layout_ops bl_layout_ops;
#ifdef CONFIG_NFSD_SCSILAYOUT
extern const struct nfsd4_layout_ops scsi_layout_ops;
#endif
+#ifdef CONFIG_NFSD_FLEXFILELAYOUT
+extern const struct nfsd4_layout_ops ff_layout_ops;
+#endif
__be32 nfsd4_preprocess_layout_stateid(struct svc_rqst *rqstp,
struct nfsd4_compound_state *cstate, stateid_t *stateid,
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 64053eadeb81..b95adf9a1595 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -345,6 +345,7 @@ struct nfs4_client {
u32 cl_exchange_flags;
/* number of rpc's in progress over an associated session: */
atomic_t cl_refcount;
+ struct nfs4_op_map cl_spo_must_allow;
/* for nfs41 callbacks */
/* We currently support a single back channel with a single slot */
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6fbd81ecb410..ff476e654b8f 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1135,96 +1135,37 @@ nfsd_check_ignore_resizing(struct iattr *iap)
iap->ia_valid &= ~ATTR_SIZE;
}
-/*
- * Create a file (regular, directory, device, fifo); UNIX sockets
- * not yet implemented.
- * If the response fh has been verified, the parent directory should
- * already be locked. Note that the parent directory is left locked.
- *
- * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
- */
+/* The parent directory should already be locked: */
__be32
-nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
char *fname, int flen, struct iattr *iap,
int type, dev_t rdev, struct svc_fh *resfhp)
{
- struct dentry *dentry, *dchild = NULL;
+ struct dentry *dentry, *dchild;
struct inode *dirp;
__be32 err;
__be32 err2;
int host_err;
- err = nfserr_perm;
- if (!flen)
- goto out;
- err = nfserr_exist;
- if (isdotent(fname, flen))
- goto out;
-
- err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
- if (err)
- goto out;
-
dentry = fhp->fh_dentry;
dirp = d_inode(dentry);
- err = nfserr_notdir;
- if (!dirp->i_op->lookup)
- goto out;
- /*
- * Check whether the response file handle has been verified yet.
- * If it has, the parent directory should already be locked.
- */
- if (!resfhp->fh_dentry) {
- host_err = fh_want_write(fhp);
- if (host_err)
- goto out_nfserr;
-
- /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
- fh_lock_nested(fhp, I_MUTEX_PARENT);
- dchild = lookup_one_len(fname, dentry, flen);
- host_err = PTR_ERR(dchild);
- if (IS_ERR(dchild))
- goto out_nfserr;
- err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
- if (err)
- goto out;
- } else {
- /* called from nfsd_proc_create */
- dchild = dget(resfhp->fh_dentry);
- if (!fhp->fh_locked) {
- /* not actually possible */
- printk(KERN_ERR
- "nfsd_create: parent %pd2 not locked!\n",
+ dchild = dget(resfhp->fh_dentry);
+ if (!fhp->fh_locked) {
+ WARN_ONCE(1, "nfsd_create: parent %pd2 not locked!\n",
dentry);
- err = nfserr_io;
- goto out;
- }
- }
- /*
- * Make sure the child dentry is still negative ...
- */
- err = nfserr_exist;
- if (d_really_is_positive(dchild)) {
- dprintk("nfsd_create: dentry %pd/%pd not negative!\n",
- dentry, dchild);
- goto out;
+ err = nfserr_io;
+ goto out;
}
+ err = nfsd_permission(rqstp, fhp->fh_export, dentry, NFSD_MAY_CREATE);
+ if (err)
+ goto out;
+
if (!(iap->ia_valid & ATTR_MODE))
iap->ia_mode = 0;
iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
- err = nfserr_inval;
- if (!S_ISREG(type) && !S_ISDIR(type) && !special_file(type)) {
- printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",
- type);
- goto out;
- }
-
- /*
- * Get the dir op function pointer.
- */
err = 0;
host_err = 0;
switch (type) {
@@ -1242,6 +1183,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
case S_IFSOCK:
host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
break;
+ default:
+ printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n",
+ type);
+ host_err = -EINVAL;
}
if (host_err < 0)
goto out_nfserr;
@@ -1251,7 +1196,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
/*
* nfsd_create_setattr already committed the child. Transactional
* filesystems had a chance to commit changes for both parent and
- * child * simultaneously making the following commit_metadata a
+ * child simultaneously making the following commit_metadata a
* noop.
*/
err2 = nfserrno(commit_metadata(fhp));
@@ -1263,8 +1208,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (!err)
err = fh_update(resfhp);
out:
- if (dchild && !IS_ERR(dchild))
- dput(dchild);
+ dput(dchild);
return err;
out_nfserr:
@@ -1272,6 +1216,53 @@ out_nfserr:
goto out;
}
+/*
+ * Create a filesystem object (regular, directory, special).
+ * Note that the parent directory is left locked.
+ *
+ * N.B. Every call to nfsd_create needs an fh_put for _both_ fhp and resfhp
+ */
+__be32
+nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ char *fname, int flen, struct iattr *iap,
+ int type, dev_t rdev, struct svc_fh *resfhp)
+{
+ struct dentry *dentry, *dchild = NULL;
+ struct inode *dirp;
+ __be32 err;
+ int host_err;
+
+ if (isdotent(fname, flen))
+ return nfserr_exist;
+
+ err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_NOP);
+ if (err)
+ return err;
+
+ dentry = fhp->fh_dentry;
+ dirp = d_inode(dentry);
+
+ host_err = fh_want_write(fhp);
+ if (host_err)
+ return nfserrno(host_err);
+
+ fh_lock_nested(fhp, I_MUTEX_PARENT);
+ dchild = lookup_one_len(fname, dentry, flen);
+ host_err = PTR_ERR(dchild);
+ if (IS_ERR(dchild))
+ return nfserrno(host_err);
+ err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
+ /*
+ * We unconditionally drop our ref to dchild as fh_compose will have
+ * already grabbed its own ref for it.
+ */
+ dput(dchild);
+ if (err)
+ return err;
+ return nfsd_create_locked(rqstp, fhp, fname, flen, iap, type,
+ rdev, resfhp);
+}
+
#ifdef CONFIG_NFSD_V3
/*
@@ -1304,12 +1295,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry;
dirp = d_inode(dentry);
- /* Get all the sanity checks out of the way before
- * we lock the parent. */
- err = nfserr_notdir;
- if (!dirp->i_op->lookup)
- goto out;
-
host_err = fh_want_write(fhp);
if (host_err)
goto out_nfserr;
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 2d573ec057f8..3cbb1b33777b 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -59,6 +59,9 @@ __be32 nfsd4_vfs_fallocate(struct svc_rqst *, struct svc_fh *,
__be32 nfsd4_clone_file_range(struct file *, u64, struct file *,
u64, u64);
#endif /* CONFIG_NFSD_V4 */
+__be32 nfsd_create_locked(struct svc_rqst *, struct svc_fh *,
+ char *name, int len, struct iattr *attrs,
+ int type, dev_t rdev, struct svc_fh *res);
__be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
char *name, int len, struct iattr *attrs,
int type, dev_t rdev, struct svc_fh *res);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index d9554813e58a..beea0c5edc51 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -59,6 +59,7 @@ struct nfsd4_compound_state {
struct nfsd4_session *session;
struct nfsd4_slot *slot;
int data_offset;
+ bool spo_must_allowed;
size_t iovlen;
u32 minorversion;
__be32 status;
@@ -403,6 +404,8 @@ struct nfsd4_exchange_id {
clientid_t clientid;
u32 seqid;
int spa_how;
+ u32 spo_must_enforce[3];
+ u32 spo_must_allow[3];
};
struct nfsd4_sequence {
@@ -654,6 +657,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
}
+
+bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp);
int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *,
struct nfsd4_compoundargs *);
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 12e064b8be9a..533bd524e41e 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -172,12 +172,10 @@ void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
{
struct hlist_head *bucket;
- struct qstr *q;
assert_spin_locked(&dlm->spinlock);
- q = &res->lockname;
- bucket = dlm_lockres_hash(dlm, q->hash);
+ bucket = dlm_lockres_hash(dlm, res->lockname.hash);
/* get a reference for our hashtable */
dlm_lockres_get(res);
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c
index 47b3b2d4e775..ef474cdd6404 100644
--- a/fs/ocfs2/dlmfs/dlmfs.c
+++ b/fs/ocfs2/dlmfs/dlmfs.c
@@ -469,7 +469,7 @@ static int dlmfs_mkdir(struct inode * dir,
{
int status;
struct inode *inode = NULL;
- struct qstr *domain = &dentry->d_name;
+ const struct qstr *domain = &dentry->d_name;
struct dlmfs_inode_private *ip;
struct ocfs2_cluster_connection *conn;
@@ -518,7 +518,7 @@ static int dlmfs_create(struct inode *dir,
{
int status = 0;
struct inode *inode;
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
mlog(0, "create %.*s\n", name->len, name->name);
diff --git a/fs/ocfs2/dlmfs/userdlm.c b/fs/ocfs2/dlmfs/userdlm.c
index 0499e3fb7bdb..f70cda2f090d 100644
--- a/fs/ocfs2/dlmfs/userdlm.c
+++ b/fs/ocfs2/dlmfs/userdlm.c
@@ -667,7 +667,7 @@ void user_dlm_set_locking_protocol(void)
ocfs2_stack_glue_set_max_proto_version(&user_dlm_lproto.lp_max_version);
}
-struct ocfs2_cluster_connection *user_dlm_register(struct qstr *name)
+struct ocfs2_cluster_connection *user_dlm_register(const struct qstr *name)
{
int rc;
struct ocfs2_cluster_connection *conn;
diff --git a/fs/ocfs2/dlmfs/userdlm.h b/fs/ocfs2/dlmfs/userdlm.h
index 3b42d79531d7..ede94a6e7fd3 100644
--- a/fs/ocfs2/dlmfs/userdlm.h
+++ b/fs/ocfs2/dlmfs/userdlm.h
@@ -83,7 +83,7 @@ void user_dlm_write_lvb(struct inode *inode,
ssize_t user_dlm_read_lvb(struct inode *inode,
char *val,
unsigned int len);
-struct ocfs2_cluster_connection *user_dlm_register(struct qstr *name);
+struct ocfs2_cluster_connection *user_dlm_register(const struct qstr *name);
void user_dlm_unregister(struct ocfs2_cluster_connection *conn);
void user_dlm_set_locking_protocol(void);
diff --git a/fs/open.c b/fs/open.c
index bf66cf1a9f5c..4fd6e256f4f4 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -998,6 +998,26 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
}
EXPORT_SYMBOL(file_open_root);
+struct file *filp_clone_open(struct file *oldfile)
+{
+ struct file *file;
+ int retval;
+
+ file = get_empty_filp();
+ if (IS_ERR(file))
+ return file;
+
+ file->f_flags = oldfile->f_flags;
+ retval = vfs_open(&oldfile->f_path, file, oldfile->f_cred);
+ if (retval) {
+ put_filp(file);
+ return ERR_PTR(retval);
+ }
+
+ return file;
+}
+EXPORT_SYMBOL(filp_clone_open);
+
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
diff --git a/fs/pipe.c b/fs/pipe.c
index 4b32928f5426..4ebe6b2e5217 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -144,10 +144,8 @@ static int anon_pipe_buf_steal(struct pipe_inode_info *pipe,
struct page *page = buf->page;
if (page_count(page) == 1) {
- if (memcg_kmem_enabled()) {
+ if (memcg_kmem_enabled())
memcg_kmem_uncharge(page, 0);
- __ClearPageKmemcg(page);
- }
__SetPageLocked(page);
return 0;
}
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 09e18fdf61e5..b9a8c813e5e6 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -46,7 +46,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
cached = 0;
for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
- pages[lru] = global_page_state(NR_LRU_BASE + lru);
+ pages[lru] = global_node_page_state(NR_LRU_BASE + lru);
available = si_mem_available();
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index b59db94d2ff4..1b93650dda2f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -474,7 +474,7 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
{
struct ctl_table_header *head = grab_header(dir);
struct ctl_table_header *h = NULL;
- struct qstr *name = &dentry->d_name;
+ const struct qstr *name = &dentry->d_name;
struct ctl_table *p;
struct inode *inode;
struct dentry *err = ERR_PTR(-ENOENT);
@@ -834,7 +834,7 @@ static int sysctl_is_seen(struct ctl_table_header *p)
return res;
}
-static int proc_sys_compare(const struct dentry *parent, const struct dentry *dentry,
+static int proc_sys_compare(const struct dentry *dentry,
unsigned int len, const char *str, const struct qstr *name)
{
struct ctl_table_header *head;
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 47516a794011..7a034d62cf8c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -486,30 +486,21 @@ static int ramoops_parse_dt(struct platform_device *pdev,
struct ramoops_platform_data *pdata)
{
struct device_node *of_node = pdev->dev.of_node;
- struct device_node *mem_region;
- struct resource res;
+ struct resource *res;
u32 value;
int ret;
dev_dbg(&pdev->dev, "using Device Tree\n");
- mem_region = of_parse_phandle(of_node, "memory-region", 0);
- if (!mem_region) {
- dev_err(&pdev->dev, "no memory-region phandle\n");
- return -ENODEV;
- }
-
- ret = of_address_to_resource(mem_region, 0, &res);
- of_node_put(mem_region);
- if (ret) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
dev_err(&pdev->dev,
- "failed to translate memory-region to resource: %d\n",
- ret);
- return ret;
+ "failed to locate DT /reserved-memory resource\n");
+ return -EINVAL;
}
- pdata->mem_size = resource_size(&res);
- pdata->mem_address = res.start;
+ pdata->mem_size = resource_size(res);
+ pdata->mem_address = res->start;
pdata->mem_type = of_property_read_bool(of_node, "unbuffered");
pdata->dump_oops = !of_property_read_bool(of_node, "no-dump-oops");
@@ -652,11 +643,11 @@ fail_buf:
kfree(cxt->pstore.buf);
fail_clear:
cxt->pstore.bufsize = 0;
- kfree(cxt->mprz);
+ persistent_ram_free(cxt->mprz);
fail_init_mprz:
- kfree(cxt->fprz);
+ persistent_ram_free(cxt->fprz);
fail_init_fprz:
- kfree(cxt->cprz);
+ persistent_ram_free(cxt->cprz);
fail_init_cprz:
ramoops_free_przs(cxt);
fail_out:
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 9718da86ad01..821b34816976 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -100,10 +100,6 @@ static int switch_gc_head(struct ubifs_info *c)
if (err)
return err;
- err = ubifs_wbuf_sync_nolock(wbuf);
- if (err)
- return err;
-
err = ubifs_add_bud_to_log(c, GCHD, gc_lnum, 0);
if (err)
return err;
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 70349954e78b..4ec051089186 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -520,19 +520,19 @@ static int init_constants_early(struct ubifs_info *c)
c->max_write_shift = fls(c->max_write_size) - 1;
if (c->leb_size < UBIFS_MIN_LEB_SZ) {
- ubifs_err(c, "too small LEBs (%d bytes), min. is %d bytes",
- c->leb_size, UBIFS_MIN_LEB_SZ);
+ ubifs_errc(c, "too small LEBs (%d bytes), min. is %d bytes",
+ c->leb_size, UBIFS_MIN_LEB_SZ);
return -EINVAL;
}
if (c->leb_cnt < UBIFS_MIN_LEB_CNT) {
- ubifs_err(c, "too few LEBs (%d), min. is %d",
- c->leb_cnt, UBIFS_MIN_LEB_CNT);
+ ubifs_errc(c, "too few LEBs (%d), min. is %d",
+ c->leb_cnt, UBIFS_MIN_LEB_CNT);
return -EINVAL;
}
if (!is_power_of_2(c->min_io_size)) {
- ubifs_err(c, "bad min. I/O size %d", c->min_io_size);
+ ubifs_errc(c, "bad min. I/O size %d", c->min_io_size);
return -EINVAL;
}
@@ -543,8 +543,8 @@ static int init_constants_early(struct ubifs_info *c)
if (c->max_write_size < c->min_io_size ||
c->max_write_size % c->min_io_size ||
!is_power_of_2(c->max_write_size)) {
- ubifs_err(c, "bad write buffer size %d for %d min. I/O unit",
- c->max_write_size, c->min_io_size);
+ ubifs_errc(c, "bad write buffer size %d for %d min. I/O unit",
+ c->max_write_size, c->min_io_size);
return -EINVAL;
}
@@ -2108,8 +2108,9 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
*/
ubi = open_ubi(name, UBI_READONLY);
if (IS_ERR(ubi)) {
- pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d",
- current->pid, name, (int)PTR_ERR(ubi));
+ if (!(flags & MS_SILENT))
+ pr_err("UBIFS error (pid: %d): cannot open \"%s\", error %d",
+ current->pid, name, (int)PTR_ERR(ubi));
return ERR_CAST(ubi);
}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index ddf9f6b9eee2..4617d459022a 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1783,8 +1783,8 @@ void ubifs_err(const struct ubifs_info *c, const char *fmt, ...);
__printf(2, 3)
void ubifs_warn(const struct ubifs_info *c, const char *fmt, ...);
/*
- * A variant of 'ubifs_err()' which takes the UBIFS file-sytem description
- * object as an argument.
+ * A conditional variant of 'ubifs_err()' which doesn't output anything
+ * if probing (ie. MS_SILENT set).
*/
#define ubifs_errc(c, fmt, ...) \
do { \
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index b5fc27969e9d..e237811f09ce 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -592,19 +592,19 @@ static int ubifs_xattr_set(const struct xattr_handler *handler,
return __ubifs_removexattr(inode, name);
}
-const struct xattr_handler ubifs_user_xattr_handler = {
+static const struct xattr_handler ubifs_user_xattr_handler = {
.prefix = XATTR_USER_PREFIX,
.get = ubifs_xattr_get,
.set = ubifs_xattr_set,
};
-const struct xattr_handler ubifs_trusted_xattr_handler = {
+static const struct xattr_handler ubifs_trusted_xattr_handler = {
.prefix = XATTR_TRUSTED_PREFIX,
.get = ubifs_xattr_get,
.set = ubifs_xattr_set,
};
-const struct xattr_handler ubifs_security_xattr_handler = {
+static const struct xattr_handler ubifs_security_xattr_handler = {
.prefix = XATTR_SECURITY_PREFIX,
.get = ubifs_xattr_get,
.set = ubifs_xattr_set,
diff --git a/fs/utimes.c b/fs/utimes.c
index 85c40f4f373d..794f5f5b1fb5 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -92,10 +92,11 @@ static int utimes_common(struct path *path, struct timespec *times)
* then we need to check permissions, because
* inode_change_ok() won't do it.
*/
- error = -EACCES;
+ error = -EPERM;
if (IS_IMMUTABLE(inode))
goto mnt_drop_write_and_out;
+ error = -EACCES;
if (!inode_owner_or_capable(inode)) {
error = inode_permission(inode, MAY_WRITE);
if (error)
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 3542d94fddce..fc593c869493 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \
xfs_btree.o \
xfs_da_btree.o \
xfs_da_format.o \
+ xfs_defer.o \
xfs_dir2.o \
xfs_dir2_block.o \
xfs_dir2_data.o \
@@ -51,6 +52,8 @@ xfs-y += $(addprefix libxfs/, \
xfs_inode_fork.o \
xfs_inode_buf.o \
xfs_log_rlimit.o \
+ xfs_rmap.o \
+ xfs_rmap_btree.o \
xfs_sb.o \
xfs_symlink_remote.o \
xfs_trans_resv.o \
@@ -100,11 +103,13 @@ xfs-y += xfs_log.o \
xfs_extfree_item.o \
xfs_icreate_item.o \
xfs_inode_item.o \
+ xfs_rmap_item.o \
xfs_log_recover.o \
xfs_trans_ail.o \
xfs_trans_buf.o \
xfs_trans_extfree.o \
xfs_trans_inode.o \
+ xfs_trans_rmap.o \
# optional features
xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \
@@ -121,5 +126,4 @@ xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
xfs-$(CONFIG_SYSCTL) += xfs_sysctl.o
xfs-$(CONFIG_COMPAT) += xfs_ioctl32.o
-xfs-$(CONFIG_NFSD_BLOCKLAYOUT) += xfs_pnfs.o
-xfs-$(CONFIG_NFSD_SCSILAYOUT) += xfs_pnfs.o
+xfs-$(CONFIG_EXPORTFS_BLOCK_OPS) += xfs_pnfs.o
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 88c26b827a2d..776ae2f325d1 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -24,8 +24,10 @@
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
+#include "xfs_rmap.h"
#include "xfs_alloc_btree.h"
#include "xfs_alloc.h"
#include "xfs_extent_busy.h"
@@ -49,6 +51,81 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *);
STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *,
xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *);
+xfs_extlen_t
+xfs_prealloc_blocks(
+ struct xfs_mount *mp)
+{
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return XFS_RMAP_BLOCK(mp) + 1;
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ return XFS_FIBT_BLOCK(mp) + 1;
+ return XFS_IBT_BLOCK(mp) + 1;
+}
+
+/*
+ * In order to avoid ENOSPC-related deadlock caused by out-of-order locking of
+ * AGF buffer (PV 947395), we place constraints on the relationship among
+ * actual allocations for data blocks, freelist blocks, and potential file data
+ * bmap btree blocks. However, these restrictions may result in no actual space
+ * allocated for a delayed extent, for example, a data block in a certain AG is
+ * allocated but there is no additional block for the additional bmap btree
+ * block due to a split of the bmap btree of the file. The result of this may
+ * lead to an infinite loop when the file gets flushed to disk and all delayed
+ * extents need to be actually allocated. To get around this, we explicitly set
+ * aside a few blocks which will not be reserved in delayed allocation.
+ *
+ * When rmap is disabled, we need to reserve 4 fsbs _per AG_ for the freelist
+ * and 4 more to handle a potential split of the file's bmap btree.
+ *
+ * When rmap is enabled, we must also be able to handle two rmap btree inserts
+ * to record both the file data extent and a new bmbt block. The bmbt block
+ * might not be in the same AG as the file data extent. In the worst case
+ * the bmap btree splits multiple levels and all the new blocks come from
+ * different AGs, so set aside enough to handle rmap btree splits in all AGs.
+ */
+unsigned int
+xfs_alloc_set_aside(
+ struct xfs_mount *mp)
+{
+ unsigned int blocks;
+
+ blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE);
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ blocks += mp->m_sb.sb_agcount * mp->m_rmap_maxlevels;
+ return blocks;
+}
+
+/*
+ * When deciding how much space to allocate out of an AG, we limit the
+ * allocation maximum size to the size the AG. However, we cannot use all the
+ * blocks in the AG - some are permanently used by metadata. These
+ * blocks are generally:
+ * - the AG superblock, AGF, AGI and AGFL
+ * - the AGF (bno and cnt) and AGI btree root blocks, and optionally
+ * the AGI free inode and rmap btree root blocks.
+ * - blocks on the AGFL according to xfs_alloc_set_aside() limits
+ * - the rmapbt root block
+ *
+ * The AG headers are sector sized, so the amount of space they take up is
+ * dependent on filesystem geometry. The others are all single blocks.
+ */
+unsigned int
+xfs_alloc_ag_max_usable(
+ struct xfs_mount *mp)
+{
+ unsigned int blocks;
+
+ blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */
+ blocks += XFS_ALLOC_AGFL_RESERVE;
+ blocks += 3; /* AGF, AGI btree root blocks */
+ if (xfs_sb_version_hasfinobt(&mp->m_sb))
+ blocks++; /* finobt root block */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ blocks++; /* rmap root block */
+
+ return mp->m_sb.sb_agblocks - blocks;
+}
+
/*
* Lookup the record equal to [bno, len] in the btree given by cur.
*/
@@ -636,6 +713,14 @@ xfs_alloc_ag_vextent(
ASSERT(!args->wasfromfl || !args->isfl);
ASSERT(args->agbno % args->alignment == 0);
+ /* if not file data, insert new block into the reverse map btree */
+ if (args->oinfo.oi_owner != XFS_RMAP_OWN_UNKNOWN) {
+ error = xfs_rmap_alloc(args->tp, args->agbp, args->agno,
+ args->agbno, args->len, &args->oinfo);
+ if (error)
+ return error;
+ }
+
if (!args->wasfromfl) {
error = xfs_alloc_update_counters(args->tp, args->pag,
args->agbp,
@@ -1577,14 +1662,15 @@ error0:
/*
* Free the extent starting at agno/bno for length.
*/
-STATIC int /* error */
+STATIC int
xfs_free_ag_extent(
- xfs_trans_t *tp, /* transaction pointer */
- xfs_buf_t *agbp, /* buffer for a.g. freelist header */
- xfs_agnumber_t agno, /* allocation group number */
- xfs_agblock_t bno, /* starting block number */
- xfs_extlen_t len, /* length of extent */
- int isfl) /* set if is freelist blocks - no sb acctg */
+ xfs_trans_t *tp,
+ xfs_buf_t *agbp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ struct xfs_owner_info *oinfo,
+ int isfl)
{
xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */
xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */
@@ -1601,12 +1687,19 @@ xfs_free_ag_extent(
xfs_extlen_t nlen; /* new length of freespace */
xfs_perag_t *pag; /* per allocation group data */
+ bno_cur = cnt_cur = NULL;
mp = tp->t_mountp;
+
+ if (oinfo->oi_owner != XFS_RMAP_OWN_UNKNOWN) {
+ error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo);
+ if (error)
+ goto error0;
+ }
+
/*
* Allocate and initialize a cursor for the by-block btree.
*/
bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO);
- cnt_cur = NULL;
/*
* Look for a neighboring block on the left (lower block numbers)
* that is contiguous with this space.
@@ -1875,6 +1968,11 @@ xfs_alloc_min_freelist(
/* space needed by-size freespace btree */
min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1,
mp->m_ag_maxlevels);
+ /* space needed reverse mapping used space btree */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ min_free += min_t(unsigned int,
+ pag->pagf_levels[XFS_BTNUM_RMAPi] + 1,
+ mp->m_rmap_maxlevels);
return min_free;
}
@@ -1992,21 +2090,34 @@ xfs_alloc_fix_freelist(
* anything other than extra overhead when we need to put more blocks
* back on the free list? Maybe we should only do this when space is
* getting low or the AGFL is more than half full?
+ *
+ * The NOSHRINK flag prevents the AGFL from being shrunk if it's too
+ * big; the NORMAP flag prevents AGFL expand/shrink operations from
+ * updating the rmapbt. Both flags are used in xfs_repair while we're
+ * rebuilding the rmapbt, and neither are used by the kernel. They're
+ * both required to ensure that rmaps are correctly recorded for the
+ * regenerated AGFL, bnobt, and cntbt. See repair/phase5.c and
+ * repair/rmap.c in xfsprogs for details.
*/
- while (pag->pagf_flcount > need) {
+ memset(&targs, 0, sizeof(targs));
+ if (flags & XFS_ALLOC_FLAG_NORMAP)
+ xfs_rmap_skip_owner_update(&targs.oinfo);
+ else
+ xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
+ while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
struct xfs_buf *bp;
error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
if (error)
goto out_agbp_relse;
- error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1);
+ error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1,
+ &targs.oinfo, 1);
if (error)
goto out_agbp_relse;
bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0);
xfs_trans_binval(tp, bp);
}
- memset(&targs, 0, sizeof(targs));
targs.tp = tp;
targs.mp = mp;
targs.agbp = agbp;
@@ -2271,6 +2382,10 @@ xfs_agf_verify(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS)
return false;
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb) &&
+ be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS)
+ return false;
+
/*
* during growfs operations, the perag is not fully initialised,
* so we can't use it for any useful checking. growfs ensures we can't
@@ -2402,6 +2517,8 @@ xfs_alloc_read_agf(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]);
pag->pagf_levels[XFS_BTNUM_CNTi] =
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]);
+ pag->pagf_levels[XFS_BTNUM_RMAPi] =
+ be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]);
spin_lock_init(&pag->pagb_lock);
pag->pagb_count = 0;
pag->pagb_tree = RB_ROOT;
@@ -2691,7 +2808,8 @@ int /* error */
xfs_free_extent(
struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t bno, /* starting block number of extent */
- xfs_extlen_t len) /* length of extent */
+ xfs_extlen_t len, /* length of extent */
+ struct xfs_owner_info *oinfo) /* extent owner */
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_buf *agbp;
@@ -2701,6 +2819,11 @@ xfs_free_extent(
ASSERT(len != 0);
+ if (XFS_TEST_ERROR(false, mp,
+ XFS_ERRTAG_FREE_EXTENT,
+ XFS_RANDOM_FREE_EXTENT))
+ return -EIO;
+
error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
if (error)
return error;
@@ -2712,7 +2835,7 @@ xfs_free_extent(
agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
err);
- error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0);
+ error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0);
if (error)
goto err;
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index cf268b2d0b6c..6fe2d6b7cfe9 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -54,41 +54,8 @@ typedef unsigned int xfs_alloctype_t;
*/
#define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */
#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/
-
-/*
- * In order to avoid ENOSPC-related deadlock caused by
- * out-of-order locking of AGF buffer (PV 947395), we place
- * constraints on the relationship among actual allocations for
- * data blocks, freelist blocks, and potential file data bmap
- * btree blocks. However, these restrictions may result in no
- * actual space allocated for a delayed extent, for example, a data
- * block in a certain AG is allocated but there is no additional
- * block for the additional bmap btree block due to a split of the
- * bmap btree of the file. The result of this may lead to an
- * infinite loop in xfssyncd when the file gets flushed to disk and
- * all delayed extents need to be actually allocated. To get around
- * this, we explicitly set aside a few blocks which will not be
- * reserved in delayed allocation. Considering the minimum number of
- * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap
- * btree requires 1 fsb, so we set the number of set-aside blocks
- * to 4 + 4*agcount.
- */
-#define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4))
-
-/*
- * When deciding how much space to allocate out of an AG, we limit the
- * allocation maximum size to the size the AG. However, we cannot use all the
- * blocks in the AG - some are permanently used by metadata. These
- * blocks are generally:
- * - the AG superblock, AGF, AGI and AGFL
- * - the AGF (bno and cnt) and AGI btree root blocks
- * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits
- *
- * The AG headers are sector sized, so the amount of space they take up is
- * dependent on filesystem geometry. The others are all single blocks.
- */
-#define XFS_ALLOC_AG_MAX_USABLE(mp) \
- ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7)
+#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */
+#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */
/*
@@ -123,6 +90,7 @@ typedef struct xfs_alloc_arg {
char isfl; /* set if is freelist blocks - !acctg */
char userdata; /* mask defining userdata treatment */
xfs_fsblock_t firstblock; /* io first block allocated */
+ struct xfs_owner_info oinfo; /* owner of blocks being allocated */
} xfs_alloc_arg_t;
/*
@@ -132,6 +100,11 @@ typedef struct xfs_alloc_arg {
#define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */
#define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */
+/* freespace limit calculations */
+#define XFS_ALLOC_AGFL_RESERVE 4
+unsigned int xfs_alloc_set_aside(struct xfs_mount *mp);
+unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp);
+
xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp,
struct xfs_perag *pag, xfs_extlen_t need);
unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp,
@@ -208,9 +181,10 @@ xfs_alloc_vextent(
*/
int /* error */
xfs_free_extent(
- struct xfs_trans *tp, /* transaction pointer */
- xfs_fsblock_t bno, /* starting block number of extent */
- xfs_extlen_t len); /* length of extent */
+ struct xfs_trans *tp, /* transaction pointer */
+ xfs_fsblock_t bno, /* starting block number of extent */
+ xfs_extlen_t len, /* length of extent */
+ struct xfs_owner_info *oinfo);/* extent owner */
int /* error */
xfs_alloc_lookup_ge(
@@ -232,4 +206,6 @@ int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
struct xfs_buf **agbp);
+xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp);
+
#endif /* __XFS_ALLOC_H__ */
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index d9b42425291e..5ba2dac5e67c 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -212,17 +212,6 @@ xfs_allocbt_init_key_from_rec(
}
STATIC void
-xfs_allocbt_init_rec_from_key(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
-{
- ASSERT(key->alloc.ar_startblock != 0);
-
- rec->alloc.ar_startblock = key->alloc.ar_startblock;
- rec->alloc.ar_blockcount = key->alloc.ar_blockcount;
-}
-
-STATIC void
xfs_allocbt_init_rec_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_rec *rec)
@@ -406,7 +395,6 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
.get_minrecs = xfs_allocbt_get_minrecs,
.get_maxrecs = xfs_allocbt_get_maxrecs,
.init_key_from_rec = xfs_allocbt_init_key_from_rec,
- .init_rec_from_key = xfs_allocbt_init_rec_from_key,
.init_rec_from_cur = xfs_allocbt_init_rec_from_cur,
.init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur,
.key_diff = xfs_allocbt_key_diff,
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 4e126f41a0aa..af1ecb19121e 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_attr_sf.h"
@@ -203,7 +204,7 @@ xfs_attr_set(
{
struct xfs_mount *mp = dp->i_mount;
struct xfs_da_args args;
- struct xfs_bmap_free flist;
+ struct xfs_defer_ops dfops;
struct xfs_trans_res tres;
xfs_fsblock_t firstblock;
int rsvd = (flags & ATTR_ROOT) != 0;
@@ -221,7 +222,7 @@ xfs_attr_set(
args.value = value;
args.valuelen = valuelen;
args.firstblock = &firstblock;
- args.flist = &flist;
+ args.dfops = &dfops;
args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
args.total = xfs_attr_calc_size(&args, &local);
@@ -316,13 +317,13 @@ xfs_attr_set(
* It won't fit in the shortform, transform to a leaf block.
* GROT: another possible req'mt for a double-split btree op.
*/
- xfs_bmap_init(args.flist, args.firstblock);
+ xfs_defer_init(args.dfops, args.firstblock);
error = xfs_attr_shortform_to_leaf(&args);
if (!error)
- error = xfs_bmap_finish(&args.trans, args.flist, dp);
+ error = xfs_defer_finish(&args.trans, args.dfops, dp);
if (error) {
args.trans = NULL;
- xfs_bmap_cancel(&flist);
+ xfs_defer_cancel(&dfops);
goto out;
}
@@ -382,7 +383,7 @@ xfs_attr_remove(
{
struct xfs_mount *mp = dp->i_mount;
struct xfs_da_args args;
- struct xfs_bmap_free flist;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t firstblock;
int error;
@@ -399,7 +400,7 @@ xfs_attr_remove(
return error;
args.firstblock = &firstblock;
- args.flist = &flist;
+ args.dfops = &dfops;
/*
* we have no control over the attribute names that userspace passes us
@@ -584,13 +585,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
* Commit that transaction so that the node_addname() call
* can manage its own transactions.
*/
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_attr3_leaf_to_node(args);
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist, dp);
+ error = xfs_defer_finish(&args->trans, args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
return error;
}
@@ -674,15 +675,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
* If the result is small enough, shrink it all into the inode.
*/
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error)
- error = xfs_bmap_finish(&args->trans,
- args->flist, dp);
+ error = xfs_defer_finish(&args->trans,
+ args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
return error;
}
}
@@ -737,14 +738,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
* If the result is small enough, shrink it all into the inode.
*/
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist, dp);
+ error = xfs_defer_finish(&args->trans, args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
return error;
}
}
@@ -863,14 +864,14 @@ restart:
*/
xfs_da_state_free(state);
state = NULL;
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_attr3_leaf_to_node(args);
if (!error)
- error = xfs_bmap_finish(&args->trans,
- args->flist, dp);
+ error = xfs_defer_finish(&args->trans,
+ args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
goto out;
}
@@ -891,13 +892,13 @@ restart:
* in the index/blkno/rmtblkno/rmtblkcnt fields and
* in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
*/
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_da3_split(state);
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist, dp);
+ error = xfs_defer_finish(&args->trans, args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
goto out;
}
} else {
@@ -990,14 +991,14 @@ restart:
* Check to see if the tree needs to be collapsed.
*/
if (retval && (state->path.active > 1)) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_da3_join(state);
if (!error)
- error = xfs_bmap_finish(&args->trans,
- args->flist, dp);
+ error = xfs_defer_finish(&args->trans,
+ args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
goto out;
}
}
@@ -1113,13 +1114,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)
* Check to see if the tree needs to be collapsed.
*/
if (retval && (state->path.active > 1)) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_da3_join(state);
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist, dp);
+ error = xfs_defer_finish(&args->trans, args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
goto out;
}
/*
@@ -1146,15 +1147,15 @@ xfs_attr_node_removename(xfs_da_args_t *args)
goto out;
if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
/* bp is gone due to xfs_da_shrink_inode */
if (!error)
- error = xfs_bmap_finish(&args->trans,
- args->flist, dp);
+ error = xfs_defer_finish(&args->trans,
+ args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
goto out;
}
} else
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 01a5ecfedfcf..8ea91f363093 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -792,7 +792,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)
nargs.dp = dp;
nargs.geo = args->geo;
nargs.firstblock = args->firstblock;
- nargs.flist = args->flist;
+ nargs.dfops = args->dfops;
nargs.total = args->total;
nargs.whichfork = XFS_ATTR_FORK;
nargs.trans = args->trans;
@@ -922,7 +922,7 @@ xfs_attr3_leaf_to_shortform(
nargs.geo = args->geo;
nargs.dp = dp;
nargs.firstblock = args->firstblock;
- nargs.flist = args->flist;
+ nargs.dfops = args->dfops;
nargs.total = args->total;
nargs.whichfork = XFS_ATTR_FORK;
nargs.trans = args->trans;
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index a572532a55cd..d52f525f5b2d 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -24,6 +24,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_inode.h"
@@ -460,16 +461,16 @@ xfs_attr_rmtval_set(
* extent and then crash then the block may not contain the
* correct metadata after log recovery occurs.
*/
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock,
- args->total, &map, &nmap, args->flist);
+ args->total, &map, &nmap, args->dfops);
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist, dp);
+ error = xfs_defer_finish(&args->trans, args->dfops, dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
return error;
}
@@ -503,7 +504,7 @@ xfs_attr_rmtval_set(
ASSERT(blkcnt > 0);
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
nmap = 1;
error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
blkcnt, &map, &nmap,
@@ -603,16 +604,16 @@ xfs_attr_rmtval_remove(
blkcnt = args->rmtblkcnt;
done = 0;
while (!done) {
- xfs_bmap_init(args->flist, args->firstblock);
+ xfs_defer_init(args->dfops, args->firstblock);
error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
XFS_BMAPI_ATTRFORK, 1, args->firstblock,
- args->flist, &done);
+ args->dfops, &done);
if (!error)
- error = xfs_bmap_finish(&args->trans, args->flist,
+ error = xfs_defer_finish(&args->trans, args->dfops,
args->dp);
if (error) {
args->trans = NULL;
- xfs_bmap_cancel(args->flist);
+ xfs_defer_cancel(args->dfops);
return error;
}
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 2f2c85cc8117..b060bca93402 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -24,6 +24,7 @@
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_dir2.h"
@@ -45,6 +46,7 @@
#include "xfs_symlink.h"
#include "xfs_attr_leaf.h"
#include "xfs_filestream.h"
+#include "xfs_rmap.h"
kmem_zone_t *xfs_bmap_free_item_zone;
@@ -570,12 +572,13 @@ xfs_bmap_validate_ret(
*/
void
xfs_bmap_add_free(
- struct xfs_mount *mp, /* mount point structure */
- struct xfs_bmap_free *flist, /* list of extents */
- xfs_fsblock_t bno, /* fs block number of extent */
- xfs_filblks_t len) /* length of extent */
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ xfs_fsblock_t bno,
+ xfs_filblks_t len,
+ struct xfs_owner_info *oinfo)
{
- struct xfs_bmap_free_item *new; /* new element */
+ struct xfs_extent_free_item *new; /* new element */
#ifdef DEBUG
xfs_agnumber_t agno;
xfs_agblock_t agbno;
@@ -592,44 +595,17 @@ xfs_bmap_add_free(
ASSERT(agbno + len <= mp->m_sb.sb_agblocks);
#endif
ASSERT(xfs_bmap_free_item_zone != NULL);
- new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
- new->xbfi_startblock = bno;
- new->xbfi_blockcount = (xfs_extlen_t)len;
- list_add(&new->xbfi_list, &flist->xbf_flist);
- flist->xbf_count++;
-}
-
-/*
- * Remove the entry "free" from the free item list. Prev points to the
- * previous entry, unless "free" is the head of the list.
- */
-void
-xfs_bmap_del_free(
- struct xfs_bmap_free *flist, /* free item list header */
- struct xfs_bmap_free_item *free) /* list item to be freed */
-{
- list_del(&free->xbfi_list);
- flist->xbf_count--;
- kmem_zone_free(xfs_bmap_free_item_zone, free);
-}
-
-/*
- * Free up any items left in the list.
- */
-void
-xfs_bmap_cancel(
- struct xfs_bmap_free *flist) /* list of bmap_free_items */
-{
- struct xfs_bmap_free_item *free; /* free list item */
- if (flist->xbf_count == 0)
- return;
- while (!list_empty(&flist->xbf_flist)) {
- free = list_first_entry(&flist->xbf_flist,
- struct xfs_bmap_free_item, xbfi_list);
- xfs_bmap_del_free(flist, free);
- }
- ASSERT(flist->xbf_count == 0);
+ new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP);
+ new->xefi_startblock = bno;
+ new->xefi_blockcount = (xfs_extlen_t)len;
+ if (oinfo)
+ new->xefi_oinfo = *oinfo;
+ else
+ xfs_rmap_skip_owner_update(&new->xefi_oinfo);
+ trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
+ XFS_FSB_TO_AGBNO(mp, bno), len);
+ xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
}
/*
@@ -659,6 +635,7 @@ xfs_bmap_btree_to_extents(
xfs_mount_t *mp; /* mount point structure */
__be64 *pp; /* ptr to block address */
struct xfs_btree_block *rblock;/* root btree block */
+ struct xfs_owner_info oinfo;
mp = ip->i_mount;
ifp = XFS_IFORK_PTR(ip, whichfork);
@@ -682,7 +659,8 @@ xfs_bmap_btree_to_extents(
cblock = XFS_BUF_TO_BLOCK(cbp);
if ((error = xfs_btree_check_block(cur, cblock, 0, cbp)))
return error;
- xfs_bmap_add_free(mp, cur->bc_private.b.flist, cbno, 1);
+ xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
+ xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1, &oinfo);
ip->i_d.di_nblocks--;
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
xfs_trans_binval(tp, cbp);
@@ -705,7 +683,7 @@ xfs_bmap_extents_to_btree(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode pointer */
xfs_fsblock_t *firstblock, /* first-block-allocated */
- xfs_bmap_free_t *flist, /* blocks freed in xaction */
+ struct xfs_defer_ops *dfops, /* blocks freed in xaction */
xfs_btree_cur_t **curp, /* cursor returned to caller */
int wasdel, /* converting a delayed alloc */
int *logflagsp, /* inode logging flags */
@@ -754,7 +732,7 @@ xfs_bmap_extents_to_btree(
*/
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstblock;
- cur->bc_private.b.flist = flist;
+ cur->bc_private.b.dfops = dfops;
cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
/*
* Convert to a btree with two levels, one record in root.
@@ -763,11 +741,12 @@ xfs_bmap_extents_to_btree(
memset(&args, 0, sizeof(args));
args.tp = tp;
args.mp = mp;
+ xfs_rmap_ino_bmbt_owner(&args.oinfo, ip->i_ino, whichfork);
args.firstblock = *firstblock;
if (*firstblock == NULLFSBLOCK) {
args.type = XFS_ALLOCTYPE_START_BNO;
args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
- } else if (flist->xbf_low) {
+ } else if (dfops->dop_low) {
args.type = XFS_ALLOCTYPE_START_BNO;
args.fsbno = *firstblock;
} else {
@@ -788,7 +767,7 @@ xfs_bmap_extents_to_btree(
ASSERT(args.fsbno != NULLFSBLOCK);
ASSERT(*firstblock == NULLFSBLOCK ||
args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) ||
- (flist->xbf_low &&
+ (dfops->dop_low &&
args.agno > XFS_FSB_TO_AGNO(mp, *firstblock)));
*firstblock = cur->bc_private.b.firstblock = args.fsbno;
cur->bc_private.b.allocated++;
@@ -909,6 +888,7 @@ xfs_bmap_local_to_extents(
memset(&args, 0, sizeof(args));
args.tp = tp;
args.mp = ip->i_mount;
+ xfs_rmap_ino_owner(&args.oinfo, ip->i_ino, whichfork, 0);
args.firstblock = *firstblock;
/*
* Allocate a block. We know we need only one, since the
@@ -973,7 +953,7 @@ xfs_bmap_add_attrfork_btree(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode pointer */
xfs_fsblock_t *firstblock, /* first block allocated */
- xfs_bmap_free_t *flist, /* blocks to free at commit */
+ struct xfs_defer_ops *dfops, /* blocks to free at commit */
int *flags) /* inode logging flags */
{
xfs_btree_cur_t *cur; /* btree cursor */
@@ -986,7 +966,7 @@ xfs_bmap_add_attrfork_btree(
*flags |= XFS_ILOG_DBROOT;
else {
cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
- cur->bc_private.b.flist = flist;
+ cur->bc_private.b.dfops = dfops;
cur->bc_private.b.firstblock = *firstblock;
if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
goto error0;
@@ -1016,7 +996,7 @@ xfs_bmap_add_attrfork_extents(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode pointer */
xfs_fsblock_t *firstblock, /* first block allocated */
- xfs_bmap_free_t *flist, /* blocks to free at commit */
+ struct xfs_defer_ops *dfops, /* blocks to free at commit */
int *flags) /* inode logging flags */
{
xfs_btree_cur_t *cur; /* bmap btree cursor */
@@ -1025,7 +1005,7 @@ xfs_bmap_add_attrfork_extents(
if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip))
return 0;
cur = NULL;
- error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0,
+ error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0,
flags, XFS_DATA_FORK);
if (cur) {
cur->bc_private.b.allocated = 0;
@@ -1051,7 +1031,7 @@ xfs_bmap_add_attrfork_local(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *ip, /* incore inode pointer */
xfs_fsblock_t *firstblock, /* first block allocated */
- xfs_bmap_free_t *flist, /* blocks to free at commit */
+ struct xfs_defer_ops *dfops, /* blocks to free at commit */
int *flags) /* inode logging flags */
{
xfs_da_args_t dargs; /* args for dir/attr code */
@@ -1064,7 +1044,7 @@ xfs_bmap_add_attrfork_local(
dargs.geo = ip->i_mount->m_dir_geo;
dargs.dp = ip;
dargs.firstblock = firstblock;
- dargs.flist = flist;
+ dargs.dfops = dfops;
dargs.total = dargs.geo->fsbcount;
dargs.whichfork = XFS_DATA_FORK;
dargs.trans = tp;
@@ -1092,7 +1072,7 @@ xfs_bmap_add_attrfork(
int rsvd) /* xact may use reserved blks */
{
xfs_fsblock_t firstblock; /* 1st block/ag allocated */
- xfs_bmap_free_t flist; /* freed extent records */
+ struct xfs_defer_ops dfops; /* freed extent records */
xfs_mount_t *mp; /* mount structure */
xfs_trans_t *tp; /* transaction pointer */
int blks; /* space reservation */
@@ -1158,18 +1138,18 @@ xfs_bmap_add_attrfork(
ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
ip->i_afp->if_flags = XFS_IFEXTENTS;
logflags = 0;
- xfs_bmap_init(&flist, &firstblock);
+ xfs_defer_init(&dfops, &firstblock);
switch (ip->i_d.di_format) {
case XFS_DINODE_FMT_LOCAL:
- error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist,
+ error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &dfops,
&logflags);
break;
case XFS_DINODE_FMT_EXTENTS:
error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock,
- &flist, &logflags);
+ &dfops, &logflags);
break;
case XFS_DINODE_FMT_BTREE:
- error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist,
+ error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &dfops,
&logflags);
break;
default:
@@ -1198,7 +1178,7 @@ xfs_bmap_add_attrfork(
xfs_log_sb(tp);
}
- error = xfs_bmap_finish(&tp, &flist, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto bmap_cancel;
error = xfs_trans_commit(tp);
@@ -1206,7 +1186,7 @@ xfs_bmap_add_attrfork(
return error;
bmap_cancel:
- xfs_bmap_cancel(&flist);
+ xfs_defer_cancel(&dfops);
trans_cancel:
xfs_trans_cancel(tp);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -2003,7 +1983,7 @@ xfs_bmap_add_extent_delay_real(
if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
- bma->firstblock, bma->flist,
+ bma->firstblock, bma->dfops,
&bma->cur, 1, &tmp_rval, whichfork);
rval |= tmp_rval;
if (error)
@@ -2087,7 +2067,7 @@ xfs_bmap_add_extent_delay_real(
if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
- bma->firstblock, bma->flist, &bma->cur, 1,
+ bma->firstblock, bma->dfops, &bma->cur, 1,
&tmp_rval, whichfork);
rval |= tmp_rval;
if (error)
@@ -2156,7 +2136,7 @@ xfs_bmap_add_extent_delay_real(
if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
- bma->firstblock, bma->flist, &bma->cur,
+ bma->firstblock, bma->dfops, &bma->cur,
1, &tmp_rval, whichfork);
rval |= tmp_rval;
if (error)
@@ -2199,13 +2179,18 @@ xfs_bmap_add_extent_delay_real(
ASSERT(0);
}
+ /* add reverse mapping */
+ error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new);
+ if (error)
+ goto done;
+
/* convert to a btree if necessary */
if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
int tmp_logflags; /* partial log flag return val */
ASSERT(bma->cur == NULL);
error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
- bma->firstblock, bma->flist, &bma->cur,
+ bma->firstblock, bma->dfops, &bma->cur,
da_old > 0, &tmp_logflags, whichfork);
bma->logflags |= tmp_logflags;
if (error)
@@ -2247,7 +2232,7 @@ xfs_bmap_add_extent_unwritten_real(
xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
xfs_bmbt_irec_t *new, /* new data to add to file extents */
xfs_fsblock_t *first, /* pointer to firstblock variable */
- xfs_bmap_free_t *flist, /* list of extents to be freed */
+ struct xfs_defer_ops *dfops, /* list of extents to be freed */
int *logflagsp) /* inode logging flags */
{
xfs_btree_cur_t *cur; /* btree cursor */
@@ -2735,12 +2720,17 @@ xfs_bmap_add_extent_unwritten_real(
ASSERT(0);
}
+ /* update reverse mappings */
+ error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new);
+ if (error)
+ goto done;
+
/* convert to a btree if necessary */
if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) {
int tmp_logflags; /* partial log flag return val */
ASSERT(cur == NULL);
- error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur,
+ error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur,
0, &tmp_logflags, XFS_DATA_FORK);
*logflagsp |= tmp_logflags;
if (error)
@@ -3127,13 +3117,18 @@ xfs_bmap_add_extent_hole_real(
break;
}
+ /* add reverse mapping */
+ error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new);
+ if (error)
+ goto done;
+
/* convert to a btree if necessary */
if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
int tmp_logflags; /* partial log flag return val */
ASSERT(bma->cur == NULL);
error = xfs_bmap_extents_to_btree(bma->tp, bma->ip,
- bma->firstblock, bma->flist, &bma->cur,
+ bma->firstblock, bma->dfops, &bma->cur,
0, &tmp_logflags, whichfork);
bma->logflags |= tmp_logflags;
if (error)
@@ -3691,9 +3686,10 @@ xfs_bmap_btalloc(
args.tp = ap->tp;
args.mp = mp;
args.fsbno = ap->blkno;
+ xfs_rmap_skip_owner_update(&args.oinfo);
/* Trim the allocation back to the maximum an AG can fit. */
- args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp));
+ args.maxlen = MIN(ap->length, mp->m_ag_max_usable);
args.firstblock = *ap->firstblock;
blen = 0;
if (nullfb) {
@@ -3708,7 +3704,7 @@ xfs_bmap_btalloc(
error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
if (error)
return error;
- } else if (ap->flist->xbf_low) {
+ } else if (ap->dfops->dop_low) {
if (xfs_inode_is_filestream(ap->ip))
args.type = XFS_ALLOCTYPE_FIRST_AG;
else
@@ -3741,7 +3737,7 @@ xfs_bmap_btalloc(
* is >= the stripe unit and the allocation offset is
* at the end of file.
*/
- if (!ap->flist->xbf_low && ap->aeof) {
+ if (!ap->dfops->dop_low && ap->aeof) {
if (!ap->offset) {
args.alignment = stripe_align;
atype = args.type;
@@ -3834,7 +3830,7 @@ xfs_bmap_btalloc(
args.minleft = 0;
if ((error = xfs_alloc_vextent(&args)))
return error;
- ap->flist->xbf_low = 1;
+ ap->dfops->dop_low = true;
}
if (args.fsbno != NULLFSBLOCK) {
/*
@@ -3844,7 +3840,7 @@ xfs_bmap_btalloc(
ASSERT(*ap->firstblock == NULLFSBLOCK ||
XFS_FSB_TO_AGNO(mp, *ap->firstblock) ==
XFS_FSB_TO_AGNO(mp, args.fsbno) ||
- (ap->flist->xbf_low &&
+ (ap->dfops->dop_low &&
XFS_FSB_TO_AGNO(mp, *ap->firstblock) <
XFS_FSB_TO_AGNO(mp, args.fsbno)));
@@ -3852,7 +3848,7 @@ xfs_bmap_btalloc(
if (*ap->firstblock == NULLFSBLOCK)
*ap->firstblock = args.fsbno;
ASSERT(nullfb || fb_agno == args.agno ||
- (ap->flist->xbf_low && fb_agno < args.agno));
+ (ap->dfops->dop_low && fb_agno < args.agno));
ap->length = args.len;
ap->ip->i_d.di_nblocks += args.len;
xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
@@ -4319,7 +4315,7 @@ xfs_bmapi_allocate(
if (error)
return error;
- if (bma->flist->xbf_low)
+ if (bma->dfops->dop_low)
bma->minleft = 0;
if (bma->cur)
bma->cur->bc_private.b.firstblock = *bma->firstblock;
@@ -4328,7 +4324,7 @@ xfs_bmapi_allocate(
if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) {
bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
bma->cur->bc_private.b.firstblock = *bma->firstblock;
- bma->cur->bc_private.b.flist = bma->flist;
+ bma->cur->bc_private.b.dfops = bma->dfops;
}
/*
* Bump the number of extents we've allocated
@@ -4409,7 +4405,7 @@ xfs_bmapi_convert_unwritten(
bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp,
bma->ip, whichfork);
bma->cur->bc_private.b.firstblock = *bma->firstblock;
- bma->cur->bc_private.b.flist = bma->flist;
+ bma->cur->bc_private.b.dfops = bma->dfops;
}
mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
? XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
@@ -4426,7 +4422,7 @@ xfs_bmapi_convert_unwritten(
}
error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx,
- &bma->cur, mval, bma->firstblock, bma->flist,
+ &bma->cur, mval, bma->firstblock, bma->dfops,
&tmp_logflags);
/*
* Log the inode core unconditionally in the unwritten extent conversion
@@ -4480,7 +4476,7 @@ xfs_bmapi_write(
xfs_extlen_t total, /* total blocks needed */
struct xfs_bmbt_irec *mval, /* output: map values */
int *nmap, /* i/o: mval size/count */
- struct xfs_bmap_free *flist) /* i/o: list extents to free */
+ struct xfs_defer_ops *dfops) /* i/o: list extents to free */
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp;
@@ -4570,7 +4566,7 @@ xfs_bmapi_write(
bma.ip = ip;
bma.total = total;
bma.userdata = 0;
- bma.flist = flist;
+ bma.dfops = dfops;
bma.firstblock = firstblock;
while (bno < end && n < *nmap) {
@@ -4684,7 +4680,7 @@ error0:
XFS_FSB_TO_AGNO(mp, *firstblock) ==
XFS_FSB_TO_AGNO(mp,
bma.cur->bc_private.b.firstblock) ||
- (flist->xbf_low &&
+ (dfops->dop_low &&
XFS_FSB_TO_AGNO(mp, *firstblock) <
XFS_FSB_TO_AGNO(mp,
bma.cur->bc_private.b.firstblock)));
@@ -4768,7 +4764,7 @@ xfs_bmap_del_extent(
xfs_inode_t *ip, /* incore inode pointer */
xfs_trans_t *tp, /* current transaction pointer */
xfs_extnum_t *idx, /* extent number to update/delete */
- xfs_bmap_free_t *flist, /* list of extents to be freed */
+ struct xfs_defer_ops *dfops, /* list of extents to be freed */
xfs_btree_cur_t *cur, /* if null, not a btree */
xfs_bmbt_irec_t *del, /* data to remove from extents */
int *logflagsp, /* inode logging flags */
@@ -4870,6 +4866,7 @@ xfs_bmap_del_extent(
nblks = 0;
do_fx = 0;
}
+
/*
* Set flag value to use in switch statement.
* Left-contig is 2, right-contig is 1.
@@ -5052,12 +5049,20 @@ xfs_bmap_del_extent(
++*idx;
break;
}
+
+ /* remove reverse mapping */
+ if (!delay) {
+ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del);
+ if (error)
+ goto done;
+ }
+
/*
* If we need to, add to list of extents to delete.
*/
if (do_fx)
- xfs_bmap_add_free(mp, flist, del->br_startblock,
- del->br_blockcount);
+ xfs_bmap_add_free(mp, dfops, del->br_startblock,
+ del->br_blockcount, NULL);
/*
* Adjust inode # blocks in the file.
*/
@@ -5097,7 +5102,7 @@ xfs_bunmapi(
xfs_extnum_t nexts, /* number of extents max */
xfs_fsblock_t *firstblock, /* first allocated block
controls a.g. for allocs */
- xfs_bmap_free_t *flist, /* i/o: list extents to free */
+ struct xfs_defer_ops *dfops, /* i/o: list extents to free */
int *done) /* set if not done yet */
{
xfs_btree_cur_t *cur; /* bmap btree cursor */
@@ -5170,7 +5175,7 @@ xfs_bunmapi(
ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstblock;
- cur->bc_private.b.flist = flist;
+ cur->bc_private.b.dfops = dfops;
cur->bc_private.b.flags = 0;
} else
cur = NULL;
@@ -5179,8 +5184,10 @@ xfs_bunmapi(
/*
* Synchronize by locking the bitmap inode.
*/
- xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP);
xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+ xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM);
+ xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
}
extno = 0;
@@ -5262,7 +5269,7 @@ xfs_bunmapi(
}
del.br_state = XFS_EXT_UNWRITTEN;
error = xfs_bmap_add_extent_unwritten_real(tp, ip,
- &lastx, &cur, &del, firstblock, flist,
+ &lastx, &cur, &del, firstblock, dfops,
&logflags);
if (error)
goto error0;
@@ -5321,7 +5328,7 @@ xfs_bunmapi(
lastx--;
error = xfs_bmap_add_extent_unwritten_real(tp,
ip, &lastx, &cur, &prev,
- firstblock, flist, &logflags);
+ firstblock, dfops, &logflags);
if (error)
goto error0;
goto nodelete;
@@ -5330,7 +5337,7 @@ xfs_bunmapi(
del.br_state = XFS_EXT_UNWRITTEN;
error = xfs_bmap_add_extent_unwritten_real(tp,
ip, &lastx, &cur, &del,
- firstblock, flist, &logflags);
+ firstblock, dfops, &logflags);
if (error)
goto error0;
goto nodelete;
@@ -5388,7 +5395,7 @@ xfs_bunmapi(
} else if (cur)
cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL;
- error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del,
+ error = xfs_bmap_del_extent(ip, tp, &lastx, dfops, cur, &del,
&tmp_logflags, whichfork);
logflags |= tmp_logflags;
if (error)
@@ -5422,7 +5429,7 @@ nodelete:
*/
if (xfs_bmap_needs_btree(ip, whichfork)) {
ASSERT(cur == NULL);
- error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist,
+ error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops,
&cur, 0, &tmp_logflags, whichfork);
logflags |= tmp_logflags;
if (error)
@@ -5589,7 +5596,8 @@ xfs_bmse_shift_one(
struct xfs_bmbt_rec_host *gotp,
struct xfs_btree_cur *cur,
int *logflags,
- enum shift_direction direction)
+ enum shift_direction direction,
+ struct xfs_defer_ops *dfops)
{
struct xfs_ifork *ifp;
struct xfs_mount *mp;
@@ -5637,9 +5645,13 @@ xfs_bmse_shift_one(
/* check whether to merge the extent or shift it down */
if (xfs_bmse_can_merge(&adj_irec, &got,
offset_shift_fsb)) {
- return xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
- *current_ext, gotp, adj_irecp,
- cur, logflags);
+ error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
+ *current_ext, gotp, adj_irecp,
+ cur, logflags);
+ if (error)
+ return error;
+ adj_irec = got;
+ goto update_rmap;
}
} else {
startoff = got.br_startoff + offset_shift_fsb;
@@ -5676,9 +5688,10 @@ update_current_ext:
(*current_ext)--;
xfs_bmbt_set_startoff(gotp, startoff);
*logflags |= XFS_ILOG_CORE;
+ adj_irec = got;
if (!cur) {
*logflags |= XFS_ILOG_DEXT;
- return 0;
+ goto update_rmap;
}
error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
@@ -5688,8 +5701,18 @@ update_current_ext:
XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
got.br_startoff = startoff;
- return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
- got.br_blockcount, got.br_state);
+ error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
+ got.br_blockcount, got.br_state);
+ if (error)
+ return error;
+
+update_rmap:
+ /* update reverse mapping */
+ error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec);
+ if (error)
+ return error;
+ adj_irec.br_startoff = startoff;
+ return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec);
}
/*
@@ -5711,7 +5734,7 @@ xfs_bmap_shift_extents(
int *done,
xfs_fileoff_t stop_fsb,
xfs_fsblock_t *firstblock,
- struct xfs_bmap_free *flist,
+ struct xfs_defer_ops *dfops,
enum shift_direction direction,
int num_exts)
{
@@ -5756,7 +5779,7 @@ xfs_bmap_shift_extents(
if (ifp->if_flags & XFS_IFBROOT) {
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstblock;
- cur->bc_private.b.flist = flist;
+ cur->bc_private.b.dfops = dfops;
cur->bc_private.b.flags = 0;
}
@@ -5817,7 +5840,7 @@ xfs_bmap_shift_extents(
while (nexts++ < num_exts) {
error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
&current_ext, gotp, cur, &logflags,
- direction);
+ direction, dfops);
if (error)
goto del_cursor;
/*
@@ -5865,7 +5888,7 @@ xfs_bmap_split_extent_at(
struct xfs_inode *ip,
xfs_fileoff_t split_fsb,
xfs_fsblock_t *firstfsb,
- struct xfs_bmap_free *free_list)
+ struct xfs_defer_ops *dfops)
{
int whichfork = XFS_DATA_FORK;
struct xfs_btree_cur *cur = NULL;
@@ -5927,7 +5950,7 @@ xfs_bmap_split_extent_at(
if (ifp->if_flags & XFS_IFBROOT) {
cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
cur->bc_private.b.firstblock = *firstfsb;
- cur->bc_private.b.flist = free_list;
+ cur->bc_private.b.dfops = dfops;
cur->bc_private.b.flags = 0;
error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
got.br_startblock,
@@ -5980,7 +6003,7 @@ xfs_bmap_split_extent_at(
int tmp_logflags; /* partial log flag return val */
ASSERT(cur == NULL);
- error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list,
+ error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, dfops,
&cur, 0, &tmp_logflags, whichfork);
logflags |= tmp_logflags;
}
@@ -6004,7 +6027,7 @@ xfs_bmap_split_extent(
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
- struct xfs_bmap_free free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t firstfsb;
int error;
@@ -6016,21 +6039,21 @@ xfs_bmap_split_extent(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_bmap_init(&free_list, &firstfsb);
+ xfs_defer_init(&dfops, &firstfsb);
error = xfs_bmap_split_extent_at(tp, ip, split_fsb,
- &firstfsb, &free_list);
+ &firstfsb, &dfops);
if (error)
goto out;
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out;
return xfs_trans_commit(tp);
out:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
xfs_trans_cancel(tp);
return error;
}
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index f1f3ae6c0a3f..254034f96941 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone;
*/
struct xfs_bmalloca {
xfs_fsblock_t *firstblock; /* i/o first block allocated */
- struct xfs_bmap_free *flist; /* bmap freelist */
+ struct xfs_defer_ops *dfops; /* bmap freelist */
struct xfs_trans *tp; /* transaction pointer */
struct xfs_inode *ip; /* incore inode pointer */
struct xfs_bmbt_irec prev; /* extent before the new one */
@@ -62,34 +62,14 @@ struct xfs_bmalloca {
* List of extents to be free "later".
* The list is kept sorted on xbf_startblock.
*/
-struct xfs_bmap_free_item
+struct xfs_extent_free_item
{
- xfs_fsblock_t xbfi_startblock;/* starting fs block number */
- xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */
- struct list_head xbfi_list;
+ xfs_fsblock_t xefi_startblock;/* starting fs block number */
+ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
+ struct list_head xefi_list;
+ struct xfs_owner_info xefi_oinfo; /* extent owner */
};
-/*
- * Header for free extent list.
- *
- * xbf_low is used by the allocator to activate the lowspace algorithm -
- * when free space is running low the extent allocator may choose to
- * allocate an extent from an AG without leaving sufficient space for
- * a btree split when inserting the new extent. In this case the allocator
- * will enable the lowspace algorithm which is supposed to allow further
- * allocations (such as btree splits and newroots) to allocate from
- * sequential AGs. In order to avoid locking AGs out of order the lowspace
- * algorithm will start searching for free space from AG 0. If the correct
- * transaction reservations have been made then this algorithm will eventually
- * find all the space it needs.
- */
-typedef struct xfs_bmap_free
-{
- struct list_head xbf_flist; /* list of to-be-free extents */
- int xbf_count; /* count of items on list */
- int xbf_low; /* alloc in low mode */
-} xfs_bmap_free_t;
-
#define XFS_BMAP_MAX_NMAP 4
/*
@@ -139,14 +119,6 @@ static inline int xfs_bmapi_aflag(int w)
#define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL)
#define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL)
-static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
-{
- INIT_LIST_HEAD(&flp->xbf_flist);
- flp->xbf_count = 0;
- flp->xbf_low = 0;
- *fbp = NULLFSBLOCK;
-}
-
/*
* Flags for xfs_bmap_add_extent*.
*/
@@ -193,11 +165,9 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt,
int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
-void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist,
- xfs_fsblock_t bno, xfs_filblks_t len);
-void xfs_bmap_cancel(struct xfs_bmap_free *flist);
-int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist,
- struct xfs_inode *ip);
+void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ xfs_fsblock_t bno, xfs_filblks_t len,
+ struct xfs_owner_info *oinfo);
void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
@@ -218,18 +188,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_fileoff_t bno, xfs_filblks_t len, int flags,
xfs_fsblock_t *firstblock, xfs_extlen_t total,
struct xfs_bmbt_irec *mval, int *nmap,
- struct xfs_bmap_free *flist);
+ struct xfs_defer_ops *dfops);
int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_fileoff_t bno, xfs_filblks_t len, int flags,
xfs_extnum_t nexts, xfs_fsblock_t *firstblock,
- struct xfs_bmap_free *flist, int *done);
+ struct xfs_defer_ops *dfops, int *done);
int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
xfs_extnum_t num);
uint xfs_default_attroffset(struct xfs_inode *ip);
int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
- struct xfs_bmap_free *flist, enum shift_direction direction,
+ struct xfs_defer_ops *dfops, enum shift_direction direction,
int num_exts);
int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index db0c71e470c9..cd85274e810c 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "xfs_inode_item.h"
@@ -34,6 +35,7 @@
#include "xfs_quota.h"
#include "xfs_trace.h"
#include "xfs_cksum.h"
+#include "xfs_rmap.h"
/*
* Determine the extent state.
@@ -406,11 +408,11 @@ xfs_bmbt_dup_cursor(
cur->bc_private.b.ip, cur->bc_private.b.whichfork);
/*
- * Copy the firstblock, flist, and flags values,
+ * Copy the firstblock, dfops, and flags values,
* since init cursor doesn't get them.
*/
new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
- new->bc_private.b.flist = cur->bc_private.b.flist;
+ new->bc_private.b.dfops = cur->bc_private.b.dfops;
new->bc_private.b.flags = cur->bc_private.b.flags;
return new;
@@ -423,7 +425,7 @@ xfs_bmbt_update_cursor(
{
ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) ||
(dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME));
- ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist);
+ ASSERT(dst->bc_private.b.dfops == src->bc_private.b.dfops);
dst->bc_private.b.allocated += src->bc_private.b.allocated;
dst->bc_private.b.firstblock = src->bc_private.b.firstblock;
@@ -446,6 +448,8 @@ xfs_bmbt_alloc_block(
args.mp = cur->bc_mp;
args.fsbno = cur->bc_private.b.firstblock;
args.firstblock = args.fsbno;
+ xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino,
+ cur->bc_private.b.whichfork);
if (args.fsbno == NULLFSBLOCK) {
args.fsbno = be64_to_cpu(start->l);
@@ -462,7 +466,7 @@ xfs_bmbt_alloc_block(
* block allocation here and corrupt the filesystem.
*/
args.minleft = args.tp->t_blk_res;
- } else if (cur->bc_private.b.flist->xbf_low) {
+ } else if (cur->bc_private.b.dfops->dop_low) {
args.type = XFS_ALLOCTYPE_START_BNO;
} else {
args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -490,7 +494,7 @@ xfs_bmbt_alloc_block(
error = xfs_alloc_vextent(&args);
if (error)
goto error0;
- cur->bc_private.b.flist->xbf_low = 1;
+ cur->bc_private.b.dfops->dop_low = true;
}
if (args.fsbno == NULLFSBLOCK) {
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
@@ -525,8 +529,10 @@ xfs_bmbt_free_block(
struct xfs_inode *ip = cur->bc_private.b.ip;
struct xfs_trans *tp = cur->bc_tp;
xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp));
+ struct xfs_owner_info oinfo;
- xfs_bmap_add_free(mp, cur->bc_private.b.flist, fsbno, 1);
+ xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork);
+ xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo);
ip->i_d.di_nblocks--;
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
@@ -600,17 +606,6 @@ xfs_bmbt_init_key_from_rec(
}
STATIC void
-xfs_bmbt_init_rec_from_key(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
-{
- ASSERT(key->bmbt.br_startoff != 0);
-
- xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff),
- 0, 0, XFS_EXT_NORM);
-}
-
-STATIC void
xfs_bmbt_init_rec_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_rec *rec)
@@ -760,7 +755,6 @@ static const struct xfs_btree_ops xfs_bmbt_ops = {
.get_minrecs = xfs_bmbt_get_minrecs,
.get_dmaxrecs = xfs_bmbt_get_dmaxrecs,
.init_key_from_rec = xfs_bmbt_init_key_from_rec,
- .init_rec_from_key = xfs_bmbt_init_rec_from_key,
.init_rec_from_cur = xfs_bmbt_init_rec_from_cur,
.init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur,
.key_diff = xfs_bmbt_key_diff,
@@ -800,7 +794,7 @@ xfs_bmbt_init_cursor(
cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
cur->bc_private.b.ip = ip;
cur->bc_private.b.firstblock = NULLFSBLOCK;
- cur->bc_private.b.flist = NULL;
+ cur->bc_private.b.dfops = NULL;
cur->bc_private.b.allocated = 0;
cur->bc_private.b.flags = 0;
cur->bc_private.b.whichfork = whichfork;
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 07eeb0b4ca74..b5c213a051cd 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_trans.h"
#include "xfs_inode_item.h"
@@ -43,15 +44,14 @@ kmem_zone_t *xfs_btree_cur_zone;
* Btree magic numbers.
*/
static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
- { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC,
+ { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC,
XFS_FIBT_MAGIC },
- { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC,
+ { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC,
XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC }
};
#define xfs_btree_magic(cur) \
xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
-
STATIC int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lblock(
struct xfs_btree_cur *cur, /* btree cursor */
@@ -428,6 +428,50 @@ xfs_btree_dup_cursor(
* into a btree block (xfs_btree_*_offset) or return a pointer to the given
* record, key or pointer (xfs_btree_*_addr). Note that all addressing
* inside the btree block is done using indices starting at one, not zero!
+ *
+ * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing
+ * overlapping intervals. In such a tree, records are still sorted lowest to
+ * highest and indexed by the smallest key value that refers to the record.
+ * However, nodes are different: each pointer has two associated keys -- one
+ * indexing the lowest key available in the block(s) below (the same behavior
+ * as the key in a regular btree) and another indexing the highest key
+ * available in the block(s) below. Because records are /not/ sorted by the
+ * highest key, all leaf block updates require us to compute the highest key
+ * that matches any record in the leaf and to recursively update the high keys
+ * in the nodes going further up in the tree, if necessary. Nodes look like
+ * this:
+ *
+ * +--------+-----+-----+-----+-----+-----+-------+-------+-----+
+ * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... |
+ * +--------+-----+-----+-----+-----+-----+-------+-------+-----+
+ *
+ * To perform an interval query on an overlapped tree, perform the usual
+ * depth-first search and use the low and high keys to decide if we can skip
+ * that particular node. If a leaf node is reached, return the records that
+ * intersect the interval. Note that an interval query may return numerous
+ * entries. For a non-overlapped tree, simply search for the record associated
+ * with the lowest key and iterate forward until a non-matching record is
+ * found. Section 14.3 ("Interval Trees") of _Introduction to Algorithms_ by
+ * Cormen, Leiserson, Rivest, and Stein (2nd or 3rd ed. only) discuss this in
+ * more detail.
+ *
+ * Why do we care about overlapping intervals? Let's say you have a bunch of
+ * reverse mapping records on a reflink filesystem:
+ *
+ * 1: +- file A startblock B offset C length D -----------+
+ * 2: +- file E startblock F offset G length H --------------+
+ * 3: +- file I startblock F offset J length K --+
+ * 4: +- file L... --+
+ *
+ * Now say we want to map block (B+D) into file A at offset (C+D). Ideally,
+ * we'd simply increment the length of record 1. But how do we find the record
+ * that ends at (B+D-1) (i.e. record 1)? A LE lookup of (B+D-1) would return
+ * record 3 because the keys are ordered first by startblock. An interval
+ * query would return records 1 and 2 because they both overlap (B+D-1), and
+ * from that we can pick out record 1 as the appropriate left neighbor.
+ *
+ * In the non-overlapped case you can do a LE lookup and decrement the cursor
+ * because a record's interval must end before the next record.
*/
/*
@@ -479,6 +523,18 @@ xfs_btree_key_offset(
}
/*
+ * Calculate offset of the n-th high key in a btree block.
+ */
+STATIC size_t
+xfs_btree_high_key_offset(
+ struct xfs_btree_cur *cur,
+ int n)
+{
+ return xfs_btree_block_len(cur) +
+ (n - 1) * cur->bc_ops->key_len + (cur->bc_ops->key_len / 2);
+}
+
+/*
* Calculate offset of the n-th block pointer in a btree block.
*/
STATIC size_t
@@ -519,6 +575,19 @@ xfs_btree_key_addr(
}
/*
+ * Return a pointer to the n-th high key in the btree block.
+ */
+STATIC union xfs_btree_key *
+xfs_btree_high_key_addr(
+ struct xfs_btree_cur *cur,
+ int n,
+ struct xfs_btree_block *block)
+{
+ return (union xfs_btree_key *)
+ ((char *)block + xfs_btree_high_key_offset(cur, n));
+}
+
+/*
* Return a pointer to the n-th block pointer in the btree block.
*/
STATIC union xfs_btree_ptr *
@@ -1144,6 +1213,9 @@ xfs_btree_set_refs(
case XFS_BTNUM_BMAP:
xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF);
break;
+ case XFS_BTNUM_RMAP:
+ xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF);
+ break;
default:
ASSERT(0);
}
@@ -1879,32 +1951,214 @@ error0:
return error;
}
+/* Find the high key storage area from a regular key. */
+STATIC union xfs_btree_key *
+xfs_btree_high_key_from_key(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *key)
+{
+ ASSERT(cur->bc_flags & XFS_BTREE_OVERLAPPING);
+ return (union xfs_btree_key *)((char *)key +
+ (cur->bc_ops->key_len / 2));
+}
+
+/* Determine the low (and high if overlapped) keys of a leaf block */
+STATIC void
+xfs_btree_get_leaf_keys(
+ struct xfs_btree_cur *cur,
+ struct xfs_btree_block *block,
+ union xfs_btree_key *key)
+{
+ union xfs_btree_key max_hkey;
+ union xfs_btree_key hkey;
+ union xfs_btree_rec *rec;
+ union xfs_btree_key *high;
+ int n;
+
+ rec = xfs_btree_rec_addr(cur, 1, block);
+ cur->bc_ops->init_key_from_rec(key, rec);
+
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) {
+
+ cur->bc_ops->init_high_key_from_rec(&max_hkey, rec);
+ for (n = 2; n <= xfs_btree_get_numrecs(block); n++) {
+ rec = xfs_btree_rec_addr(cur, n, block);
+ cur->bc_ops->init_high_key_from_rec(&hkey, rec);
+ if (cur->bc_ops->diff_two_keys(cur, &hkey, &max_hkey)
+ > 0)
+ max_hkey = hkey;
+ }
+
+ high = xfs_btree_high_key_from_key(cur, key);
+ memcpy(high, &max_hkey, cur->bc_ops->key_len / 2);
+ }
+}
+
+/* Determine the low (and high if overlapped) keys of a node block */
+STATIC void
+xfs_btree_get_node_keys(
+ struct xfs_btree_cur *cur,
+ struct xfs_btree_block *block,
+ union xfs_btree_key *key)
+{
+ union xfs_btree_key *hkey;
+ union xfs_btree_key *max_hkey;
+ union xfs_btree_key *high;
+ int n;
+
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) {
+ memcpy(key, xfs_btree_key_addr(cur, 1, block),
+ cur->bc_ops->key_len / 2);
+
+ max_hkey = xfs_btree_high_key_addr(cur, 1, block);
+ for (n = 2; n <= xfs_btree_get_numrecs(block); n++) {
+ hkey = xfs_btree_high_key_addr(cur, n, block);
+ if (cur->bc_ops->diff_two_keys(cur, hkey, max_hkey) > 0)
+ max_hkey = hkey;
+ }
+
+ high = xfs_btree_high_key_from_key(cur, key);
+ memcpy(high, max_hkey, cur->bc_ops->key_len / 2);
+ } else {
+ memcpy(key, xfs_btree_key_addr(cur, 1, block),
+ cur->bc_ops->key_len);
+ }
+}
+
+/* Derive the keys for any btree block. */
+STATIC void
+xfs_btree_get_keys(
+ struct xfs_btree_cur *cur,
+ struct xfs_btree_block *block,
+ union xfs_btree_key *key)
+{
+ if (be16_to_cpu(block->bb_level) == 0)
+ xfs_btree_get_leaf_keys(cur, block, key);
+ else
+ xfs_btree_get_node_keys(cur, block, key);
+}
+
/*
- * Update keys at all levels from here to the root along the cursor's path.
+ * Decide if we need to update the parent keys of a btree block. For
+ * a standard btree this is only necessary if we're updating the first
+ * record/key. For an overlapping btree, we must always update the
+ * keys because the highest key can be in any of the records or keys
+ * in the block.
+ */
+static inline bool
+xfs_btree_needs_key_update(
+ struct xfs_btree_cur *cur,
+ int ptr)
+{
+ return (cur->bc_flags & XFS_BTREE_OVERLAPPING) || ptr == 1;
+}
+
+/*
+ * Update the low and high parent keys of the given level, progressing
+ * towards the root. If force_all is false, stop if the keys for a given
+ * level do not need updating.
*/
STATIC int
-xfs_btree_updkey(
+__xfs_btree_updkeys(
+ struct xfs_btree_cur *cur,
+ int level,
+ struct xfs_btree_block *block,
+ struct xfs_buf *bp0,
+ bool force_all)
+{
+ union xfs_btree_bigkey key; /* keys from current level */
+ union xfs_btree_key *lkey; /* keys from the next level up */
+ union xfs_btree_key *hkey;
+ union xfs_btree_key *nlkey; /* keys from the next level up */
+ union xfs_btree_key *nhkey;
+ struct xfs_buf *bp;
+ int ptr;
+
+ ASSERT(cur->bc_flags & XFS_BTREE_OVERLAPPING);
+
+ /* Exit if there aren't any parent levels to update. */
+ if (level + 1 >= cur->bc_nlevels)
+ return 0;
+
+ trace_xfs_btree_updkeys(cur, level, bp0);
+
+ lkey = (union xfs_btree_key *)&key;
+ hkey = xfs_btree_high_key_from_key(cur, lkey);
+ xfs_btree_get_keys(cur, block, lkey);
+ for (level++; level < cur->bc_nlevels; level++) {
+#ifdef DEBUG
+ int error;
+#endif
+ block = xfs_btree_get_block(cur, level, &bp);
+ trace_xfs_btree_updkeys(cur, level, bp);
+#ifdef DEBUG
+ error = xfs_btree_check_block(cur, block, level, bp);
+ if (error) {
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+ return error;
+ }
+#endif
+ ptr = cur->bc_ptrs[level];
+ nlkey = xfs_btree_key_addr(cur, ptr, block);
+ nhkey = xfs_btree_high_key_addr(cur, ptr, block);
+ if (!force_all &&
+ !(cur->bc_ops->diff_two_keys(cur, nlkey, lkey) != 0 ||
+ cur->bc_ops->diff_two_keys(cur, nhkey, hkey) != 0))
+ break;
+ xfs_btree_copy_keys(cur, nlkey, lkey, 1);
+ xfs_btree_log_keys(cur, bp, ptr, ptr);
+ if (level + 1 >= cur->bc_nlevels)
+ break;
+ xfs_btree_get_node_keys(cur, block, lkey);
+ }
+
+ return 0;
+}
+
+/* Update all the keys from some level in cursor back to the root. */
+STATIC int
+xfs_btree_updkeys_force(
+ struct xfs_btree_cur *cur,
+ int level)
+{
+ struct xfs_buf *bp;
+ struct xfs_btree_block *block;
+
+ block = xfs_btree_get_block(cur, level, &bp);
+ return __xfs_btree_updkeys(cur, level, block, bp, true);
+}
+
+/*
+ * Update the parent keys of the given level, progressing towards the root.
+ */
+STATIC int
+xfs_btree_update_keys(
struct xfs_btree_cur *cur,
- union xfs_btree_key *keyp,
int level)
{
struct xfs_btree_block *block;
struct xfs_buf *bp;
union xfs_btree_key *kp;
+ union xfs_btree_key key;
int ptr;
+ ASSERT(level >= 0);
+
+ block = xfs_btree_get_block(cur, level, &bp);
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING)
+ return __xfs_btree_updkeys(cur, level, block, bp, false);
+
XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
XFS_BTREE_TRACE_ARGIK(cur, level, keyp);
- ASSERT(!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) || level >= 1);
-
/*
* Go up the tree from this level toward the root.
* At each level, update the key value to the value input.
* Stop when we reach a level where the cursor isn't pointing
* at the first entry in the block.
*/
- for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
+ xfs_btree_get_keys(cur, block, &key);
+ for (level++, ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
#ifdef DEBUG
int error;
#endif
@@ -1918,7 +2172,7 @@ xfs_btree_updkey(
#endif
ptr = cur->bc_ptrs[level];
kp = xfs_btree_key_addr(cur, ptr, block);
- xfs_btree_copy_keys(cur, kp, keyp, 1);
+ xfs_btree_copy_keys(cur, kp, &key, 1);
xfs_btree_log_keys(cur, bp, ptr, ptr);
}
@@ -1970,12 +2224,9 @@ xfs_btree_update(
ptr, LASTREC_UPDATE);
}
- /* Updating first rec in leaf. Pass new key value up to our parent. */
- if (ptr == 1) {
- union xfs_btree_key key;
-
- cur->bc_ops->init_key_from_rec(&key, rec);
- error = xfs_btree_updkey(cur, &key, 1);
+ /* Pass new key value up to our parent. */
+ if (xfs_btree_needs_key_update(cur, ptr)) {
+ error = xfs_btree_update_keys(cur, 0);
if (error)
goto error0;
}
@@ -1998,18 +2249,19 @@ xfs_btree_lshift(
int level,
int *stat) /* success/failure */
{
- union xfs_btree_key key; /* btree key */
struct xfs_buf *lbp; /* left buffer pointer */
struct xfs_btree_block *left; /* left btree block */
int lrecs; /* left record count */
struct xfs_buf *rbp; /* right buffer pointer */
struct xfs_btree_block *right; /* right btree block */
+ struct xfs_btree_cur *tcur; /* temporary btree cursor */
int rrecs; /* right record count */
union xfs_btree_ptr lptr; /* left btree pointer */
union xfs_btree_key *rkp = NULL; /* right btree key */
union xfs_btree_ptr *rpp = NULL; /* right address pointer */
union xfs_btree_rec *rrp = NULL; /* right record pointer */
int error; /* error return value */
+ int i;
XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
XFS_BTREE_TRACE_ARGI(cur, level);
@@ -2139,18 +2391,33 @@ xfs_btree_lshift(
xfs_btree_rec_addr(cur, 2, right),
-1, rrecs);
xfs_btree_log_recs(cur, rbp, 1, rrecs);
+ }
- /*
- * If it's the first record in the block, we'll need a key
- * structure to pass up to the next level (updkey).
- */
- cur->bc_ops->init_key_from_rec(&key,
- xfs_btree_rec_addr(cur, 1, right));
- rkp = &key;
+ /*
+ * Using a temporary cursor, update the parent key values of the
+ * block on the left.
+ */
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) {
+ error = xfs_btree_dup_cursor(cur, &tcur);
+ if (error)
+ goto error0;
+ i = xfs_btree_firstrec(tcur, level);
+ XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0);
+
+ error = xfs_btree_decrement(tcur, level, &i);
+ if (error)
+ goto error1;
+
+ /* Update the parent high keys of the left block, if needed. */
+ error = xfs_btree_update_keys(tcur, level);
+ if (error)
+ goto error1;
+
+ xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
}
- /* Update the parent key values of right. */
- error = xfs_btree_updkey(cur, rkp, level + 1);
+ /* Update the parent keys of the right block. */
+ error = xfs_btree_update_keys(cur, level);
if (error)
goto error0;
@@ -2169,6 +2436,11 @@ out0:
error0:
XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
return error;
+
+error1:
+ XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR);
+ xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
+ return error;
}
/*
@@ -2181,7 +2453,6 @@ xfs_btree_rshift(
int level,
int *stat) /* success/failure */
{
- union xfs_btree_key key; /* btree key */
struct xfs_buf *lbp; /* left buffer pointer */
struct xfs_btree_block *left; /* left btree block */
struct xfs_buf *rbp; /* right buffer pointer */
@@ -2290,12 +2561,6 @@ xfs_btree_rshift(
/* Now put the new data in, and log it. */
xfs_btree_copy_recs(cur, rrp, lrp, 1);
xfs_btree_log_recs(cur, rbp, 1, rrecs + 1);
-
- cur->bc_ops->init_key_from_rec(&key, rrp);
- rkp = &key;
-
- ASSERT(cur->bc_ops->recs_inorder(cur, rrp,
- xfs_btree_rec_addr(cur, 2, right)));
}
/*
@@ -2315,13 +2580,21 @@ xfs_btree_rshift(
if (error)
goto error0;
i = xfs_btree_lastrec(tcur, level);
- XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, i == 1, error0);
+ XFS_WANT_CORRUPTED_GOTO(tcur->bc_mp, i == 1, error0);
error = xfs_btree_increment(tcur, level, &i);
if (error)
goto error1;
- error = xfs_btree_updkey(tcur, rkp, level + 1);
+ /* Update the parent high keys of the left block, if needed. */
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) {
+ error = xfs_btree_update_keys(cur, level);
+ if (error)
+ goto error1;
+ }
+
+ /* Update the parent keys of the right block. */
+ error = xfs_btree_update_keys(tcur, level);
if (error)
goto error1;
@@ -2422,6 +2695,11 @@ __xfs_btree_split(
XFS_BTREE_STATS_ADD(cur, moves, rrecs);
+ /* Adjust numrecs for the later get_*_keys() calls. */
+ lrecs -= rrecs;
+ xfs_btree_set_numrecs(left, lrecs);
+ xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs);
+
/*
* Copy btree block entries from the left block over to the
* new block, the right. Update the right block and log the
@@ -2447,14 +2725,15 @@ __xfs_btree_split(
}
#endif
+ /* Copy the keys & pointers to the new block. */
xfs_btree_copy_keys(cur, rkp, lkp, rrecs);
xfs_btree_copy_ptrs(cur, rpp, lpp, rrecs);
xfs_btree_log_keys(cur, rbp, 1, rrecs);
xfs_btree_log_ptrs(cur, rbp, 1, rrecs);
- /* Grab the keys to the entries moved to the right block */
- xfs_btree_copy_keys(cur, key, rkp, 1);
+ /* Stash the keys of the new block for later insertion. */
+ xfs_btree_get_node_keys(cur, right, key);
} else {
/* It's a leaf. Move records. */
union xfs_btree_rec *lrp; /* left record pointer */
@@ -2463,27 +2742,23 @@ __xfs_btree_split(
lrp = xfs_btree_rec_addr(cur, src_index, left);
rrp = xfs_btree_rec_addr(cur, 1, right);
+ /* Copy records to the new block. */
xfs_btree_copy_recs(cur, rrp, lrp, rrecs);
xfs_btree_log_recs(cur, rbp, 1, rrecs);
- cur->bc_ops->init_key_from_rec(key,
- xfs_btree_rec_addr(cur, 1, right));
+ /* Stash the keys of the new block for later insertion. */
+ xfs_btree_get_leaf_keys(cur, right, key);
}
-
/*
* Find the left block number by looking in the buffer.
- * Adjust numrecs, sibling pointers.
+ * Adjust sibling pointers.
*/
xfs_btree_get_sibling(cur, left, &rrptr, XFS_BB_RIGHTSIB);
xfs_btree_set_sibling(cur, right, &rrptr, XFS_BB_RIGHTSIB);
xfs_btree_set_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
xfs_btree_set_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB);
- lrecs -= rrecs;
- xfs_btree_set_numrecs(left, lrecs);
- xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs);
-
xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS);
xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
@@ -2499,6 +2774,14 @@ __xfs_btree_split(
xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB);
xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB);
}
+
+ /* Update the parent high keys of the left block, if needed. */
+ if (cur->bc_flags & XFS_BTREE_OVERLAPPING) {
+ error = xfs_btree_update_keys(cur, level);
+ if (error)
+ goto error0;
+ }
+
/*
* If the cursor is really in the right block, move it there.
* If it's just pointing past the last entry in left, then we'll
@@ -2802,6 +3085,7 @@ xfs_btree_new_root(
bp = lbp;
nptr = 2;
}
+
/* Fill in the new block's btree header and log it. */
xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2);
xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS);
@@ -2810,19 +3094,24 @@ xfs_btree_new_root(
/* Fill in the key data in the new root. */
if (xfs_btree_get_level(left) > 0) {
- xfs_btree_copy_keys(cur,
- xfs_btree_key_addr(cur, 1, new),
- xfs_btree_key_addr(cur, 1, left), 1);
- xfs_btree_copy_keys(cur,
- xfs_btree_key_addr(cur, 2, new),
- xfs_btree_key_addr(cur, 1, right), 1);
+ /*
+ * Get the keys for the left block's keys and put them directly
+ * in the parent block. Do the same for the right block.
+ */
+ xfs_btree_get_node_keys(cur, left,
+ xfs_btree_key_addr(cur, 1, new));
+ xfs_btree_get_node_keys(cur, right,
+ xfs_btree_key_addr(cur, 2, new));
} else {
- cur->bc_ops->init_key_from_rec(
- xfs_btree_key_addr(cur, 1, new),
- xfs_btree_rec_addr(cur, 1, left));
- cur->bc_ops->init_key_from_rec(
- xfs_btree_key_addr(cur, 2, new),
- xfs_btree_rec_addr(cur, 1, right));
+ /*
+ * Get the keys for the left block's records and put them
+ * directly in the parent block. Do the same for the right
+ * block.
+ */
+ xfs_btree_get_leaf_keys(cur, left,
+ xfs_btree_key_addr(cur, 1, new));
+ xfs_btree_get_leaf_keys(cur, right,
+ xfs_btree_key_addr(cur, 2, new));
}
xfs_btree_log_keys(cur, nbp, 1, 2);
@@ -2858,10 +3147,9 @@ xfs_btree_make_block_unfull(
int *index, /* new tree index */
union xfs_btree_ptr *nptr, /* new btree ptr */
struct xfs_btree_cur **ncur, /* new btree cursor */
- union xfs_btree_rec *nrec, /* new record */
+ union xfs_btree_key *key, /* key of new block */
int *stat)
{
- union xfs_btree_key key; /* new btree key value */
int error = 0;
if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
@@ -2871,6 +3159,7 @@ xfs_btree_make_block_unfull(
if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) {
/* A root block that can be made bigger. */
xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork);
+ *stat = 1;
} else {
/* A root block that needs replacing */
int logflags = 0;
@@ -2906,13 +3195,12 @@ xfs_btree_make_block_unfull(
* If this works we have to re-set our variables because we
* could be in a different block now.
*/
- error = xfs_btree_split(cur, level, nptr, &key, ncur, stat);
+ error = xfs_btree_split(cur, level, nptr, key, ncur, stat);
if (error || *stat == 0)
return error;
*index = cur->bc_ptrs[level];
- cur->bc_ops->init_rec_from_key(&key, nrec);
return 0;
}
@@ -2925,16 +3213,17 @@ xfs_btree_insrec(
struct xfs_btree_cur *cur, /* btree cursor */
int level, /* level to insert record at */
union xfs_btree_ptr *ptrp, /* i/o: block number inserted */
- union xfs_btree_rec *recp, /* i/o: record data inserted */
+ union xfs_btree_rec *rec, /* record to insert */
+ union xfs_btree_key *key, /* i/o: block key for ptrp */
struct xfs_btree_cur **curp, /* output: new cursor replacing cur */
int *stat) /* success/failure */
{
struct xfs_btree_block *block; /* btree block */
struct xfs_buf *bp; /* buffer for block */
- union xfs_btree_key key; /* btree key */
union xfs_btree_ptr nptr; /* new block ptr */
struct xfs_btree_cur *ncur; /* new btree cursor */
- union xfs_btree_rec nrec; /* new record count */
+ union xfs_btree_bigkey nkey; /* new block key */
+ union xfs_btree_key *lkey;
int optr; /* old key/record index */
int ptr; /* key/record index */
int numrecs;/* number of records */
@@ -2942,11 +3231,13 @@ xfs_btree_insrec(
#ifdef DEBUG
int i;
#endif
+ xfs_daddr_t old_bn;
XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
- XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp);
+ XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec);
ncur = NULL;
+ lkey = (union xfs_btree_key *)&nkey;
/*
* If we have an external root pointer, and we've made it to the
@@ -2969,15 +3260,13 @@ xfs_btree_insrec(
return 0;
}
- /* Make a key out of the record data to be inserted, and save it. */
- cur->bc_ops->init_key_from_rec(&key, recp);
-
optr = ptr;
XFS_BTREE_STATS_INC(cur, insrec);
/* Get pointers to the btree buffer and block. */
block = xfs_btree_get_block(cur, level, &bp);
+ old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL;
numrecs = xfs_btree_get_numrecs(block);
#ifdef DEBUG
@@ -2988,10 +3277,10 @@ xfs_btree_insrec(
/* Check that the new entry is being inserted in the right place. */
if (ptr <= numrecs) {
if (level == 0) {
- ASSERT(cur->bc_ops->recs_inorder(cur, recp,
+ ASSERT(cur->bc_ops->recs_inorder(cur, rec,
xfs_btree_rec_addr(cur, ptr, block)));
} else {
- ASSERT(cur->bc_ops->keys_inorder(cur, &key,
+ ASSERT(cur->bc_ops->keys_inorder(cur, key,
xfs_btree_key_addr(cur, ptr, block)));
}
}
@@ -3004,7 +3293,7 @@ xfs_btree_insrec(
xfs_btree_set_ptr_null(cur, &nptr);
if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) {
error = xfs_btree_make_block_unfull(cur, level, numrecs,
- &optr, &ptr, &nptr, &ncur, &nrec, stat);
+ &optr, &ptr, &nptr, &ncur, lkey, stat);
if (error || *stat == 0)
goto error0;
}
@@ -3054,7 +3343,7 @@ xfs_btree_insrec(
#endif
/* Now put the new data in, bump numrecs and log it. */
- xfs_btree_copy_keys(cur, kp, &key, 1);
+ xfs_btree_copy_keys(cur, kp, key, 1);
xfs_btree_copy_ptrs(cur, pp, ptrp, 1);
numrecs++;
xfs_btree_set_numrecs(block, numrecs);
@@ -3075,7 +3364,7 @@ xfs_btree_insrec(
xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1);
/* Now put the new data in, bump numrecs and log it. */
- xfs_btree_copy_recs(cur, rp, recp, 1);
+ xfs_btree_copy_recs(cur, rp, rec, 1);
xfs_btree_set_numrecs(block, ++numrecs);
xfs_btree_log_recs(cur, bp, ptr, numrecs);
#ifdef DEBUG
@@ -3089,9 +3378,18 @@ xfs_btree_insrec(
/* Log the new number of records in the btree header. */
xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
- /* If we inserted at the start of a block, update the parents' keys. */
- if (optr == 1) {
- error = xfs_btree_updkey(cur, &key, level + 1);
+ /*
+ * If we just inserted into a new tree block, we have to
+ * recalculate nkey here because nkey is out of date.
+ *
+ * Otherwise we're just updating an existing block (having shoved
+ * some records into the new tree block), so use the regular key
+ * update mechanism.
+ */
+ if (bp && bp->b_bn != old_bn) {
+ xfs_btree_get_keys(cur, block, lkey);
+ } else if (xfs_btree_needs_key_update(cur, optr)) {
+ error = xfs_btree_update_keys(cur, level);
if (error)
goto error0;
}
@@ -3101,7 +3399,7 @@ xfs_btree_insrec(
* we are at the far right edge of the tree, update it.
*/
if (xfs_btree_is_lastrec(cur, block, level)) {
- cur->bc_ops->update_lastrec(cur, block, recp,
+ cur->bc_ops->update_lastrec(cur, block, rec,
ptr, LASTREC_INSREC);
}
@@ -3111,7 +3409,7 @@ xfs_btree_insrec(
*/
*ptrp = nptr;
if (!xfs_btree_ptr_is_null(cur, &nptr)) {
- *recp = nrec;
+ xfs_btree_copy_keys(cur, key, lkey, 1);
*curp = ncur;
}
@@ -3142,14 +3440,20 @@ xfs_btree_insert(
union xfs_btree_ptr nptr; /* new block number (split result) */
struct xfs_btree_cur *ncur; /* new cursor (split result) */
struct xfs_btree_cur *pcur; /* previous level's cursor */
+ union xfs_btree_bigkey bkey; /* key of block to insert */
+ union xfs_btree_key *key;
union xfs_btree_rec rec; /* record to insert */
level = 0;
ncur = NULL;
pcur = cur;
+ key = (union xfs_btree_key *)&bkey;
xfs_btree_set_ptr_null(cur, &nptr);
+
+ /* Make a key out of the record data to be inserted, and save it. */
cur->bc_ops->init_rec_from_cur(cur, &rec);
+ cur->bc_ops->init_key_from_rec(key, &rec);
/*
* Loop going up the tree, starting at the leaf level.
@@ -3161,7 +3465,8 @@ xfs_btree_insert(
* Insert nrec/nptr into this level of the tree.
* Note if we fail, nptr will be null.
*/
- error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i);
+ error = xfs_btree_insrec(pcur, level, &nptr, &rec, key,
+ &ncur, &i);
if (error) {
if (pcur != cur)
xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
@@ -3385,8 +3690,6 @@ xfs_btree_delrec(
struct xfs_buf *bp; /* buffer for block */
int error; /* error return value */
int i; /* loop counter */
- union xfs_btree_key key; /* storage for keyp */
- union xfs_btree_key *keyp = &key; /* passed to the next level */
union xfs_btree_ptr lptr; /* left sibling block ptr */
struct xfs_buf *lbp; /* left buffer pointer */
struct xfs_btree_block *left; /* left btree block */
@@ -3457,13 +3760,6 @@ xfs_btree_delrec(
xfs_btree_log_keys(cur, bp, ptr, numrecs - 1);
xfs_btree_log_ptrs(cur, bp, ptr, numrecs - 1);
}
-
- /*
- * If it's the first record in the block, we'll need to pass a
- * key up to the next level (updkey).
- */
- if (ptr == 1)
- keyp = xfs_btree_key_addr(cur, 1, block);
} else {
/* It's a leaf. operate on records */
if (ptr < numrecs) {
@@ -3472,16 +3768,6 @@ xfs_btree_delrec(
-1, numrecs - ptr);
xfs_btree_log_recs(cur, bp, ptr, numrecs - 1);
}
-
- /*
- * If it's the first record in the block, we'll need a key
- * structure to pass up to the next level (updkey).
- */
- if (ptr == 1) {
- cur->bc_ops->init_key_from_rec(&key,
- xfs_btree_rec_addr(cur, 1, block));
- keyp = &key;
- }
}
/*
@@ -3548,8 +3834,8 @@ xfs_btree_delrec(
* If we deleted the leftmost entry in the block, update the
* key values above us in the tree.
*/
- if (ptr == 1) {
- error = xfs_btree_updkey(cur, keyp, level + 1);
+ if (xfs_btree_needs_key_update(cur, ptr)) {
+ error = xfs_btree_update_keys(cur, level);
if (error)
goto error0;
}
@@ -3878,6 +4164,16 @@ xfs_btree_delrec(
if (level > 0)
cur->bc_ptrs[level]--;
+ /*
+ * We combined blocks, so we have to update the parent keys if the
+ * btree supports overlapped intervals. However, bc_ptrs[level + 1]
+ * points to the old block so that the caller knows which record to
+ * delete. Therefore, the caller must be savvy enough to call updkeys
+ * for us if we return stat == 2. The other exit points from this
+ * function don't require deletions further up the tree, so they can
+ * call updkeys directly.
+ */
+
XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
/* Return value means the next level up has something to do. */
*stat = 2;
@@ -3903,6 +4199,7 @@ xfs_btree_delete(
int error; /* error return value */
int level;
int i;
+ bool joined = false;
XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
@@ -3916,6 +4213,18 @@ xfs_btree_delete(
error = xfs_btree_delrec(cur, level, &i);
if (error)
goto error0;
+ if (i == 2)
+ joined = true;
+ }
+
+ /*
+ * If we combined blocks as part of deleting the record, delrec won't
+ * have updated the parent high keys so we have to do that here.
+ */
+ if (joined && (cur->bc_flags & XFS_BTREE_OVERLAPPING)) {
+ error = xfs_btree_updkeys_force(cur, 0);
+ if (error)
+ goto error0;
}
if (i == 0) {
@@ -3978,6 +4287,81 @@ xfs_btree_get_rec(
return 0;
}
+/* Visit a block in a btree. */
+STATIC int
+xfs_btree_visit_block(
+ struct xfs_btree_cur *cur,
+ int level,
+ xfs_btree_visit_blocks_fn fn,
+ void *data)
+{
+ struct xfs_btree_block *block;
+ struct xfs_buf *bp;
+ union xfs_btree_ptr rptr;
+ int error;
+
+ /* do right sibling readahead */
+ xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
+ block = xfs_btree_get_block(cur, level, &bp);
+
+ /* process the block */
+ error = fn(cur, level, data);
+ if (error)
+ return error;
+
+ /* now read rh sibling block for next iteration */
+ xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
+ if (xfs_btree_ptr_is_null(cur, &rptr))
+ return -ENOENT;
+
+ return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
+}
+
+
+/* Visit every block in a btree. */
+int
+xfs_btree_visit_blocks(
+ struct xfs_btree_cur *cur,
+ xfs_btree_visit_blocks_fn fn,
+ void *data)
+{
+ union xfs_btree_ptr lptr;
+ int level;
+ struct xfs_btree_block *block = NULL;
+ int error = 0;
+
+ cur->bc_ops->init_ptr_from_cur(cur, &lptr);
+
+ /* for each level */
+ for (level = cur->bc_nlevels - 1; level >= 0; level--) {
+ /* grab the left hand block */
+ error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
+ if (error)
+ return error;
+
+ /* readahead the left most block for the next level down */
+ if (level > 0) {
+ union xfs_btree_ptr *ptr;
+
+ ptr = xfs_btree_ptr_addr(cur, 1, block);
+ xfs_btree_readahead_ptr(cur, ptr, 1);
+
+ /* save for the next iteration of the loop */
+ lptr = *ptr;
+ }
+
+ /* for each buffer in the level */
+ do {
+ error = xfs_btree_visit_block(cur, level, fn, data);
+ } while (!error);
+
+ if (error != -ENOENT)
+ return error;
+ }
+
+ return 0;
+}
+
/*
* Change the owner of a btree.
*
@@ -4002,26 +4386,27 @@ xfs_btree_get_rec(
* just queue the modified buffer as delayed write buffer so the transaction
* recovery completion writes the changes to disk.
*/
+struct xfs_btree_block_change_owner_info {
+ __uint64_t new_owner;
+ struct list_head *buffer_list;
+};
+
static int
xfs_btree_block_change_owner(
struct xfs_btree_cur *cur,
int level,
- __uint64_t new_owner,
- struct list_head *buffer_list)
+ void *data)
{
+ struct xfs_btree_block_change_owner_info *bbcoi = data;
struct xfs_btree_block *block;
struct xfs_buf *bp;
- union xfs_btree_ptr rptr;
-
- /* do right sibling readahead */
- xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
/* modify the owner */
block = xfs_btree_get_block(cur, level, &bp);
if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
- block->bb_u.l.bb_owner = cpu_to_be64(new_owner);
+ block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner);
else
- block->bb_u.s.bb_owner = cpu_to_be32(new_owner);
+ block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner);
/*
* If the block is a root block hosted in an inode, we might not have a
@@ -4035,19 +4420,14 @@ xfs_btree_block_change_owner(
xfs_trans_ordered_buf(cur->bc_tp, bp);
xfs_btree_log_block(cur, bp, XFS_BB_OWNER);
} else {
- xfs_buf_delwri_queue(bp, buffer_list);
+ xfs_buf_delwri_queue(bp, bbcoi->buffer_list);
}
} else {
ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
ASSERT(level == cur->bc_nlevels - 1);
}
- /* now read rh sibling block for next iteration */
- xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
- if (xfs_btree_ptr_is_null(cur, &rptr))
- return -ENOENT;
-
- return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
+ return 0;
}
int
@@ -4056,43 +4436,13 @@ xfs_btree_change_owner(
__uint64_t new_owner,
struct list_head *buffer_list)
{
- union xfs_btree_ptr lptr;
- int level;
- struct xfs_btree_block *block = NULL;
- int error = 0;
-
- cur->bc_ops->init_ptr_from_cur(cur, &lptr);
-
- /* for each level */
- for (level = cur->bc_nlevels - 1; level >= 0; level--) {
- /* grab the left hand block */
- error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
- if (error)
- return error;
-
- /* readahead the left most block for the next level down */
- if (level > 0) {
- union xfs_btree_ptr *ptr;
-
- ptr = xfs_btree_ptr_addr(cur, 1, block);
- xfs_btree_readahead_ptr(cur, ptr, 1);
-
- /* save for the next iteration of the loop */
- lptr = *ptr;
- }
-
- /* for each buffer in the level */
- do {
- error = xfs_btree_block_change_owner(cur, level,
- new_owner,
- buffer_list);
- } while (!error);
+ struct xfs_btree_block_change_owner_info bbcoi;
- if (error != -ENOENT)
- return error;
- }
+ bbcoi.new_owner = new_owner;
+ bbcoi.buffer_list = buffer_list;
- return 0;
+ return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner,
+ &bbcoi);
}
/**
@@ -4171,3 +4521,267 @@ xfs_btree_compute_maxlevels(
maxblocks = (maxblocks + limits[1] - 1) / limits[1];
return level;
}
+
+/*
+ * Query a regular btree for all records overlapping a given interval.
+ * Start with a LE lookup of the key of low_rec and return all records
+ * until we find a record with a key greater than the key of high_rec.
+ */
+STATIC int
+xfs_btree_simple_query_range(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *low_key,
+ union xfs_btree_key *high_key,
+ xfs_btree_query_range_fn fn,
+ void *priv)
+{
+ union xfs_btree_rec *recp;
+ union xfs_btree_key rec_key;
+ __int64_t diff;
+ int stat;
+ bool firstrec = true;
+ int error;
+
+ ASSERT(cur->bc_ops->init_high_key_from_rec);
+ ASSERT(cur->bc_ops->diff_two_keys);
+
+ /*
+ * Find the leftmost record. The btree cursor must be set
+ * to the low record used to generate low_key.
+ */
+ stat = 0;
+ error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat);
+ if (error)
+ goto out;
+
+ while (stat) {
+ /* Find the record. */
+ error = xfs_btree_get_rec(cur, &recp, &stat);
+ if (error || !stat)
+ break;
+ cur->bc_ops->init_high_key_from_rec(&rec_key, recp);
+
+ /* Skip if high_key(rec) < low_key. */
+ if (firstrec) {
+ firstrec = false;
+ diff = cur->bc_ops->diff_two_keys(cur, low_key,
+ &rec_key);
+ if (diff > 0)
+ goto advloop;
+ }
+
+ /* Stop if high_key < low_key(rec). */
+ diff = cur->bc_ops->diff_two_keys(cur, &rec_key, high_key);
+ if (diff > 0)
+ break;
+
+ /* Callback */
+ error = fn(cur, recp, priv);
+ if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT)
+ break;
+
+advloop:
+ /* Move on to the next record. */
+ error = xfs_btree_increment(cur, 0, &stat);
+ if (error)
+ break;
+ }
+
+out:
+ return error;
+}
+
+/*
+ * Query an overlapped interval btree for all records overlapping a given
+ * interval. This function roughly follows the algorithm given in
+ * "Interval Trees" of _Introduction to Algorithms_, which is section
+ * 14.3 in the 2nd and 3rd editions.
+ *
+ * First, generate keys for the low and high records passed in.
+ *
+ * For any leaf node, generate the high and low keys for the record.
+ * If the record keys overlap with the query low/high keys, pass the
+ * record to the function iterator.
+ *
+ * For any internal node, compare the low and high keys of each
+ * pointer against the query low/high keys. If there's an overlap,
+ * follow the pointer.
+ *
+ * As an optimization, we stop scanning a block when we find a low key
+ * that is greater than the query's high key.
+ */
+STATIC int
+xfs_btree_overlapped_query_range(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *low_key,
+ union xfs_btree_key *high_key,
+ xfs_btree_query_range_fn fn,
+ void *priv)
+{
+ union xfs_btree_ptr ptr;
+ union xfs_btree_ptr *pp;
+ union xfs_btree_key rec_key;
+ union xfs_btree_key rec_hkey;
+ union xfs_btree_key *lkp;
+ union xfs_btree_key *hkp;
+ union xfs_btree_rec *recp;
+ struct xfs_btree_block *block;
+ __int64_t ldiff;
+ __int64_t hdiff;
+ int level;
+ struct xfs_buf *bp;
+ int i;
+ int error;
+
+ /* Load the root of the btree. */
+ level = cur->bc_nlevels - 1;
+ cur->bc_ops->init_ptr_from_cur(cur, &ptr);
+ error = xfs_btree_lookup_get_block(cur, level, &ptr, &block);
+ if (error)
+ return error;
+ xfs_btree_get_block(cur, level, &bp);
+ trace_xfs_btree_overlapped_query_range(cur, level, bp);
+#ifdef DEBUG
+ error = xfs_btree_check_block(cur, block, level, bp);
+ if (error)
+ goto out;
+#endif
+ cur->bc_ptrs[level] = 1;
+
+ while (level < cur->bc_nlevels) {
+ block = xfs_btree_get_block(cur, level, &bp);
+
+ /* End of node, pop back towards the root. */
+ if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) {
+pop_up:
+ if (level < cur->bc_nlevels - 1)
+ cur->bc_ptrs[level + 1]++;
+ level++;
+ continue;
+ }
+
+ if (level == 0) {
+ /* Handle a leaf node. */
+ recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
+
+ cur->bc_ops->init_high_key_from_rec(&rec_hkey, recp);
+ ldiff = cur->bc_ops->diff_two_keys(cur, &rec_hkey,
+ low_key);
+
+ cur->bc_ops->init_key_from_rec(&rec_key, recp);
+ hdiff = cur->bc_ops->diff_two_keys(cur, high_key,
+ &rec_key);
+
+ /*
+ * If (record's high key >= query's low key) and
+ * (query's high key >= record's low key), then
+ * this record overlaps the query range; callback.
+ */
+ if (ldiff >= 0 && hdiff >= 0) {
+ error = fn(cur, recp, priv);
+ if (error < 0 ||
+ error == XFS_BTREE_QUERY_RANGE_ABORT)
+ break;
+ } else if (hdiff < 0) {
+ /* Record is larger than high key; pop. */
+ goto pop_up;
+ }
+ cur->bc_ptrs[level]++;
+ continue;
+ }
+
+ /* Handle an internal node. */
+ lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block);
+ hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block);
+ pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block);
+
+ ldiff = cur->bc_ops->diff_two_keys(cur, hkp, low_key);
+ hdiff = cur->bc_ops->diff_two_keys(cur, high_key, lkp);
+
+ /*
+ * If (pointer's high key >= query's low key) and
+ * (query's high key >= pointer's low key), then
+ * this record overlaps the query range; follow pointer.
+ */
+ if (ldiff >= 0 && hdiff >= 0) {
+ level--;
+ error = xfs_btree_lookup_get_block(cur, level, pp,
+ &block);
+ if (error)
+ goto out;
+ xfs_btree_get_block(cur, level, &bp);
+ trace_xfs_btree_overlapped_query_range(cur, level, bp);
+#ifdef DEBUG
+ error = xfs_btree_check_block(cur, block, level, bp);
+ if (error)
+ goto out;
+#endif
+ cur->bc_ptrs[level] = 1;
+ continue;
+ } else if (hdiff < 0) {
+ /* The low key is larger than the upper range; pop. */
+ goto pop_up;
+ }
+ cur->bc_ptrs[level]++;
+ }
+
+out:
+ /*
+ * If we don't end this function with the cursor pointing at a record
+ * block, a subsequent non-error cursor deletion will not release
+ * node-level buffers, causing a buffer leak. This is quite possible
+ * with a zero-results range query, so release the buffers if we
+ * failed to return any results.
+ */
+ if (cur->bc_bufs[0] == NULL) {
+ for (i = 0; i < cur->bc_nlevels; i++) {
+ if (cur->bc_bufs[i]) {
+ xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]);
+ cur->bc_bufs[i] = NULL;
+ cur->bc_ptrs[i] = 0;
+ cur->bc_ra[i] = 0;
+ }
+ }
+ }
+
+ return error;
+}
+
+/*
+ * Query a btree for all records overlapping a given interval of keys. The
+ * supplied function will be called with each record found; return one of the
+ * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error
+ * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a
+ * negative error code.
+ */
+int
+xfs_btree_query_range(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_irec *low_rec,
+ union xfs_btree_irec *high_rec,
+ xfs_btree_query_range_fn fn,
+ void *priv)
+{
+ union xfs_btree_rec rec;
+ union xfs_btree_key low_key;
+ union xfs_btree_key high_key;
+
+ /* Find the keys of both ends of the interval. */
+ cur->bc_rec = *high_rec;
+ cur->bc_ops->init_rec_from_cur(cur, &rec);
+ cur->bc_ops->init_key_from_rec(&high_key, &rec);
+
+ cur->bc_rec = *low_rec;
+ cur->bc_ops->init_rec_from_cur(cur, &rec);
+ cur->bc_ops->init_key_from_rec(&low_key, &rec);
+
+ /* Enforce low key < high key. */
+ if (cur->bc_ops->diff_two_keys(cur, &low_key, &high_key) > 0)
+ return -EINVAL;
+
+ if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
+ return xfs_btree_simple_query_range(cur, &low_key,
+ &high_key, fn, priv);
+ return xfs_btree_overlapped_query_range(cur, &low_key, &high_key,
+ fn, priv);
+}
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 785a99682159..04d0865e5e6d 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -19,7 +19,7 @@
#define __XFS_BTREE_H__
struct xfs_buf;
-struct xfs_bmap_free;
+struct xfs_defer_ops;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
@@ -38,17 +38,37 @@ union xfs_btree_ptr {
};
union xfs_btree_key {
- xfs_bmbt_key_t bmbt;
- xfs_bmdr_key_t bmbr; /* bmbt root block */
- xfs_alloc_key_t alloc;
- xfs_inobt_key_t inobt;
+ struct xfs_bmbt_key bmbt;
+ xfs_bmdr_key_t bmbr; /* bmbt root block */
+ xfs_alloc_key_t alloc;
+ struct xfs_inobt_key inobt;
+ struct xfs_rmap_key rmap;
+};
+
+/*
+ * In-core key that holds both low and high keys for overlapped btrees.
+ * The two keys are packed next to each other on disk, so do the same
+ * in memory. Preserve the existing xfs_btree_key as a single key to
+ * avoid the mental model breakage that would happen if we passed a
+ * bigkey into a function that operates on a single key.
+ */
+union xfs_btree_bigkey {
+ struct xfs_bmbt_key bmbt;
+ xfs_bmdr_key_t bmbr; /* bmbt root block */
+ xfs_alloc_key_t alloc;
+ struct xfs_inobt_key inobt;
+ struct {
+ struct xfs_rmap_key rmap;
+ struct xfs_rmap_key rmap_hi;
+ };
};
union xfs_btree_rec {
- xfs_bmbt_rec_t bmbt;
- xfs_bmdr_rec_t bmbr; /* bmbt root block */
- xfs_alloc_rec_t alloc;
- xfs_inobt_rec_t inobt;
+ struct xfs_bmbt_rec bmbt;
+ xfs_bmdr_rec_t bmbr; /* bmbt root block */
+ struct xfs_alloc_rec alloc;
+ struct xfs_inobt_rec inobt;
+ struct xfs_rmap_rec rmap;
};
/*
@@ -63,6 +83,7 @@ union xfs_btree_rec {
#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi)
#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
#define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi)
+#define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi)
/*
* For logging record fields.
@@ -95,6 +116,7 @@ do { \
case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \
case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \
case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \
+ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \
case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
} \
} while (0)
@@ -115,11 +137,13 @@ do { \
__XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \
case XFS_BTNUM_FINO: \
__XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \
+ case XFS_BTNUM_RMAP: \
+ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \
case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \
} \
} while (0)
-#define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */
+#define XFS_BTREE_MAXLEVELS 9 /* max of all btrees */
struct xfs_btree_ops {
/* size of the key and record structures */
@@ -158,17 +182,25 @@ struct xfs_btree_ops {
/* init values of btree structures */
void (*init_key_from_rec)(union xfs_btree_key *key,
union xfs_btree_rec *rec);
- void (*init_rec_from_key)(union xfs_btree_key *key,
- union xfs_btree_rec *rec);
void (*init_rec_from_cur)(struct xfs_btree_cur *cur,
union xfs_btree_rec *rec);
void (*init_ptr_from_cur)(struct xfs_btree_cur *cur,
union xfs_btree_ptr *ptr);
+ void (*init_high_key_from_rec)(union xfs_btree_key *key,
+ union xfs_btree_rec *rec);
/* difference between key value and cursor value */
__int64_t (*key_diff)(struct xfs_btree_cur *cur,
union xfs_btree_key *key);
+ /*
+ * Difference between key2 and key1 -- positive if key1 > key2,
+ * negative if key1 < key2, and zero if equal.
+ */
+ __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur,
+ union xfs_btree_key *key1,
+ union xfs_btree_key *key2);
+
const struct xfs_buf_ops *buf_ops;
#if defined(DEBUG) || defined(XFS_WARN)
@@ -192,6 +224,13 @@ struct xfs_btree_ops {
#define LASTREC_DELREC 2
+union xfs_btree_irec {
+ struct xfs_alloc_rec_incore a;
+ struct xfs_bmbt_irec b;
+ struct xfs_inobt_rec_incore i;
+ struct xfs_rmap_irec r;
+};
+
/*
* Btree cursor structure.
* This collects all information needed by the btree code in one place.
@@ -202,11 +241,7 @@ typedef struct xfs_btree_cur
struct xfs_mount *bc_mp; /* file system mount struct */
const struct xfs_btree_ops *bc_ops;
uint bc_flags; /* btree features - below */
- union {
- xfs_alloc_rec_incore_t a;
- xfs_bmbt_irec_t b;
- xfs_inobt_rec_incore_t i;
- } bc_rec; /* current insert/search record value */
+ union xfs_btree_irec bc_rec; /* current insert/search record value */
struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */
int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */
__uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */
@@ -218,11 +253,12 @@ typedef struct xfs_btree_cur
union {
struct { /* needed for BNO, CNT, INO */
struct xfs_buf *agbp; /* agf/agi buffer pointer */
+ struct xfs_defer_ops *dfops; /* deferred updates */
xfs_agnumber_t agno; /* ag number */
} a;
struct { /* needed for BMAP */
struct xfs_inode *ip; /* pointer to our inode */
- struct xfs_bmap_free *flist; /* list to free after */
+ struct xfs_defer_ops *dfops; /* deferred updates */
xfs_fsblock_t firstblock; /* 1st blk allocated */
int allocated; /* count of alloced */
short forksize; /* fork's inode space */
@@ -238,6 +274,7 @@ typedef struct xfs_btree_cur
#define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */
#define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */
#define XFS_BTREE_CRC_BLOCKS (1<<3) /* uses extended btree blocks */
+#define XFS_BTREE_OVERLAPPING (1<<4) /* overlapping intervals */
#define XFS_BTREE_NOERROR 0
@@ -477,4 +514,19 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs);
uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits,
unsigned long len);
+/* return codes */
+#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */
+#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */
+typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec, void *priv);
+
+int xfs_btree_query_range(struct xfs_btree_cur *cur,
+ union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec,
+ xfs_btree_query_range_fn fn, void *priv);
+
+typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
+ void *data);
+int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
+ xfs_btree_visit_blocks_fn fn, void *data);
+
#endif /* __XFS_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index 0f1f165f4048..f2dc1a950c85 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -2029,7 +2029,7 @@ xfs_da_grow_inode_int(
error = xfs_bmapi_write(tp, dp, *bno, count,
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
args->firstblock, args->total, &map, &nmap,
- args->flist);
+ args->dfops);
if (error)
return error;
@@ -2052,7 +2052,7 @@ xfs_da_grow_inode_int(
error = xfs_bmapi_write(tp, dp, b, c,
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
args->firstblock, args->total,
- &mapp[mapi], &nmap, args->flist);
+ &mapp[mapi], &nmap, args->dfops);
if (error)
goto out_free_map;
if (nmap < 1)
@@ -2362,7 +2362,7 @@ xfs_da_shrink_inode(
*/
error = xfs_bunmapi(tp, dp, dead_blkno, count,
xfs_bmapi_aflag(w), 0, args->firstblock,
- args->flist, &done);
+ args->dfops, &done);
if (error == -ENOSPC) {
if (w != XFS_DATA_FORK)
break;
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index 6e153e399a77..98c75cbe6ac2 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -19,7 +19,7 @@
#ifndef __XFS_DA_BTREE_H__
#define __XFS_DA_BTREE_H__
-struct xfs_bmap_free;
+struct xfs_defer_ops;
struct xfs_inode;
struct xfs_trans;
struct zone;
@@ -70,7 +70,7 @@ typedef struct xfs_da_args {
xfs_ino_t inumber; /* input/output inode number */
struct xfs_inode *dp; /* directory inode to manipulate */
xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */
- struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */
+ struct xfs_defer_ops *dfops; /* ptr to freelist for bmap_finish */
struct xfs_trans *trans; /* current trans (changes over time) */
xfs_extlen_t total; /* total blocks needed, for 1st bmap */
int whichfork; /* data or attribute fork */
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 685f23b67056..9a492a9e19bd 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -629,6 +629,7 @@ typedef struct xfs_attr_shortform {
struct xfs_attr_sf_hdr { /* constant-structure header block */
__be16 totsize; /* total bytes in shortform list */
__u8 count; /* count of active entries */
+ __u8 padding;
} hdr;
struct xfs_attr_sf_entry {
__uint8_t namelen; /* actual length of name (no NULL) */
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
new file mode 100644
index 000000000000..054a2032fdb3
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_trans.h"
+#include "xfs_trace.h"
+
+/*
+ * Deferred Operations in XFS
+ *
+ * Due to the way locking rules work in XFS, certain transactions (block
+ * mapping and unmapping, typically) have permanent reservations so that
+ * we can roll the transaction to adhere to AG locking order rules and
+ * to unlock buffers between metadata updates. Prior to rmap/reflink,
+ * the mapping code had a mechanism to perform these deferrals for
+ * extents that were going to be freed; this code makes that facility
+ * more generic.
+ *
+ * When adding the reverse mapping and reflink features, it became
+ * necessary to perform complex remapping multi-transactions to comply
+ * with AG locking order rules, and to be able to spread a single
+ * refcount update operation (an operation on an n-block extent can
+ * update as many as n records!) among multiple transactions. XFS can
+ * roll a transaction to facilitate this, but using this facility
+ * requires us to log "intent" items in case log recovery needs to
+ * redo the operation, and to log "done" items to indicate that redo
+ * is not necessary.
+ *
+ * Deferred work is tracked in xfs_defer_pending items. Each pending
+ * item tracks one type of deferred work. Incoming work items (which
+ * have not yet had an intent logged) are attached to a pending item
+ * on the dop_intake list, where they wait for the caller to finish
+ * the deferred operations.
+ *
+ * Finishing a set of deferred operations is an involved process. To
+ * start, we define "rolling a deferred-op transaction" as follows:
+ *
+ * > For each xfs_defer_pending item on the dop_intake list,
+ * - Sort the work items in AG order. XFS locking
+ * order rules require us to lock buffers in AG order.
+ * - Create a log intent item for that type.
+ * - Attach it to the pending item.
+ * - Move the pending item from the dop_intake list to the
+ * dop_pending list.
+ * > Roll the transaction.
+ *
+ * NOTE: To avoid exceeding the transaction reservation, we limit the
+ * number of items that we attach to a given xfs_defer_pending.
+ *
+ * The actual finishing process looks like this:
+ *
+ * > For each xfs_defer_pending in the dop_pending list,
+ * - Roll the deferred-op transaction as above.
+ * - Create a log done item for that type, and attach it to the
+ * log intent item.
+ * - For each work item attached to the log intent item,
+ * * Perform the described action.
+ * * Attach the work item to the log done item.
+ *
+ * The key here is that we must log an intent item for all pending
+ * work items every time we roll the transaction, and that we must log
+ * a done item as soon as the work is completed. With this mechanism
+ * we can perform complex remapping operations, chaining intent items
+ * as needed.
+ *
+ * This is an example of remapping the extent (E, E+B) into file X at
+ * offset A and dealing with the extent (C, C+B) already being mapped
+ * there:
+ * +-------------------------------------------------+
+ * | Unmap file X startblock C offset A length B | t0
+ * | Intent to reduce refcount for extent (C, B) |
+ * | Intent to remove rmap (X, C, A, B) |
+ * | Intent to free extent (D, 1) (bmbt block) |
+ * | Intent to map (X, A, B) at startblock E |
+ * +-------------------------------------------------+
+ * | Map file X startblock E offset A length B | t1
+ * | Done mapping (X, E, A, B) |
+ * | Intent to increase refcount for extent (E, B) |
+ * | Intent to add rmap (X, E, A, B) |
+ * +-------------------------------------------------+
+ * | Reduce refcount for extent (C, B) | t2
+ * | Done reducing refcount for extent (C, B) |
+ * | Increase refcount for extent (E, B) |
+ * | Done increasing refcount for extent (E, B) |
+ * | Intent to free extent (C, B) |
+ * | Intent to free extent (F, 1) (refcountbt block) |
+ * | Intent to remove rmap (F, 1, REFC) |
+ * +-------------------------------------------------+
+ * | Remove rmap (X, C, A, B) | t3
+ * | Done removing rmap (X, C, A, B) |
+ * | Add rmap (X, E, A, B) |
+ * | Done adding rmap (X, E, A, B) |
+ * | Remove rmap (F, 1, REFC) |
+ * | Done removing rmap (F, 1, REFC) |
+ * +-------------------------------------------------+
+ * | Free extent (C, B) | t4
+ * | Done freeing extent (C, B) |
+ * | Free extent (D, 1) |
+ * | Done freeing extent (D, 1) |
+ * | Free extent (F, 1) |
+ * | Done freeing extent (F, 1) |
+ * +-------------------------------------------------+
+ *
+ * If we should crash before t2 commits, log recovery replays
+ * the following intent items:
+ *
+ * - Intent to reduce refcount for extent (C, B)
+ * - Intent to remove rmap (X, C, A, B)
+ * - Intent to free extent (D, 1) (bmbt block)
+ * - Intent to increase refcount for extent (E, B)
+ * - Intent to add rmap (X, E, A, B)
+ *
+ * In the process of recovering, it should also generate and take care
+ * of these intent items:
+ *
+ * - Intent to free extent (C, B)
+ * - Intent to free extent (F, 1) (refcountbt block)
+ * - Intent to remove rmap (F, 1, REFC)
+ */
+
+static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX];
+
+/*
+ * For each pending item in the intake list, log its intent item and the
+ * associated extents, then add the entire intake list to the end of
+ * the pending list.
+ */
+STATIC void
+xfs_defer_intake_work(
+ struct xfs_trans *tp,
+ struct xfs_defer_ops *dop)
+{
+ struct list_head *li;
+ struct xfs_defer_pending *dfp;
+
+ list_for_each_entry(dfp, &dop->dop_intake, dfp_list) {
+ trace_xfs_defer_intake_work(tp->t_mountp, dfp);
+ dfp->dfp_intent = dfp->dfp_type->create_intent(tp,
+ dfp->dfp_count);
+ list_sort(tp->t_mountp, &dfp->dfp_work,
+ dfp->dfp_type->diff_items);
+ list_for_each(li, &dfp->dfp_work)
+ dfp->dfp_type->log_item(tp, dfp->dfp_intent, li);
+ }
+
+ list_splice_tail_init(&dop->dop_intake, &dop->dop_pending);
+}
+
+/* Abort all the intents that were committed. */
+STATIC void
+xfs_defer_trans_abort(
+ struct xfs_trans *tp,
+ struct xfs_defer_ops *dop,
+ int error)
+{
+ struct xfs_defer_pending *dfp;
+
+ trace_xfs_defer_trans_abort(tp->t_mountp, dop);
+ /*
+ * If the transaction was committed, drop the intent reference
+ * since we're bailing out of here. The other reference is
+ * dropped when the intent hits the AIL. If the transaction
+ * was not committed, the intent is freed by the intent item
+ * unlock handler on abort.
+ */
+ if (!dop->dop_committed)
+ return;
+
+ /* Abort intent items. */
+ list_for_each_entry(dfp, &dop->dop_pending, dfp_list) {
+ trace_xfs_defer_pending_abort(tp->t_mountp, dfp);
+ if (dfp->dfp_committed)
+ dfp->dfp_type->abort_intent(dfp->dfp_intent);
+ }
+
+ /* Shut down FS. */
+ xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ?
+ SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR);
+}
+
+/* Roll a transaction so we can do some deferred op processing. */
+STATIC int
+xfs_defer_trans_roll(
+ struct xfs_trans **tp,
+ struct xfs_defer_ops *dop,
+ struct xfs_inode *ip)
+{
+ int i;
+ int error;
+
+ /* Log all the joined inodes except the one we passed in. */
+ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) {
+ if (dop->dop_inodes[i] == ip)
+ continue;
+ xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE);
+ }
+
+ trace_xfs_defer_trans_roll((*tp)->t_mountp, dop);
+
+ /* Roll the transaction. */
+ error = xfs_trans_roll(tp, ip);
+ if (error) {
+ trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error);
+ xfs_defer_trans_abort(*tp, dop, error);
+ return error;
+ }
+ dop->dop_committed = true;
+
+ /* Rejoin the joined inodes except the one we passed in. */
+ for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) {
+ if (dop->dop_inodes[i] == ip)
+ continue;
+ xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0);
+ }
+
+ return error;
+}
+
+/* Do we have any work items to finish? */
+bool
+xfs_defer_has_unfinished_work(
+ struct xfs_defer_ops *dop)
+{
+ return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake);
+}
+
+/*
+ * Add this inode to the deferred op. Each joined inode is relogged
+ * each time we roll the transaction, in addition to any inode passed
+ * to xfs_defer_finish().
+ */
+int
+xfs_defer_join(
+ struct xfs_defer_ops *dop,
+ struct xfs_inode *ip)
+{
+ int i;
+
+ for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) {
+ if (dop->dop_inodes[i] == ip)
+ return 0;
+ else if (dop->dop_inodes[i] == NULL) {
+ dop->dop_inodes[i] = ip;
+ return 0;
+ }
+ }
+
+ return -EFSCORRUPTED;
+}
+
+/*
+ * Finish all the pending work. This involves logging intent items for
+ * any work items that wandered in since the last transaction roll (if
+ * one has even happened), rolling the transaction, and finishing the
+ * work items in the first item on the logged-and-pending list.
+ *
+ * If an inode is provided, relog it to the new transaction.
+ */
+int
+xfs_defer_finish(
+ struct xfs_trans **tp,
+ struct xfs_defer_ops *dop,
+ struct xfs_inode *ip)
+{
+ struct xfs_defer_pending *dfp;
+ struct list_head *li;
+ struct list_head *n;
+ void *done_item = NULL;
+ void *state;
+ int error = 0;
+ void (*cleanup_fn)(struct xfs_trans *, void *, int);
+
+ ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
+
+ trace_xfs_defer_finish((*tp)->t_mountp, dop);
+
+ /* Until we run out of pending work to finish... */
+ while (xfs_defer_has_unfinished_work(dop)) {
+ /* Log intents for work items sitting in the intake. */
+ xfs_defer_intake_work(*tp, dop);
+
+ /* Roll the transaction. */
+ error = xfs_defer_trans_roll(tp, dop, ip);
+ if (error)
+ goto out;
+
+ /* Mark all pending intents as committed. */
+ list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) {
+ if (dfp->dfp_committed)
+ break;
+ trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp);
+ dfp->dfp_committed = true;
+ }
+
+ /* Log an intent-done item for the first pending item. */
+ dfp = list_first_entry(&dop->dop_pending,
+ struct xfs_defer_pending, dfp_list);
+ trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp);
+ done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent,
+ dfp->dfp_count);
+ cleanup_fn = dfp->dfp_type->finish_cleanup;
+
+ /* Finish the work items. */
+ state = NULL;
+ list_for_each_safe(li, n, &dfp->dfp_work) {
+ list_del(li);
+ dfp->dfp_count--;
+ error = dfp->dfp_type->finish_item(*tp, dop, li,
+ done_item, &state);
+ if (error) {
+ /*
+ * Clean up after ourselves and jump out.
+ * xfs_defer_cancel will take care of freeing
+ * all these lists and stuff.
+ */
+ if (cleanup_fn)
+ cleanup_fn(*tp, state, error);
+ xfs_defer_trans_abort(*tp, dop, error);
+ goto out;
+ }
+ }
+ /* Done with the dfp, free it. */
+ list_del(&dfp->dfp_list);
+ kmem_free(dfp);
+
+ if (cleanup_fn)
+ cleanup_fn(*tp, state, error);
+ }
+
+out:
+ if (error)
+ trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error);
+ else
+ trace_xfs_defer_finish_done((*tp)->t_mountp, dop);
+ return error;
+}
+
+/*
+ * Free up any items left in the list.
+ */
+void
+xfs_defer_cancel(
+ struct xfs_defer_ops *dop)
+{
+ struct xfs_defer_pending *dfp;
+ struct xfs_defer_pending *pli;
+ struct list_head *pwi;
+ struct list_head *n;
+
+ trace_xfs_defer_cancel(NULL, dop);
+
+ /*
+ * Free the pending items. Caller should already have arranged
+ * for the intent items to be released.
+ */
+ list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) {
+ trace_xfs_defer_intake_cancel(NULL, dfp);
+ list_del(&dfp->dfp_list);
+ list_for_each_safe(pwi, n, &dfp->dfp_work) {
+ list_del(pwi);
+ dfp->dfp_count--;
+ dfp->dfp_type->cancel_item(pwi);
+ }
+ ASSERT(dfp->dfp_count == 0);
+ kmem_free(dfp);
+ }
+ list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) {
+ trace_xfs_defer_pending_cancel(NULL, dfp);
+ list_del(&dfp->dfp_list);
+ list_for_each_safe(pwi, n, &dfp->dfp_work) {
+ list_del(pwi);
+ dfp->dfp_count--;
+ dfp->dfp_type->cancel_item(pwi);
+ }
+ ASSERT(dfp->dfp_count == 0);
+ kmem_free(dfp);
+ }
+}
+
+/* Add an item for later deferred processing. */
+void
+xfs_defer_add(
+ struct xfs_defer_ops *dop,
+ enum xfs_defer_ops_type type,
+ struct list_head *li)
+{
+ struct xfs_defer_pending *dfp = NULL;
+
+ /*
+ * Add the item to a pending item at the end of the intake list.
+ * If the last pending item has the same type, reuse it. Else,
+ * create a new pending item at the end of the intake list.
+ */
+ if (!list_empty(&dop->dop_intake)) {
+ dfp = list_last_entry(&dop->dop_intake,
+ struct xfs_defer_pending, dfp_list);
+ if (dfp->dfp_type->type != type ||
+ (dfp->dfp_type->max_items &&
+ dfp->dfp_count >= dfp->dfp_type->max_items))
+ dfp = NULL;
+ }
+ if (!dfp) {
+ dfp = kmem_alloc(sizeof(struct xfs_defer_pending),
+ KM_SLEEP | KM_NOFS);
+ dfp->dfp_type = defer_op_types[type];
+ dfp->dfp_committed = false;
+ dfp->dfp_intent = NULL;
+ dfp->dfp_count = 0;
+ INIT_LIST_HEAD(&dfp->dfp_work);
+ list_add_tail(&dfp->dfp_list, &dop->dop_intake);
+ }
+
+ list_add_tail(li, &dfp->dfp_work);
+ dfp->dfp_count++;
+}
+
+/* Initialize a deferred operation list. */
+void
+xfs_defer_init_op_type(
+ const struct xfs_defer_op_type *type)
+{
+ defer_op_types[type->type] = type;
+}
+
+/* Initialize a deferred operation. */
+void
+xfs_defer_init(
+ struct xfs_defer_ops *dop,
+ xfs_fsblock_t *fbp)
+{
+ dop->dop_committed = false;
+ dop->dop_low = false;
+ memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes));
+ *fbp = NULLFSBLOCK;
+ INIT_LIST_HEAD(&dop->dop_intake);
+ INIT_LIST_HEAD(&dop->dop_pending);
+ trace_xfs_defer_init(NULL, dop);
+}
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
new file mode 100644
index 000000000000..cc3981c48296
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __XFS_DEFER_H__
+#define __XFS_DEFER_H__
+
+struct xfs_defer_op_type;
+
+/*
+ * Save a log intent item and a list of extents, so that we can replay
+ * whatever action had to happen to the extent list and file the log done
+ * item.
+ */
+struct xfs_defer_pending {
+ const struct xfs_defer_op_type *dfp_type; /* function pointers */
+ struct list_head dfp_list; /* pending items */
+ bool dfp_committed; /* committed trans? */
+ void *dfp_intent; /* log intent item */
+ struct list_head dfp_work; /* work items */
+ unsigned int dfp_count; /* # extent items */
+};
+
+/*
+ * Header for deferred operation list.
+ *
+ * dop_low is used by the allocator to activate the lowspace algorithm -
+ * when free space is running low the extent allocator may choose to
+ * allocate an extent from an AG without leaving sufficient space for
+ * a btree split when inserting the new extent. In this case the allocator
+ * will enable the lowspace algorithm which is supposed to allow further
+ * allocations (such as btree splits and newroots) to allocate from
+ * sequential AGs. In order to avoid locking AGs out of order the lowspace
+ * algorithm will start searching for free space from AG 0. If the correct
+ * transaction reservations have been made then this algorithm will eventually
+ * find all the space it needs.
+ */
+enum xfs_defer_ops_type {
+ XFS_DEFER_OPS_TYPE_RMAP,
+ XFS_DEFER_OPS_TYPE_FREE,
+ XFS_DEFER_OPS_TYPE_MAX,
+};
+
+#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */
+
+struct xfs_defer_ops {
+ bool dop_committed; /* did any trans commit? */
+ bool dop_low; /* alloc in low mode */
+ struct list_head dop_intake; /* unlogged pending work */
+ struct list_head dop_pending; /* logged pending work */
+
+ /* relog these inodes with each roll */
+ struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES];
+};
+
+void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type,
+ struct list_head *h);
+int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop,
+ struct xfs_inode *ip);
+void xfs_defer_cancel(struct xfs_defer_ops *dop);
+void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp);
+bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);
+int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip);
+
+/* Description of a deferred type. */
+struct xfs_defer_op_type {
+ enum xfs_defer_ops_type type;
+ unsigned int max_items;
+ void (*abort_intent)(void *);
+ void *(*create_done)(struct xfs_trans *, void *, unsigned int);
+ int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *,
+ struct list_head *, void *, void **);
+ void (*finish_cleanup)(struct xfs_trans *, void *, int);
+ void (*cancel_item)(struct list_head *);
+ int (*diff_items)(void *, struct list_head *, struct list_head *);
+ void *(*create_intent)(struct xfs_trans *, uint);
+ void (*log_item)(struct xfs_trans *, void *, struct list_head *);
+};
+
+void xfs_defer_init_op_type(const struct xfs_defer_op_type *type);
+
+#endif /* __XFS_DEFER_H__ */
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index af0f9d171f8a..20a96dd5af7e 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -21,6 +21,7 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_inode.h"
@@ -259,7 +260,7 @@ xfs_dir_createname(
struct xfs_name *name,
xfs_ino_t inum, /* new entry inode number */
xfs_fsblock_t *first, /* bmap's firstblock */
- xfs_bmap_free_t *flist, /* bmap's freeblock list */
+ struct xfs_defer_ops *dfops, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
struct xfs_da_args *args;
@@ -286,7 +287,7 @@ xfs_dir_createname(
args->inumber = inum;
args->dp = dp;
args->firstblock = first;
- args->flist = flist;
+ args->dfops = dfops;
args->total = total;
args->whichfork = XFS_DATA_FORK;
args->trans = tp;
@@ -436,7 +437,7 @@ xfs_dir_removename(
struct xfs_name *name,
xfs_ino_t ino,
xfs_fsblock_t *first, /* bmap's firstblock */
- xfs_bmap_free_t *flist, /* bmap's freeblock list */
+ struct xfs_defer_ops *dfops, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
struct xfs_da_args *args;
@@ -458,7 +459,7 @@ xfs_dir_removename(
args->inumber = ino;
args->dp = dp;
args->firstblock = first;
- args->flist = flist;
+ args->dfops = dfops;
args->total = total;
args->whichfork = XFS_DATA_FORK;
args->trans = tp;
@@ -498,7 +499,7 @@ xfs_dir_replace(
struct xfs_name *name, /* name of entry to replace */
xfs_ino_t inum, /* new inode number */
xfs_fsblock_t *first, /* bmap's firstblock */
- xfs_bmap_free_t *flist, /* bmap's freeblock list */
+ struct xfs_defer_ops *dfops, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
struct xfs_da_args *args;
@@ -523,7 +524,7 @@ xfs_dir_replace(
args->inumber = inum;
args->dp = dp;
args->firstblock = first;
- args->flist = flist;
+ args->dfops = dfops;
args->total = total;
args->whichfork = XFS_DATA_FORK;
args->trans = tp;
@@ -680,7 +681,7 @@ xfs_dir2_shrink_inode(
/* Unmap the fsblock(s). */
error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0,
- args->firstblock, args->flist, &done);
+ args->firstblock, args->dfops, &done);
if (error) {
/*
* ENOSPC actually can happen if we're in a removename with no
diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h
index e55353651f5b..becc926c3e3d 100644
--- a/fs/xfs/libxfs/xfs_dir2.h
+++ b/fs/xfs/libxfs/xfs_dir2.h
@@ -18,7 +18,7 @@
#ifndef __XFS_DIR2_H__
#define __XFS_DIR2_H__
-struct xfs_bmap_free;
+struct xfs_defer_ops;
struct xfs_da_args;
struct xfs_inode;
struct xfs_mount;
@@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
xfs_fsblock_t *first,
- struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ struct xfs_defer_ops *dfops, xfs_extlen_t tot);
extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t *inum,
struct xfs_name *ci_name);
extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t ino,
xfs_fsblock_t *first,
- struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ struct xfs_defer_ops *dfops, xfs_extlen_t tot);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name, xfs_ino_t inum,
xfs_fsblock_t *first,
- struct xfs_bmap_free *flist, xfs_extlen_t tot);
+ struct xfs_defer_ops *dfops, xfs_extlen_t tot);
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
struct xfs_name *name);
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index adb204d40f22..f814d42c73b2 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -455,8 +455,10 @@ xfs_sb_has_compat_feature(
}
#define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */
+#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */
#define XFS_SB_FEAT_RO_COMPAT_ALL \
- (XFS_SB_FEAT_RO_COMPAT_FINOBT)
+ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \
+ XFS_SB_FEAT_RO_COMPAT_RMAPBT)
#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL
static inline bool
xfs_sb_has_ro_compat_feature(
@@ -538,6 +540,12 @@ static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp)
(sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID);
}
+static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp)
+{
+ return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) &&
+ (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT);
+}
+
/*
* end of superblock version macros
*/
@@ -598,10 +606,10 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
#define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION)
/*
- * Btree number 0 is bno, 1 is cnt. This value gives the size of the
+ * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the
* arrays below.
*/
-#define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1)
+#define XFS_BTNUM_AGF ((int)XFS_BTNUM_RMAPi + 1)
/*
* The second word of agf_levels in the first a.g. overlaps the EFS
@@ -618,12 +626,10 @@ typedef struct xfs_agf {
__be32 agf_seqno; /* sequence # starting from 0 */
__be32 agf_length; /* size in blocks of a.g. */
/*
- * Freespace information
+ * Freespace and rmap information
*/
__be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */
- __be32 agf_spare0; /* spare field */
__be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */
- __be32 agf_spare1; /* spare field */
__be32 agf_flfirst; /* first freelist block's index */
__be32 agf_fllast; /* last freelist block's index */
@@ -1308,17 +1314,118 @@ typedef __be32 xfs_inobt_ptr_t;
#define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1))
/*
- * The first data block of an AG depends on whether the filesystem was formatted
- * with the finobt feature. If so, account for the finobt reserved root btree
- * block.
+ * Reverse mapping btree format definitions
+ *
+ * There is a btree for the reverse map per allocation group
+ */
+#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */
+
+/*
+ * Ownership info for an extent. This is used to create reverse-mapping
+ * entries.
*/
-#define XFS_PREALLOC_BLOCKS(mp) \
+#define XFS_OWNER_INFO_ATTR_FORK (1 << 0)
+#define XFS_OWNER_INFO_BMBT_BLOCK (1 << 1)
+struct xfs_owner_info {
+ uint64_t oi_owner;
+ xfs_fileoff_t oi_offset;
+ unsigned int oi_flags;
+};
+
+/*
+ * Special owner types.
+ *
+ * Seeing as we only support up to 8EB, we have the upper bit of the owner field
+ * to tell us we have a special owner value. We use these for static metadata
+ * allocated at mkfs/growfs time, as well as for freespace management metadata.
+ */
+#define XFS_RMAP_OWN_NULL (-1ULL) /* No owner, for growfs */
+#define XFS_RMAP_OWN_UNKNOWN (-2ULL) /* Unknown owner, for EFI recovery */
+#define XFS_RMAP_OWN_FS (-3ULL) /* static fs metadata */
+#define XFS_RMAP_OWN_LOG (-4ULL) /* static fs metadata */
+#define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */
+#define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */
+#define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */
+#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */
+
+#define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63)))
+
+/*
+ * Data record structure
+ */
+struct xfs_rmap_rec {
+ __be32 rm_startblock; /* extent start block */
+ __be32 rm_blockcount; /* extent length */
+ __be64 rm_owner; /* extent owner */
+ __be64 rm_offset; /* offset within the owner */
+};
+
+/*
+ * rmap btree record
+ * rm_offset:63 is the attribute fork flag
+ * rm_offset:62 is the bmbt block flag
+ * rm_offset:61 is the unwritten extent flag (same as l0:63 in bmbt)
+ * rm_offset:54-60 aren't used and should be zero
+ * rm_offset:0-53 is the block offset within the inode
+ */
+#define XFS_RMAP_OFF_ATTR_FORK ((__uint64_t)1ULL << 63)
+#define XFS_RMAP_OFF_BMBT_BLOCK ((__uint64_t)1ULL << 62)
+#define XFS_RMAP_OFF_UNWRITTEN ((__uint64_t)1ULL << 61)
+
+#define XFS_RMAP_LEN_MAX ((__uint32_t)~0U)
+#define XFS_RMAP_OFF_FLAGS (XFS_RMAP_OFF_ATTR_FORK | \
+ XFS_RMAP_OFF_BMBT_BLOCK | \
+ XFS_RMAP_OFF_UNWRITTEN)
+#define XFS_RMAP_OFF_MASK ((__uint64_t)0x3FFFFFFFFFFFFFULL)
+
+#define XFS_RMAP_OFF(off) ((off) & XFS_RMAP_OFF_MASK)
+
+#define XFS_RMAP_IS_BMBT_BLOCK(off) (!!((off) & XFS_RMAP_OFF_BMBT_BLOCK))
+#define XFS_RMAP_IS_ATTR_FORK(off) (!!((off) & XFS_RMAP_OFF_ATTR_FORK))
+#define XFS_RMAP_IS_UNWRITTEN(len) (!!((off) & XFS_RMAP_OFF_UNWRITTEN))
+
+#define RMAPBT_STARTBLOCK_BITLEN 32
+#define RMAPBT_BLOCKCOUNT_BITLEN 32
+#define RMAPBT_OWNER_BITLEN 64
+#define RMAPBT_ATTRFLAG_BITLEN 1
+#define RMAPBT_BMBTFLAG_BITLEN 1
+#define RMAPBT_EXNTFLAG_BITLEN 1
+#define RMAPBT_UNUSED_OFFSET_BITLEN 7
+#define RMAPBT_OFFSET_BITLEN 54
+
+#define XFS_RMAP_ATTR_FORK (1 << 0)
+#define XFS_RMAP_BMBT_BLOCK (1 << 1)
+#define XFS_RMAP_UNWRITTEN (1 << 2)
+#define XFS_RMAP_KEY_FLAGS (XFS_RMAP_ATTR_FORK | \
+ XFS_RMAP_BMBT_BLOCK)
+#define XFS_RMAP_REC_FLAGS (XFS_RMAP_UNWRITTEN)
+struct xfs_rmap_irec {
+ xfs_agblock_t rm_startblock; /* extent start block */
+ xfs_extlen_t rm_blockcount; /* extent length */
+ __uint64_t rm_owner; /* extent owner */
+ __uint64_t rm_offset; /* offset within the owner */
+ unsigned int rm_flags; /* state flags */
+};
+
+/*
+ * Key structure
+ *
+ * We don't use the length for lookups
+ */
+struct xfs_rmap_key {
+ __be32 rm_startblock; /* extent start block */
+ __be64 rm_owner; /* extent owner */
+ __be64 rm_offset; /* offset within the owner */
+} __attribute__((packed));
+
+/* btree pointer type */
+typedef __be32 xfs_rmap_ptr_t;
+
+#define XFS_RMAP_BLOCK(mp) \
(xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \
XFS_FIBT_BLOCK(mp) + 1 : \
XFS_IBT_BLOCK(mp) + 1)
-
-
/*
* BMAP Btree format definitions
*
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index f5ec9c5ccae6..79455058b752 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -206,6 +206,7 @@ typedef struct xfs_fsop_resblks {
#define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */
#define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */
#define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */
+#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* Reverse mapping btree */
/*
* Minimum and maximum sizes need for growth checks.
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 4b1e408169a8..51b4e0de1fdc 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -24,6 +24,7 @@
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
@@ -39,6 +40,7 @@
#include "xfs_icache.h"
#include "xfs_trace.h"
#include "xfs_log.h"
+#include "xfs_rmap.h"
/*
@@ -614,6 +616,7 @@ xfs_ialloc_ag_alloc(
args.tp = tp;
args.mp = tp->t_mountp;
args.fsbno = NULLFSBLOCK;
+ xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES);
#ifdef DEBUG
/* randomly do sparse inode allocations */
@@ -1817,19 +1820,21 @@ xfs_difree_inode_chunk(
struct xfs_mount *mp,
xfs_agnumber_t agno,
struct xfs_inobt_rec_incore *rec,
- struct xfs_bmap_free *flist)
+ struct xfs_defer_ops *dfops)
{
xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino);
int startidx, endidx;
int nextbit;
xfs_agblock_t agbno;
int contigblk;
+ struct xfs_owner_info oinfo;
DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS);
+ xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES);
if (!xfs_inobt_issparse(rec->ir_holemask)) {
/* not sparse, calculate extent info directly */
- xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno),
- mp->m_ialloc_blks);
+ xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno),
+ mp->m_ialloc_blks, &oinfo);
return;
}
@@ -1872,8 +1877,8 @@ xfs_difree_inode_chunk(
ASSERT(agbno % mp->m_sb.sb_spino_align == 0);
ASSERT(contigblk % mp->m_sb.sb_spino_align == 0);
- xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, agbno),
- contigblk);
+ xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno),
+ contigblk, &oinfo);
/* reset range to current bit and carry on... */
startidx = endidx = nextbit;
@@ -1889,7 +1894,7 @@ xfs_difree_inobt(
struct xfs_trans *tp,
struct xfs_buf *agbp,
xfs_agino_t agino,
- struct xfs_bmap_free *flist,
+ struct xfs_defer_ops *dfops,
struct xfs_icluster *xic,
struct xfs_inobt_rec_incore *orec)
{
@@ -1976,7 +1981,7 @@ xfs_difree_inobt(
goto error0;
}
- xfs_difree_inode_chunk(mp, agno, &rec, flist);
+ xfs_difree_inode_chunk(mp, agno, &rec, dfops);
} else {
xic->deleted = 0;
@@ -2121,7 +2126,7 @@ int
xfs_difree(
struct xfs_trans *tp, /* transaction pointer */
xfs_ino_t inode, /* inode to be freed */
- struct xfs_bmap_free *flist, /* extents to free */
+ struct xfs_defer_ops *dfops, /* extents to free */
struct xfs_icluster *xic) /* cluster info if deleted */
{
/* REFERENCED */
@@ -2173,7 +2178,7 @@ xfs_difree(
/*
* Fix up the inode allocation btree.
*/
- error = xfs_difree_inobt(mp, tp, agbp, agino, flist, xic, &rec);
+ error = xfs_difree_inobt(mp, tp, agbp, agino, dfops, xic, &rec);
if (error)
goto error0;
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index 6e450df2979b..0bb89669fc07 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -95,7 +95,7 @@ int /* error */
xfs_difree(
struct xfs_trans *tp, /* transaction pointer */
xfs_ino_t inode, /* inode to be freed */
- struct xfs_bmap_free *flist, /* extents to free */
+ struct xfs_defer_ops *dfops, /* extents to free */
struct xfs_icluster *ifree); /* cluster info if deleted */
/*
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index 89c21d771e35..31ca2208c03d 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -32,6 +32,7 @@
#include "xfs_trace.h"
#include "xfs_cksum.h"
#include "xfs_trans.h"
+#include "xfs_rmap.h"
STATIC int
@@ -96,6 +97,7 @@ xfs_inobt_alloc_block(
memset(&args, 0, sizeof(args));
args.tp = cur->bc_tp;
args.mp = cur->bc_mp;
+ xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT);
args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno);
args.minlen = 1;
args.maxlen = 1;
@@ -125,8 +127,12 @@ xfs_inobt_free_block(
struct xfs_btree_cur *cur,
struct xfs_buf *bp)
{
+ struct xfs_owner_info oinfo;
+
+ xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT);
return xfs_free_extent(cur->bc_tp,
- XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1);
+ XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1,
+ &oinfo);
}
STATIC int
@@ -146,14 +152,6 @@ xfs_inobt_init_key_from_rec(
}
STATIC void
-xfs_inobt_init_rec_from_key(
- union xfs_btree_key *key,
- union xfs_btree_rec *rec)
-{
- rec->inobt.ir_startino = key->inobt.ir_startino;
-}
-
-STATIC void
xfs_inobt_init_rec_from_cur(
struct xfs_btree_cur *cur,
union xfs_btree_rec *rec)
@@ -314,7 +312,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = {
.get_minrecs = xfs_inobt_get_minrecs,
.get_maxrecs = xfs_inobt_get_maxrecs,
.init_key_from_rec = xfs_inobt_init_key_from_rec,
- .init_rec_from_key = xfs_inobt_init_rec_from_key,
.init_rec_from_cur = xfs_inobt_init_rec_from_cur,
.init_ptr_from_cur = xfs_inobt_init_ptr_from_cur,
.key_diff = xfs_inobt_key_diff,
@@ -336,7 +333,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = {
.get_minrecs = xfs_inobt_get_minrecs,
.get_maxrecs = xfs_inobt_get_maxrecs,
.init_key_from_rec = xfs_inobt_init_key_from_rec,
- .init_rec_from_key = xfs_inobt_init_rec_from_key,
.init_rec_from_cur = xfs_inobt_init_rec_from_cur,
.init_ptr_from_cur = xfs_finobt_init_ptr_from_cur,
.key_diff = xfs_inobt_key_diff,
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 9d9559eb2835..4b9769e23c83 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -22,6 +22,7 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_error.h"
#include "xfs_cksum.h"
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index e8f49c029ff0..a6eed43fa7cd 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -110,7 +110,9 @@ static inline uint xlog_get_cycle(char *ptr)
#define XLOG_REG_TYPE_COMMIT 18
#define XLOG_REG_TYPE_TRANSHDR 19
#define XLOG_REG_TYPE_ICREATE 20
-#define XLOG_REG_TYPE_MAX 20
+#define XLOG_REG_TYPE_RUI_FORMAT 21
+#define XLOG_REG_TYPE_RUD_FORMAT 22
+#define XLOG_REG_TYPE_MAX 22
/*
* Flags to log operation header
@@ -227,6 +229,8 @@ typedef struct xfs_trans_header {
#define XFS_LI_DQUOT 0x123d
#define XFS_LI_QUOTAOFF 0x123e
#define XFS_LI_ICREATE 0x123f
+#define XFS_LI_RUI 0x1240 /* rmap update intent */
+#define XFS_LI_RUD 0x1241
#define XFS_LI_TYPE_DESC \
{ XFS_LI_EFI, "XFS_LI_EFI" }, \
@@ -236,7 +240,9 @@ typedef struct xfs_trans_header {
{ XFS_LI_BUF, "XFS_LI_BUF" }, \
{ XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \
{ XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \
- { XFS_LI_ICREATE, "XFS_LI_ICREATE" }
+ { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \
+ { XFS_LI_RUI, "XFS_LI_RUI" }, \
+ { XFS_LI_RUD, "XFS_LI_RUD" }
/*
* Inode Log Item Format definitions.
@@ -604,6 +610,59 @@ typedef struct xfs_efd_log_format_64 {
} xfs_efd_log_format_64_t;
/*
+ * RUI/RUD (reverse mapping) log format definitions
+ */
+struct xfs_map_extent {
+ __uint64_t me_owner;
+ __uint64_t me_startblock;
+ __uint64_t me_startoff;
+ __uint32_t me_len;
+ __uint32_t me_flags;
+};
+
+/* rmap me_flags: upper bits are flags, lower byte is type code */
+#define XFS_RMAP_EXTENT_MAP 1
+#define XFS_RMAP_EXTENT_UNMAP 3
+#define XFS_RMAP_EXTENT_CONVERT 5
+#define XFS_RMAP_EXTENT_ALLOC 7
+#define XFS_RMAP_EXTENT_FREE 8
+#define XFS_RMAP_EXTENT_TYPE_MASK 0xFF
+
+#define XFS_RMAP_EXTENT_ATTR_FORK (1U << 31)
+#define XFS_RMAP_EXTENT_BMBT_BLOCK (1U << 30)
+#define XFS_RMAP_EXTENT_UNWRITTEN (1U << 29)
+
+#define XFS_RMAP_EXTENT_FLAGS (XFS_RMAP_EXTENT_TYPE_MASK | \
+ XFS_RMAP_EXTENT_ATTR_FORK | \
+ XFS_RMAP_EXTENT_BMBT_BLOCK | \
+ XFS_RMAP_EXTENT_UNWRITTEN)
+
+/*
+ * This is the structure used to lay out an rui log item in the
+ * log. The rui_extents field is a variable size array whose
+ * size is given by rui_nextents.
+ */
+struct xfs_rui_log_format {
+ __uint16_t rui_type; /* rui log item type */
+ __uint16_t rui_size; /* size of this item */
+ __uint32_t rui_nextents; /* # extents to free */
+ __uint64_t rui_id; /* rui identifier */
+ struct xfs_map_extent rui_extents[1]; /* array of extents to rmap */
+};
+
+/*
+ * This is the structure used to lay out an rud log item in the
+ * log. The rud_extents array is a variable size array whose
+ * size is given by rud_nextents;
+ */
+struct xfs_rud_log_format {
+ __uint16_t rud_type; /* rud log item type */
+ __uint16_t rud_size; /* size of this item */
+ __uint32_t __pad;
+ __uint64_t rud_rui_id; /* id of corresponding rui */
+};
+
+/*
* Dquot Log format definitions.
*
* The first two fields must be the type and size fitting into
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
new file mode 100644
index 000000000000..73d05407d663
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -0,0 +1,1399 @@
+/*
+ * Copyright (c) 2014 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_da_format.h"
+#include "xfs_da_btree.h"
+#include "xfs_btree.h"
+#include "xfs_trans.h"
+#include "xfs_alloc.h"
+#include "xfs_rmap.h"
+#include "xfs_rmap_btree.h"
+#include "xfs_trans_space.h"
+#include "xfs_trace.h"
+#include "xfs_error.h"
+#include "xfs_extent_busy.h"
+#include "xfs_bmap.h"
+#include "xfs_inode.h"
+
+/*
+ * Lookup the first record less than or equal to [bno, len, owner, offset]
+ * in the btree given by cur.
+ */
+int
+xfs_rmap_lookup_le(
+ struct xfs_btree_cur *cur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ uint64_t owner,
+ uint64_t offset,
+ unsigned int flags,
+ int *stat)
+{
+ cur->bc_rec.r.rm_startblock = bno;
+ cur->bc_rec.r.rm_blockcount = len;
+ cur->bc_rec.r.rm_owner = owner;
+ cur->bc_rec.r.rm_offset = offset;
+ cur->bc_rec.r.rm_flags = flags;
+ return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
+}
+
+/*
+ * Lookup the record exactly matching [bno, len, owner, offset]
+ * in the btree given by cur.
+ */
+int
+xfs_rmap_lookup_eq(
+ struct xfs_btree_cur *cur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ uint64_t owner,
+ uint64_t offset,
+ unsigned int flags,
+ int *stat)
+{
+ cur->bc_rec.r.rm_startblock = bno;
+ cur->bc_rec.r.rm_blockcount = len;
+ cur->bc_rec.r.rm_owner = owner;
+ cur->bc_rec.r.rm_offset = offset;
+ cur->bc_rec.r.rm_flags = flags;
+ return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
+}
+
+/*
+ * Update the record referred to by cur to the value given
+ * by [bno, len, owner, offset].
+ * This either works (return 0) or gets an EFSCORRUPTED error.
+ */
+STATIC int
+xfs_rmap_update(
+ struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *irec)
+{
+ union xfs_btree_rec rec;
+ int error;
+
+ trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
+ irec->rm_startblock, irec->rm_blockcount,
+ irec->rm_owner, irec->rm_offset, irec->rm_flags);
+
+ rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
+ rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
+ rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
+ rec.rmap.rm_offset = cpu_to_be64(
+ xfs_rmap_irec_offset_pack(irec));
+ error = xfs_btree_update(cur, &rec);
+ if (error)
+ trace_xfs_rmap_update_error(cur->bc_mp,
+ cur->bc_private.a.agno, error, _RET_IP_);
+ return error;
+}
+
+int
+xfs_rmap_insert(
+ struct xfs_btree_cur *rcur,
+ xfs_agblock_t agbno,
+ xfs_extlen_t len,
+ uint64_t owner,
+ uint64_t offset,
+ unsigned int flags)
+{
+ int i;
+ int error;
+
+ trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
+ len, owner, offset, flags);
+
+ error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
+
+ rcur->bc_rec.r.rm_startblock = agbno;
+ rcur->bc_rec.r.rm_blockcount = len;
+ rcur->bc_rec.r.rm_owner = owner;
+ rcur->bc_rec.r.rm_offset = offset;
+ rcur->bc_rec.r.rm_flags = flags;
+ error = xfs_btree_insert(rcur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
+done:
+ if (error)
+ trace_xfs_rmap_insert_error(rcur->bc_mp,
+ rcur->bc_private.a.agno, error, _RET_IP_);
+ return error;
+}
+
+static int
+xfs_rmap_btrec_to_irec(
+ union xfs_btree_rec *rec,
+ struct xfs_rmap_irec *irec)
+{
+ irec->rm_flags = 0;
+ irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
+ irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
+ irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
+ return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
+ irec);
+}
+
+/*
+ * Get the data from the pointed-to record.
+ */
+int
+xfs_rmap_get_rec(
+ struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *irec,
+ int *stat)
+{
+ union xfs_btree_rec *rec;
+ int error;
+
+ error = xfs_btree_get_rec(cur, &rec, stat);
+ if (error || !*stat)
+ return error;
+
+ return xfs_rmap_btrec_to_irec(rec, irec);
+}
+
+/*
+ * Find the extent in the rmap btree and remove it.
+ *
+ * The record we find should always be an exact match for the extent that we're
+ * looking for, since we insert them into the btree without modification.
+ *
+ * Special Case #1: when growing the filesystem, we "free" an extent when
+ * growing the last AG. This extent is new space and so it is not tracked as
+ * used space in the btree. The growfs code will pass in an owner of
+ * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
+ * extent. We verify that - the extent lookup result in a record that does not
+ * overlap.
+ *
+ * Special Case #2: EFIs do not record the owner of the extent, so when
+ * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
+ * btree to ignore the owner (i.e. wildcard match) so we don't trigger
+ * corruption checks during log recovery.
+ */
+STATIC int
+xfs_rmap_unmap(
+ struct xfs_btree_cur *cur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ bool unwritten,
+ struct xfs_owner_info *oinfo)
+{
+ struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_rmap_irec ltrec;
+ uint64_t ltoff;
+ int error = 0;
+ int i;
+ uint64_t owner;
+ uint64_t offset;
+ unsigned int flags;
+ bool ignore_off;
+
+ xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
+ ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
+ (flags & XFS_RMAP_BMBT_BLOCK);
+ if (unwritten)
+ flags |= XFS_RMAP_UNWRITTEN;
+ trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+
+ /*
+ * We should always have a left record because there's a static record
+ * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
+ * will not ever be removed from the tree.
+ */
+ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
+
+ error = xfs_rmap_get_rec(cur, &ltrec, &i);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
+ trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
+ cur->bc_private.a.agno, ltrec.rm_startblock,
+ ltrec.rm_blockcount, ltrec.rm_owner,
+ ltrec.rm_offset, ltrec.rm_flags);
+ ltoff = ltrec.rm_offset;
+
+ /*
+ * For growfs, the incoming extent must be beyond the left record we
+ * just found as it is new space and won't be used by anyone. This is
+ * just a corruption check as we don't actually do anything with this
+ * extent. Note that we need to use >= instead of > because it might
+ * be the case that the "left" extent goes all the way to EOFS.
+ */
+ if (owner == XFS_RMAP_OWN_NULL) {
+ XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
+ ltrec.rm_blockcount, out_error);
+ goto out_done;
+ }
+
+ /* Make sure the unwritten flag matches. */
+ XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
+ (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
+
+ /* Make sure the extent we found covers the entire freeing range. */
+ XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
+ ltrec.rm_startblock + ltrec.rm_blockcount >=
+ bno + len, out_error);
+
+ /* Make sure the owner matches what we expect to find in the tree. */
+ XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner ||
+ XFS_RMAP_NON_INODE_OWNER(owner), out_error);
+
+ /* Check the offset, if necessary. */
+ if (!XFS_RMAP_NON_INODE_OWNER(owner)) {
+ if (flags & XFS_RMAP_BMBT_BLOCK) {
+ XFS_WANT_CORRUPTED_GOTO(mp,
+ ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK,
+ out_error);
+ } else {
+ XFS_WANT_CORRUPTED_GOTO(mp,
+ ltrec.rm_offset <= offset, out_error);
+ XFS_WANT_CORRUPTED_GOTO(mp,
+ ltoff + ltrec.rm_blockcount >= offset + len,
+ out_error);
+ }
+ }
+
+ if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
+ /* exact match, simply remove the record from rmap tree */
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ ltrec.rm_startblock, ltrec.rm_blockcount,
+ ltrec.rm_owner, ltrec.rm_offset,
+ ltrec.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
+ } else if (ltrec.rm_startblock == bno) {
+ /*
+ * overlap left hand side of extent: move the start, trim the
+ * length and update the current record.
+ *
+ * ltbno ltlen
+ * Orig: |oooooooooooooooooooo|
+ * Freeing: |fffffffff|
+ * Result: |rrrrrrrrrr|
+ * bno len
+ */
+ ltrec.rm_startblock += len;
+ ltrec.rm_blockcount -= len;
+ if (!ignore_off)
+ ltrec.rm_offset += len;
+ error = xfs_rmap_update(cur, &ltrec);
+ if (error)
+ goto out_error;
+ } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
+ /*
+ * overlap right hand side of extent: trim the length and update
+ * the current record.
+ *
+ * ltbno ltlen
+ * Orig: |oooooooooooooooooooo|
+ * Freeing: |fffffffff|
+ * Result: |rrrrrrrrrr|
+ * bno len
+ */
+ ltrec.rm_blockcount -= len;
+ error = xfs_rmap_update(cur, &ltrec);
+ if (error)
+ goto out_error;
+ } else {
+
+ /*
+ * overlap middle of extent: trim the length of the existing
+ * record to the length of the new left-extent size, increment
+ * the insertion position so we can insert a new record
+ * containing the remaining right-extent space.
+ *
+ * ltbno ltlen
+ * Orig: |oooooooooooooooooooo|
+ * Freeing: |fffffffff|
+ * Result: |rrrrr| |rrrr|
+ * bno len
+ */
+ xfs_extlen_t orig_len = ltrec.rm_blockcount;
+
+ ltrec.rm_blockcount = bno - ltrec.rm_startblock;
+ error = xfs_rmap_update(cur, &ltrec);
+ if (error)
+ goto out_error;
+
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto out_error;
+
+ cur->bc_rec.r.rm_startblock = bno + len;
+ cur->bc_rec.r.rm_blockcount = orig_len - len -
+ ltrec.rm_blockcount;
+ cur->bc_rec.r.rm_owner = ltrec.rm_owner;
+ if (ignore_off)
+ cur->bc_rec.r.rm_offset = 0;
+ else
+ cur->bc_rec.r.rm_offset = offset + len;
+ cur->bc_rec.r.rm_flags = flags;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
+ cur->bc_rec.r.rm_startblock,
+ cur->bc_rec.r.rm_blockcount,
+ cur->bc_rec.r.rm_owner,
+ cur->bc_rec.r.rm_offset,
+ cur->bc_rec.r.rm_flags);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto out_error;
+ }
+
+out_done:
+ trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+out_error:
+ if (error)
+ trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
+ error, _RET_IP_);
+ return error;
+}
+
+/*
+ * Remove a reference to an extent in the rmap btree.
+ */
+int
+xfs_rmap_free(
+ struct xfs_trans *tp,
+ struct xfs_buf *agbp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ struct xfs_owner_info *oinfo)
+{
+ struct xfs_mount *mp = tp->t_mountp;
+ struct xfs_btree_cur *cur;
+ int error;
+
+ if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return 0;
+
+ cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+
+ error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
+ if (error)
+ goto out_error;
+
+ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+ return 0;
+
+out_error:
+ xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+ return error;
+}
+
+/*
+ * A mergeable rmap must have the same owner and the same values for
+ * the unwritten, attr_fork, and bmbt flags. The startblock and
+ * offset are checked separately.
+ */
+static bool
+xfs_rmap_is_mergeable(
+ struct xfs_rmap_irec *irec,
+ uint64_t owner,
+ unsigned int flags)
+{
+ if (irec->rm_owner == XFS_RMAP_OWN_NULL)
+ return false;
+ if (irec->rm_owner != owner)
+ return false;
+ if ((flags & XFS_RMAP_UNWRITTEN) ^
+ (irec->rm_flags & XFS_RMAP_UNWRITTEN))
+ return false;
+ if ((flags & XFS_RMAP_ATTR_FORK) ^
+ (irec->rm_flags & XFS_RMAP_ATTR_FORK))
+ return false;
+ if ((flags & XFS_RMAP_BMBT_BLOCK) ^
+ (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
+ return false;
+ return true;
+}
+
+/*
+ * When we allocate a new block, the first thing we do is add a reference to
+ * the extent in the rmap btree. This takes the form of a [agbno, length,
+ * owner, offset] record. Flags are encoded in the high bits of the offset
+ * field.
+ */
+STATIC int
+xfs_rmap_map(
+ struct xfs_btree_cur *cur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ bool unwritten,
+ struct xfs_owner_info *oinfo)
+{
+ struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_rmap_irec ltrec;
+ struct xfs_rmap_irec gtrec;
+ int have_gt;
+ int have_lt;
+ int error = 0;
+ int i;
+ uint64_t owner;
+ uint64_t offset;
+ unsigned int flags = 0;
+ bool ignore_off;
+
+ xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
+ ASSERT(owner != 0);
+ ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
+ (flags & XFS_RMAP_BMBT_BLOCK);
+ if (unwritten)
+ flags |= XFS_RMAP_UNWRITTEN;
+ trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+
+ /*
+ * For the initial lookup, look for an exact match or the left-adjacent
+ * record for our insertion point. This will also give us the record for
+ * start block contiguity tests.
+ */
+ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
+ &have_lt);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
+
+ error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
+ trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
+ cur->bc_private.a.agno, ltrec.rm_startblock,
+ ltrec.rm_blockcount, ltrec.rm_owner,
+ ltrec.rm_offset, ltrec.rm_flags);
+
+ if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
+ have_lt = 0;
+
+ XFS_WANT_CORRUPTED_GOTO(mp,
+ have_lt == 0 ||
+ ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
+
+ /*
+ * Increment the cursor to see if we have a right-adjacent record to our
+ * insertion point. This will give us the record for end block
+ * contiguity tests.
+ */
+ error = xfs_btree_increment(cur, 0, &have_gt);
+ if (error)
+ goto out_error;
+ if (have_gt) {
+ error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
+ XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
+ out_error);
+ trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
+ cur->bc_private.a.agno, gtrec.rm_startblock,
+ gtrec.rm_blockcount, gtrec.rm_owner,
+ gtrec.rm_offset, gtrec.rm_flags);
+ if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
+ have_gt = 0;
+ }
+
+ /*
+ * Note: cursor currently points one record to the right of ltrec, even
+ * if there is no record in the tree to the right.
+ */
+ if (have_lt &&
+ ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
+ (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
+ /*
+ * left edge contiguous, merge into left record.
+ *
+ * ltbno ltlen
+ * orig: |ooooooooo|
+ * adding: |aaaaaaaaa|
+ * result: |rrrrrrrrrrrrrrrrrrr|
+ * bno len
+ */
+ ltrec.rm_blockcount += len;
+ if (have_gt &&
+ bno + len == gtrec.rm_startblock &&
+ (ignore_off || offset + len == gtrec.rm_offset) &&
+ (unsigned long)ltrec.rm_blockcount + len +
+ gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
+ /*
+ * right edge also contiguous, delete right record
+ * and merge into left record.
+ *
+ * ltbno ltlen gtbno gtlen
+ * orig: |ooooooooo| |ooooooooo|
+ * adding: |aaaaaaaaa|
+ * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
+ */
+ ltrec.rm_blockcount += gtrec.rm_blockcount;
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ gtrec.rm_startblock,
+ gtrec.rm_blockcount,
+ gtrec.rm_owner,
+ gtrec.rm_offset,
+ gtrec.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
+ }
+
+ /* point the cursor back to the left record and update */
+ error = xfs_btree_decrement(cur, 0, &have_gt);
+ if (error)
+ goto out_error;
+ error = xfs_rmap_update(cur, &ltrec);
+ if (error)
+ goto out_error;
+ } else if (have_gt &&
+ bno + len == gtrec.rm_startblock &&
+ (ignore_off || offset + len == gtrec.rm_offset)) {
+ /*
+ * right edge contiguous, merge into right record.
+ *
+ * gtbno gtlen
+ * Orig: |ooooooooo|
+ * adding: |aaaaaaaaa|
+ * Result: |rrrrrrrrrrrrrrrrrrr|
+ * bno len
+ */
+ gtrec.rm_startblock = bno;
+ gtrec.rm_blockcount += len;
+ if (!ignore_off)
+ gtrec.rm_offset = offset;
+ error = xfs_rmap_update(cur, &gtrec);
+ if (error)
+ goto out_error;
+ } else {
+ /*
+ * no contiguous edge with identical owner, insert
+ * new record at current cursor position.
+ */
+ cur->bc_rec.r.rm_startblock = bno;
+ cur->bc_rec.r.rm_blockcount = len;
+ cur->bc_rec.r.rm_owner = owner;
+ cur->bc_rec.r.rm_offset = offset;
+ cur->bc_rec.r.rm_flags = flags;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
+ owner, offset, flags);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto out_error;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
+ }
+
+ trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+out_error:
+ if (error)
+ trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
+ error, _RET_IP_);
+ return error;
+}
+
+/*
+ * Add a reference to an extent in the rmap btree.
+ */
+int
+xfs_rmap_alloc(
+ struct xfs_trans *tp,
+ struct xfs_buf *agbp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ struct xfs_owner_info *oinfo)
+{
+ struct xfs_mount *mp = tp->t_mountp;
+ struct xfs_btree_cur *cur;
+ int error;
+
+ if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return 0;
+
+ cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+ error = xfs_rmap_map(cur, bno, len, false, oinfo);
+ if (error)
+ goto out_error;
+
+ xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
+ return 0;
+
+out_error:
+ xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
+ return error;
+}
+
+#define RMAP_LEFT_CONTIG (1 << 0)
+#define RMAP_RIGHT_CONTIG (1 << 1)
+#define RMAP_LEFT_FILLING (1 << 2)
+#define RMAP_RIGHT_FILLING (1 << 3)
+#define RMAP_LEFT_VALID (1 << 6)
+#define RMAP_RIGHT_VALID (1 << 7)
+
+#define LEFT r[0]
+#define RIGHT r[1]
+#define PREV r[2]
+#define NEW r[3]
+
+/*
+ * Convert an unwritten extent to a real extent or vice versa.
+ * Does not handle overlapping extents.
+ */
+STATIC int
+xfs_rmap_convert(
+ struct xfs_btree_cur *cur,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ bool unwritten,
+ struct xfs_owner_info *oinfo)
+{
+ struct xfs_mount *mp = cur->bc_mp;
+ struct xfs_rmap_irec r[4]; /* neighbor extent entries */
+ /* left is 0, right is 1, prev is 2 */
+ /* new is 3 */
+ uint64_t owner;
+ uint64_t offset;
+ uint64_t new_endoff;
+ unsigned int oldext;
+ unsigned int newext;
+ unsigned int flags = 0;
+ int i;
+ int state = 0;
+ int error;
+
+ xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
+ ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
+ (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
+ oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
+ new_endoff = offset + len;
+ trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+
+ /*
+ * For the initial lookup, look for an exact match or the left-adjacent
+ * record for our insertion point. This will also give us the record for
+ * start block contiguity tests.
+ */
+ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+
+ error = xfs_rmap_get_rec(cur, &PREV, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
+ cur->bc_private.a.agno, PREV.rm_startblock,
+ PREV.rm_blockcount, PREV.rm_owner,
+ PREV.rm_offset, PREV.rm_flags);
+
+ ASSERT(PREV.rm_offset <= offset);
+ ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
+ ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
+ newext = ~oldext & XFS_RMAP_UNWRITTEN;
+
+ /*
+ * Set flags determining what part of the previous oldext allocation
+ * extent is being replaced by a newext allocation.
+ */
+ if (PREV.rm_offset == offset)
+ state |= RMAP_LEFT_FILLING;
+ if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
+ state |= RMAP_RIGHT_FILLING;
+
+ /*
+ * Decrement the cursor to see if we have a left-adjacent record to our
+ * insertion point. This will give us the record for end block
+ * contiguity tests.
+ */
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ if (i) {
+ state |= RMAP_LEFT_VALID;
+ error = xfs_rmap_get_rec(cur, &LEFT, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ XFS_WANT_CORRUPTED_GOTO(mp,
+ LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
+ done);
+ trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
+ cur->bc_private.a.agno, LEFT.rm_startblock,
+ LEFT.rm_blockcount, LEFT.rm_owner,
+ LEFT.rm_offset, LEFT.rm_flags);
+ if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
+ LEFT.rm_offset + LEFT.rm_blockcount == offset &&
+ xfs_rmap_is_mergeable(&LEFT, owner, newext))
+ state |= RMAP_LEFT_CONTIG;
+ }
+
+ /*
+ * Increment the cursor to see if we have a right-adjacent record to our
+ * insertion point. This will give us the record for end block
+ * contiguity tests.
+ */
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto done;
+ if (i) {
+ state |= RMAP_RIGHT_VALID;
+ error = xfs_rmap_get_rec(cur, &RIGHT, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
+ done);
+ trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
+ cur->bc_private.a.agno, RIGHT.rm_startblock,
+ RIGHT.rm_blockcount, RIGHT.rm_owner,
+ RIGHT.rm_offset, RIGHT.rm_flags);
+ if (bno + len == RIGHT.rm_startblock &&
+ offset + len == RIGHT.rm_offset &&
+ xfs_rmap_is_mergeable(&RIGHT, owner, newext))
+ state |= RMAP_RIGHT_CONTIG;
+ }
+
+ /* check that left + prev + right is not too long */
+ if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
+ RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
+ (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
+ RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
+ (unsigned long)LEFT.rm_blockcount + len +
+ RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
+ state &= ~RMAP_RIGHT_CONTIG;
+
+ trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
+ _RET_IP_);
+
+ /* reset the cursor back to PREV */
+ error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+
+ /*
+ * Switch out based on the FILLING and CONTIG state bits.
+ */
+ switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
+ RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
+ case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
+ RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
+ /*
+ * Setting all of a previous oldext extent to newext.
+ * The left and right neighbors are both contiguous with new.
+ */
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ RIGHT.rm_startblock, RIGHT.rm_blockcount,
+ RIGHT.rm_owner, RIGHT.rm_offset,
+ RIGHT.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ PREV.rm_startblock, PREV.rm_blockcount,
+ PREV.rm_owner, PREV.rm_offset,
+ PREV.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ NEW = LEFT;
+ NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
+ /*
+ * Setting all of a previous oldext extent to newext.
+ * The left neighbor is contiguous, the right is not.
+ */
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ PREV.rm_startblock, PREV.rm_blockcount,
+ PREV.rm_owner, PREV.rm_offset,
+ PREV.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ NEW = LEFT;
+ NEW.rm_blockcount += PREV.rm_blockcount;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
+ /*
+ * Setting all of a previous oldext extent to newext.
+ * The right neighbor is contiguous, the left is not.
+ */
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
+ RIGHT.rm_startblock, RIGHT.rm_blockcount,
+ RIGHT.rm_owner, RIGHT.rm_offset,
+ RIGHT.rm_flags);
+ error = xfs_btree_delete(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ NEW = PREV;
+ NEW.rm_blockcount = len + RIGHT.rm_blockcount;
+ NEW.rm_flags = newext;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
+ /*
+ * Setting all of a previous oldext extent to newext.
+ * Neither the left nor right neighbors are contiguous with
+ * the new one.
+ */
+ NEW = PREV;
+ NEW.rm_flags = newext;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
+ /*
+ * Setting the first part of a previous oldext extent to newext.
+ * The left neighbor is contiguous.
+ */
+ NEW = PREV;
+ NEW.rm_offset += len;
+ NEW.rm_startblock += len;
+ NEW.rm_blockcount -= len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ error = xfs_btree_decrement(cur, 0, &i);
+ if (error)
+ goto done;
+ NEW = LEFT;
+ NEW.rm_blockcount += len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_LEFT_FILLING:
+ /*
+ * Setting the first part of a previous oldext extent to newext.
+ * The left neighbor is not contiguous.
+ */
+ NEW = PREV;
+ NEW.rm_startblock += len;
+ NEW.rm_offset += len;
+ NEW.rm_blockcount -= len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ NEW.rm_startblock = bno;
+ NEW.rm_owner = owner;
+ NEW.rm_offset = offset;
+ NEW.rm_blockcount = len;
+ NEW.rm_flags = newext;
+ cur->bc_rec.r = NEW;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
+ len, owner, offset, newext);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ break;
+
+ case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
+ /*
+ * Setting the last part of a previous oldext extent to newext.
+ * The right neighbor is contiguous with the new allocation.
+ */
+ NEW = PREV;
+ NEW.rm_blockcount -= len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ error = xfs_btree_increment(cur, 0, &i);
+ if (error)
+ goto done;
+ NEW = RIGHT;
+ NEW.rm_offset = offset;
+ NEW.rm_startblock = bno;
+ NEW.rm_blockcount += len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ break;
+
+ case RMAP_RIGHT_FILLING:
+ /*
+ * Setting the last part of a previous oldext extent to newext.
+ * The right neighbor is not contiguous.
+ */
+ NEW = PREV;
+ NEW.rm_blockcount -= len;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
+ oldext, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+ NEW.rm_startblock = bno;
+ NEW.rm_owner = owner;
+ NEW.rm_offset = offset;
+ NEW.rm_blockcount = len;
+ NEW.rm_flags = newext;
+ cur->bc_rec.r = NEW;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
+ len, owner, offset, newext);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ break;
+
+ case 0:
+ /*
+ * Setting the middle part of a previous oldext extent to
+ * newext. Contiguity is impossible here.
+ * One extent becomes three extents.
+ */
+ /* new right extent - oldext */
+ NEW.rm_startblock = bno + len;
+ NEW.rm_owner = owner;
+ NEW.rm_offset = new_endoff;
+ NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
+ new_endoff;
+ NEW.rm_flags = PREV.rm_flags;
+ error = xfs_rmap_update(cur, &NEW);
+ if (error)
+ goto done;
+ /* new left extent - oldext */
+ NEW = PREV;
+ NEW.rm_blockcount = offset - PREV.rm_offset;
+ cur->bc_rec.r = NEW;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
+ NEW.rm_startblock, NEW.rm_blockcount,
+ NEW.rm_owner, NEW.rm_offset,
+ NEW.rm_flags);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ /*
+ * Reset the cursor to the position of the new extent
+ * we are about to insert as we can't trust it after
+ * the previous insert.
+ */
+ error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
+ oldext, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
+ /* new middle extent - newext */
+ cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
+ cur->bc_rec.r.rm_flags |= newext;
+ trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
+ owner, offset, newext);
+ error = xfs_btree_insert(cur, &i);
+ if (error)
+ goto done;
+ XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
+ break;
+
+ case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
+ case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
+ case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
+ case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
+ case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
+ case RMAP_LEFT_CONTIG:
+ case RMAP_RIGHT_CONTIG:
+ /*
+ * These cases are all impossible.
+ */
+ ASSERT(0);
+ }
+
+ trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
+ unwritten, oinfo);
+done:
+ if (error)
+ trace_xfs_rmap_convert_error(cur->bc_mp,
+ cur->bc_private.a.agno, error, _RET_IP_);
+ return error;
+}
+
+#undef NEW
+#undef LEFT
+#undef RIGHT
+#undef PREV
+
+struct xfs_rmap_query_range_info {
+ xfs_rmap_query_range_fn fn;
+ void *priv;
+};
+
+/* Format btree record and pass to our callback. */
+STATIC int
+xfs_rmap_query_range_helper(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec,
+ void *priv)
+{
+ struct xfs_rmap_query_range_info *query = priv;
+ struct xfs_rmap_irec irec;
+ int error;
+
+ error = xfs_rmap_btrec_to_irec(rec, &irec);
+ if (error)
+ return error;
+ return query->fn(cur, &irec, query->priv);
+}
+
+/* Find all rmaps between two keys. */
+int
+xfs_rmap_query_range(
+ struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *low_rec,
+ struct xfs_rmap_irec *high_rec,
+ xfs_rmap_query_range_fn fn,
+ void *priv)
+{
+ union xfs_btree_irec low_brec;
+ union xfs_btree_irec high_brec;
+ struct xfs_rmap_query_range_info query;
+
+ low_brec.r = *low_rec;
+ high_brec.r = *high_rec;
+ query.priv = priv;
+ query.fn = fn;
+ return xfs_btree_query_range(cur, &low_brec, &high_brec,
+ xfs_rmap_query_range_helper, &query);
+}
+
+/* Clean up after calling xfs_rmap_finish_one. */
+void
+xfs_rmap_finish_one_cleanup(
+ struct xfs_trans *tp,
+ struct xfs_btree_cur *rcur,
+ int error)
+{
+ struct xfs_buf *agbp;
+
+ if (rcur == NULL)
+ return;
+ agbp = rcur->bc_private.a.agbp;
+ xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
+ if (error)
+ xfs_trans_brelse(tp, agbp);
+}
+
+/*
+ * Process one of the deferred rmap operations. We pass back the
+ * btree cursor to maintain our lock on the rmapbt between calls.
+ * This saves time and eliminates a buffer deadlock between the
+ * superblock and the AGF because we'll always grab them in the same
+ * order.
+ */
+int
+xfs_rmap_finish_one(
+ struct xfs_trans *tp,
+ enum xfs_rmap_intent_type type,
+ __uint64_t owner,
+ int whichfork,
+ xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock,
+ xfs_filblks_t blockcount,
+ xfs_exntst_t state,
+ struct xfs_btree_cur **pcur)
+{
+ struct xfs_mount *mp = tp->t_mountp;
+ struct xfs_btree_cur *rcur;
+ struct xfs_buf *agbp = NULL;
+ int error = 0;
+ xfs_agnumber_t agno;
+ struct xfs_owner_info oinfo;
+ xfs_agblock_t bno;
+ bool unwritten;
+
+ agno = XFS_FSB_TO_AGNO(mp, startblock);
+ ASSERT(agno != NULLAGNUMBER);
+ bno = XFS_FSB_TO_AGBNO(mp, startblock);
+
+ trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
+ startoff, blockcount, state);
+
+ if (XFS_TEST_ERROR(false, mp,
+ XFS_ERRTAG_RMAP_FINISH_ONE,
+ XFS_RANDOM_RMAP_FINISH_ONE))
+ return -EIO;
+
+ /*
+ * If we haven't gotten a cursor or the cursor AG doesn't match
+ * the startblock, get one now.
+ */
+ rcur = *pcur;
+ if (rcur != NULL && rcur->bc_private.a.agno != agno) {
+ xfs_rmap_finish_one_cleanup(tp, rcur, 0);
+ rcur = NULL;
+ *pcur = NULL;
+ }
+ if (rcur == NULL) {
+ /*
+ * Refresh the freelist before we start changing the
+ * rmapbt, because a shape change could cause us to
+ * allocate blocks.
+ */
+ error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
+ if (error)
+ return error;
+ if (!agbp)
+ return -EFSCORRUPTED;
+
+ rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
+ if (!rcur) {
+ error = -ENOMEM;
+ goto out_cur;
+ }
+ }
+ *pcur = rcur;
+
+ xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
+ unwritten = state == XFS_EXT_UNWRITTEN;
+ bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
+
+ switch (type) {
+ case XFS_RMAP_ALLOC:
+ case XFS_RMAP_MAP:
+ error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
+ break;
+ case XFS_RMAP_FREE:
+ case XFS_RMAP_UNMAP:
+ error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
+ &oinfo);
+ break;
+ case XFS_RMAP_CONVERT:
+ error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
+ &oinfo);
+ break;
+ default:
+ ASSERT(0);
+ error = -EFSCORRUPTED;
+ }
+ return error;
+
+out_cur:
+ xfs_trans_brelse(tp, agbp);
+
+ return error;
+}
+
+/*
+ * Don't defer an rmap if we aren't an rmap filesystem.
+ */
+static bool
+xfs_rmap_update_is_needed(
+ struct xfs_mount *mp)
+{
+ return xfs_sb_version_hasrmapbt(&mp->m_sb);
+}
+
+/*
+ * Record a rmap intent; the list is kept sorted first by AG and then by
+ * increasing age.
+ */
+static int
+__xfs_rmap_add(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ enum xfs_rmap_intent_type type,
+ __uint64_t owner,
+ int whichfork,
+ struct xfs_bmbt_irec *bmap)
+{
+ struct xfs_rmap_intent *ri;
+
+ trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
+ type,
+ XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
+ owner, whichfork,
+ bmap->br_startoff,
+ bmap->br_blockcount,
+ bmap->br_state);
+
+ ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
+ INIT_LIST_HEAD(&ri->ri_list);
+ ri->ri_type = type;
+ ri->ri_owner = owner;
+ ri->ri_whichfork = whichfork;
+ ri->ri_bmap = *bmap;
+
+ xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
+ return 0;
+}
+
+/* Map an extent into a file. */
+int
+xfs_rmap_map_extent(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip,
+ int whichfork,
+ struct xfs_bmbt_irec *PREV)
+{
+ if (!xfs_rmap_update_is_needed(mp))
+ return 0;
+
+ return __xfs_rmap_add(mp, dfops, XFS_RMAP_MAP, ip->i_ino,
+ whichfork, PREV);
+}
+
+/* Unmap an extent out of a file. */
+int
+xfs_rmap_unmap_extent(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip,
+ int whichfork,
+ struct xfs_bmbt_irec *PREV)
+{
+ if (!xfs_rmap_update_is_needed(mp))
+ return 0;
+
+ return __xfs_rmap_add(mp, dfops, XFS_RMAP_UNMAP, ip->i_ino,
+ whichfork, PREV);
+}
+
+/* Convert a data fork extent from unwritten to real or vice versa. */
+int
+xfs_rmap_convert_extent(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip,
+ int whichfork,
+ struct xfs_bmbt_irec *PREV)
+{
+ if (!xfs_rmap_update_is_needed(mp))
+ return 0;
+
+ return __xfs_rmap_add(mp, dfops, XFS_RMAP_CONVERT, ip->i_ino,
+ whichfork, PREV);
+}
+
+/* Schedule the creation of an rmap for non-file data. */
+int
+xfs_rmap_alloc_extent(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ __uint64_t owner)
+{
+ struct xfs_bmbt_irec bmap;
+
+ if (!xfs_rmap_update_is_needed(mp))
+ return 0;
+
+ bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
+ bmap.br_blockcount = len;
+ bmap.br_startoff = 0;
+ bmap.br_state = XFS_EXT_NORM;
+
+ return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
+ XFS_DATA_FORK, &bmap);
+}
+
+/* Schedule the deletion of an rmap for non-file data. */
+int
+xfs_rmap_free_extent(
+ struct xfs_mount *mp,
+ struct xfs_defer_ops *dfops,
+ xfs_agnumber_t agno,
+ xfs_agblock_t bno,
+ xfs_extlen_t len,
+ __uint64_t owner)
+{
+ struct xfs_bmbt_irec bmap;
+
+ if (!xfs_rmap_update_is_needed(mp))
+ return 0;
+
+ bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
+ bmap.br_blockcount = len;
+ bmap.br_startoff = 0;
+ bmap.br_state = XFS_EXT_NORM;
+
+ return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
+ XFS_DATA_FORK, &bmap);
+}
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
new file mode 100644
index 000000000000..71cf99a4acba
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __XFS_RMAP_H__
+#define __XFS_RMAP_H__
+
+static inline void
+xfs_rmap_ag_owner(
+ struct xfs_owner_info *oi,
+ uint64_t owner)
+{
+ oi->oi_owner = owner;
+ oi->oi_offset = 0;
+ oi->oi_flags = 0;
+}
+
+static inline void
+xfs_rmap_ino_bmbt_owner(
+ struct xfs_owner_info *oi,
+ xfs_ino_t ino,
+ int whichfork)
+{
+ oi->oi_owner = ino;
+ oi->oi_offset = 0;
+ oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK;
+ if (whichfork == XFS_ATTR_FORK)
+ oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
+}
+
+static inline void
+xfs_rmap_ino_owner(
+ struct xfs_owner_info *oi,
+ xfs_ino_t ino,
+ int whichfork,
+ xfs_fileoff_t offset)
+{
+ oi->oi_owner = ino;
+ oi->oi_offset = offset;
+ oi->oi_flags = 0;
+ if (whichfork == XFS_ATTR_FORK)
+ oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
+}
+
+static inline void
+xfs_rmap_skip_owner_update(
+ struct xfs_owner_info *oi)
+{
+ oi->oi_owner = XFS_RMAP_OWN_UNKNOWN;
+}
+
+/* Reverse mapping functions. */
+
+struct xfs_buf;
+
+static inline __u64
+xfs_rmap_irec_offset_pack(
+ const struct xfs_rmap_irec *irec)
+{
+ __u64 x;
+
+ x = XFS_RMAP_OFF(irec->rm_offset);
+ if (irec->rm_flags & XFS_RMAP_ATTR_FORK)
+ x |= XFS_RMAP_OFF_ATTR_FORK;
+ if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)
+ x |= XFS_RMAP_OFF_BMBT_BLOCK;
+ if (irec->rm_flags & XFS_RMAP_UNWRITTEN)
+ x |= XFS_RMAP_OFF_UNWRITTEN;
+ return x;
+}
+
+static inline int
+xfs_rmap_irec_offset_unpack(
+ __u64 offset,
+ struct xfs_rmap_irec *irec)
+{
+ if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS))
+ return -EFSCORRUPTED;
+ irec->rm_offset = XFS_RMAP_OFF(offset);
+ if (offset & XFS_RMAP_OFF_ATTR_FORK)
+ irec->rm_flags |= XFS_RMAP_ATTR_FORK;
+ if (offset & XFS_RMAP_OFF_BMBT_BLOCK)
+ irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
+ if (offset & XFS_RMAP_OFF_UNWRITTEN)
+ irec->rm_flags |= XFS_RMAP_UNWRITTEN;
+ return 0;
+}
+
+static inline void
+xfs_owner_info_unpack(
+ struct xfs_owner_info *oinfo,
+ uint64_t *owner,
+ uint64_t *offset,
+ unsigned int *flags)
+{
+ unsigned int r = 0;
+
+ *owner = oinfo->oi_owner;
+ *offset = oinfo->oi_offset;
+ if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
+ r |= XFS_RMAP_ATTR_FORK;
+ if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
+ r |= XFS_RMAP_BMBT_BLOCK;
+ *flags = r;
+}
+
+static inline void
+xfs_owner_info_pack(
+ struct xfs_owner_info *oinfo,
+ uint64_t owner,
+ uint64_t offset,
+ unsigned int flags)
+{
+ oinfo->oi_owner = owner;
+ oinfo->oi_offset = XFS_RMAP_OFF(offset);
+ oinfo->oi_flags = 0;
+ if (flags & XFS_RMAP_ATTR_FORK)
+ oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK;
+ if (flags & XFS_RMAP_BMBT_BLOCK)
+ oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK;
+}
+
+int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp,
+ xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+ struct xfs_owner_info *oinfo);
+int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp,
+ xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+ struct xfs_owner_info *oinfo);
+
+int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+ xfs_extlen_t len, uint64_t owner, uint64_t offset,
+ unsigned int flags, int *stat);
+int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno,
+ xfs_extlen_t len, uint64_t owner, uint64_t offset,
+ unsigned int flags, int *stat);
+int xfs_rmap_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno,
+ xfs_extlen_t len, uint64_t owner, uint64_t offset,
+ unsigned int flags);
+int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec,
+ int *stat);
+
+typedef int (*xfs_rmap_query_range_fn)(
+ struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *rec,
+ void *priv);
+
+int xfs_rmap_query_range(struct xfs_btree_cur *cur,
+ struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec,
+ xfs_rmap_query_range_fn fn, void *priv);
+
+enum xfs_rmap_intent_type {
+ XFS_RMAP_MAP,
+ XFS_RMAP_MAP_SHARED,
+ XFS_RMAP_UNMAP,
+ XFS_RMAP_UNMAP_SHARED,
+ XFS_RMAP_CONVERT,
+ XFS_RMAP_CONVERT_SHARED,
+ XFS_RMAP_ALLOC,
+ XFS_RMAP_FREE,
+};
+
+struct xfs_rmap_intent {
+ struct list_head ri_list;
+ enum xfs_rmap_intent_type ri_type;
+ __uint64_t ri_owner;
+ int ri_whichfork;
+ struct xfs_bmbt_irec ri_bmap;
+};
+
+/* functions for updating the rmapbt based on bmbt map/unmap operations */
+int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip, int whichfork,
+ struct xfs_bmbt_irec *imap);
+int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip, int whichfork,
+ struct xfs_bmbt_irec *imap);
+int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ struct xfs_inode *ip, int whichfork,
+ struct xfs_bmbt_irec *imap);
+int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+ __uint64_t owner);
+int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
+ xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
+ __uint64_t owner);
+
+void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
+ struct xfs_btree_cur *rcur, int error);
+int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type,
+ __uint64_t owner, int whichfork, xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock, xfs_filblks_t blockcount,
+ xfs_exntst_t state, struct xfs_btree_cur **pcur);
+
+#endif /* __XFS_RMAP_H__ */
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
new file mode 100644
index 000000000000..bc1faebc84ec
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (c) 2014 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_inode.h"
+#include "xfs_trans.h"
+#include "xfs_alloc.h"
+#include "xfs_btree.h"
+#include "xfs_rmap.h"
+#include "xfs_rmap_btree.h"
+#include "xfs_trace.h"
+#include "xfs_cksum.h"
+#include "xfs_error.h"
+#include "xfs_extent_busy.h"
+
+/*
+ * Reverse map btree.
+ *
+ * This is a per-ag tree used to track the owner(s) of a given extent. With
+ * reflink it is possible for there to be multiple owners, which is a departure
+ * from classic XFS. Owner records for data extents are inserted when the
+ * extent is mapped and removed when an extent is unmapped. Owner records for
+ * all other block types (i.e. metadata) are inserted when an extent is
+ * allocated and removed when an extent is freed. There can only be one owner
+ * of a metadata extent, usually an inode or some other metadata structure like
+ * an AG btree.
+ *
+ * The rmap btree is part of the free space management, so blocks for the tree
+ * are sourced from the agfl. Hence we need transaction reservation support for
+ * this tree so that the freelist is always large enough. This also impacts on
+ * the minimum space we need to leave free in the AG.
+ *
+ * The tree is ordered by [ag block, owner, offset]. This is a large key size,
+ * but it is the only way to enforce unique keys when a block can be owned by
+ * multiple files at any offset. There's no need to order/search by extent
+ * size for online updating/management of the tree. It is intended that most
+ * reverse lookups will be to find the owner(s) of a particular block, or to
+ * try to recover tree and file data from corrupt primary metadata.
+ */
+
+static struct xfs_btree_cur *
+xfs_rmapbt_dup_cursor(
+ struct xfs_btree_cur *cur)
+{
+ return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp,
+ cur->bc_private.a.agbp, cur->bc_private.a.agno);
+}
+
+STATIC void
+xfs_rmapbt_set_root(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *ptr,
+ int inc)
+{
+ struct xfs_buf *agbp = cur->bc_private.a.agbp;
+ struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
+ xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno);
+ int btnum = cur->bc_btnum;
+ struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno);
+
+ ASSERT(ptr->s != 0);
+
+ agf->agf_roots[btnum] = ptr->s;
+ be32_add_cpu(&agf->agf_levels[btnum], inc);
+ pag->pagf_levels[btnum] += inc;
+ xfs_perag_put(pag);
+
+ xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS);
+}
+
+STATIC int
+xfs_rmapbt_alloc_block(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *start,
+ union xfs_btree_ptr *new,
+ int *stat)
+{
+ int error;
+ xfs_agblock_t bno;
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
+
+ /* Allocate the new block from the freelist. If we can't, give up. */
+ error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
+ &bno, 1);
+ if (error) {
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
+ return error;
+ }
+
+ trace_xfs_rmapbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno,
+ bno, 1);
+ if (bno == NULLAGBLOCK) {
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+ *stat = 0;
+ return 0;
+ }
+
+ xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1,
+ false);
+
+ xfs_trans_agbtree_delta(cur->bc_tp, 1);
+ new->s = cpu_to_be32(bno);
+
+ XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
+ *stat = 1;
+ return 0;
+}
+
+STATIC int
+xfs_rmapbt_free_block(
+ struct xfs_btree_cur *cur,
+ struct xfs_buf *bp)
+{
+ struct xfs_buf *agbp = cur->bc_private.a.agbp;
+ struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
+ xfs_agblock_t bno;
+ int error;
+
+ bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp));
+ trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno,
+ bno, 1);
+ error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1);
+ if (error)
+ return error;
+
+ xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
+ XFS_EXTENT_BUSY_SKIP_DISCARD);
+ xfs_trans_agbtree_delta(cur->bc_tp, -1);
+
+ return 0;
+}
+
+STATIC int
+xfs_rmapbt_get_minrecs(
+ struct xfs_btree_cur *cur,
+ int level)
+{
+ return cur->bc_mp->m_rmap_mnr[level != 0];
+}
+
+STATIC int
+xfs_rmapbt_get_maxrecs(
+ struct xfs_btree_cur *cur,
+ int level)
+{
+ return cur->bc_mp->m_rmap_mxr[level != 0];
+}
+
+STATIC void
+xfs_rmapbt_init_key_from_rec(
+ union xfs_btree_key *key,
+ union xfs_btree_rec *rec)
+{
+ key->rmap.rm_startblock = rec->rmap.rm_startblock;
+ key->rmap.rm_owner = rec->rmap.rm_owner;
+ key->rmap.rm_offset = rec->rmap.rm_offset;
+}
+
+/*
+ * The high key for a reverse mapping record can be computed by shifting
+ * the startblock and offset to the highest value that would still map
+ * to that record. In practice this means that we add blockcount-1 to
+ * the startblock for all records, and if the record is for a data/attr
+ * fork mapping, we add blockcount-1 to the offset too.
+ */
+STATIC void
+xfs_rmapbt_init_high_key_from_rec(
+ union xfs_btree_key *key,
+ union xfs_btree_rec *rec)
+{
+ __uint64_t off;
+ int adj;
+
+ adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1;
+
+ key->rmap.rm_startblock = rec->rmap.rm_startblock;
+ be32_add_cpu(&key->rmap.rm_startblock, adj);
+ key->rmap.rm_owner = rec->rmap.rm_owner;
+ key->rmap.rm_offset = rec->rmap.rm_offset;
+ if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) ||
+ XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset)))
+ return;
+ off = be64_to_cpu(key->rmap.rm_offset);
+ off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK);
+ key->rmap.rm_offset = cpu_to_be64(off);
+}
+
+STATIC void
+xfs_rmapbt_init_rec_from_cur(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *rec)
+{
+ rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock);
+ rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount);
+ rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner);
+ rec->rmap.rm_offset = cpu_to_be64(
+ xfs_rmap_irec_offset_pack(&cur->bc_rec.r));
+}
+
+STATIC void
+xfs_rmapbt_init_ptr_from_cur(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_ptr *ptr)
+{
+ struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
+
+ ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
+ ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
+
+ ptr->s = agf->agf_roots[cur->bc_btnum];
+}
+
+STATIC __int64_t
+xfs_rmapbt_key_diff(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *key)
+{
+ struct xfs_rmap_irec *rec = &cur->bc_rec.r;
+ struct xfs_rmap_key *kp = &key->rmap;
+ __u64 x, y;
+ __int64_t d;
+
+ d = (__int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock;
+ if (d)
+ return d;
+
+ x = be64_to_cpu(kp->rm_owner);
+ y = rec->rm_owner;
+ if (x > y)
+ return 1;
+ else if (y > x)
+ return -1;
+
+ x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset));
+ y = rec->rm_offset;
+ if (x > y)
+ return 1;
+ else if (y > x)
+ return -1;
+ return 0;
+}
+
+STATIC __int64_t
+xfs_rmapbt_diff_two_keys(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *k1,
+ union xfs_btree_key *k2)
+{
+ struct xfs_rmap_key *kp1 = &k1->rmap;
+ struct xfs_rmap_key *kp2 = &k2->rmap;
+ __int64_t d;
+ __u64 x, y;
+
+ d = (__int64_t)be32_to_cpu(kp1->rm_startblock) -
+ be32_to_cpu(kp2->rm_startblock);
+ if (d)
+ return d;
+
+ x = be64_to_cpu(kp1->rm_owner);
+ y = be64_to_cpu(kp2->rm_owner);
+ if (x > y)
+ return 1;
+ else if (y > x)
+ return -1;
+
+ x = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset));
+ y = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset));
+ if (x > y)
+ return 1;
+ else if (y > x)
+ return -1;
+ return 0;
+}
+
+static bool
+xfs_rmapbt_verify(
+ struct xfs_buf *bp)
+{
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+ struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
+ struct xfs_perag *pag = bp->b_pag;
+ unsigned int level;
+
+ /*
+ * magic number and level verification
+ *
+ * During growfs operations, we can't verify the exact level or owner as
+ * the perag is not fully initialised and hence not attached to the
+ * buffer. In this case, check against the maximum tree depth.
+ *
+ * Similarly, during log recovery we will have a perag structure
+ * attached, but the agf information will not yet have been initialised
+ * from the on disk AGF. Again, we can only check against maximum limits
+ * in this case.
+ */
+ if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC))
+ return false;
+
+ if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return false;
+ if (!xfs_btree_sblock_v5hdr_verify(bp))
+ return false;
+
+ level = be16_to_cpu(block->bb_level);
+ if (pag && pag->pagf_init) {
+ if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi])
+ return false;
+ } else if (level >= mp->m_rmap_maxlevels)
+ return false;
+
+ return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]);
+}
+
+static void
+xfs_rmapbt_read_verify(
+ struct xfs_buf *bp)
+{
+ if (!xfs_btree_sblock_verify_crc(bp))
+ xfs_buf_ioerror(bp, -EFSBADCRC);
+ else if (!xfs_rmapbt_verify(bp))
+ xfs_buf_ioerror(bp, -EFSCORRUPTED);
+
+ if (bp->b_error) {
+ trace_xfs_btree_corrupt(bp, _RET_IP_);
+ xfs_verifier_error(bp);
+ }
+}
+
+static void
+xfs_rmapbt_write_verify(
+ struct xfs_buf *bp)
+{
+ if (!xfs_rmapbt_verify(bp)) {
+ trace_xfs_btree_corrupt(bp, _RET_IP_);
+ xfs_buf_ioerror(bp, -EFSCORRUPTED);
+ xfs_verifier_error(bp);
+ return;
+ }
+ xfs_btree_sblock_calc_crc(bp);
+
+}
+
+const struct xfs_buf_ops xfs_rmapbt_buf_ops = {
+ .name = "xfs_rmapbt",
+ .verify_read = xfs_rmapbt_read_verify,
+ .verify_write = xfs_rmapbt_write_verify,
+};
+
+#if defined(DEBUG) || defined(XFS_WARN)
+STATIC int
+xfs_rmapbt_keys_inorder(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_key *k1,
+ union xfs_btree_key *k2)
+{
+ __uint32_t x;
+ __uint32_t y;
+ __uint64_t a;
+ __uint64_t b;
+
+ x = be32_to_cpu(k1->rmap.rm_startblock);
+ y = be32_to_cpu(k2->rmap.rm_startblock);
+ if (x < y)
+ return 1;
+ else if (x > y)
+ return 0;
+ a = be64_to_cpu(k1->rmap.rm_owner);
+ b = be64_to_cpu(k2->rmap.rm_owner);
+ if (a < b)
+ return 1;
+ else if (a > b)
+ return 0;
+ a = XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset));
+ b = XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset));
+ if (a <= b)
+ return 1;
+ return 0;
+}
+
+STATIC int
+xfs_rmapbt_recs_inorder(
+ struct xfs_btree_cur *cur,
+ union xfs_btree_rec *r1,
+ union xfs_btree_rec *r2)
+{
+ __uint32_t x;
+ __uint32_t y;
+ __uint64_t a;
+ __uint64_t b;
+
+ x = be32_to_cpu(r1->rmap.rm_startblock);
+ y = be32_to_cpu(r2->rmap.rm_startblock);
+ if (x < y)
+ return 1;
+ else if (x > y)
+ return 0;
+ a = be64_to_cpu(r1->rmap.rm_owner);
+ b = be64_to_cpu(r2->rmap.rm_owner);
+ if (a < b)
+ return 1;
+ else if (a > b)
+ return 0;
+ a = XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset));
+ b = XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset));
+ if (a <= b)
+ return 1;
+ return 0;
+}
+#endif /* DEBUG */
+
+static const struct xfs_btree_ops xfs_rmapbt_ops = {
+ .rec_len = sizeof(struct xfs_rmap_rec),
+ .key_len = 2 * sizeof(struct xfs_rmap_key),
+
+ .dup_cursor = xfs_rmapbt_dup_cursor,
+ .set_root = xfs_rmapbt_set_root,
+ .alloc_block = xfs_rmapbt_alloc_block,
+ .free_block = xfs_rmapbt_free_block,
+ .get_minrecs = xfs_rmapbt_get_minrecs,
+ .get_maxrecs = xfs_rmapbt_get_maxrecs,
+ .init_key_from_rec = xfs_rmapbt_init_key_from_rec,
+ .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec,
+ .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur,
+ .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur,
+ .key_diff = xfs_rmapbt_key_diff,
+ .buf_ops = &xfs_rmapbt_buf_ops,
+ .diff_two_keys = xfs_rmapbt_diff_two_keys,
+#if defined(DEBUG) || defined(XFS_WARN)
+ .keys_inorder = xfs_rmapbt_keys_inorder,
+ .recs_inorder = xfs_rmapbt_recs_inorder,
+#endif
+};
+
+/*
+ * Allocate a new allocation btree cursor.
+ */
+struct xfs_btree_cur *
+xfs_rmapbt_init_cursor(
+ struct xfs_mount *mp,
+ struct xfs_trans *tp,
+ struct xfs_buf *agbp,
+ xfs_agnumber_t agno)
+{
+ struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
+ struct xfs_btree_cur *cur;
+
+ cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
+ cur->bc_tp = tp;
+ cur->bc_mp = mp;
+ /* Overlapping btree; 2 keys per pointer. */
+ cur->bc_btnum = XFS_BTNUM_RMAP;
+ cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING;
+ cur->bc_blocklog = mp->m_sb.sb_blocklog;
+ cur->bc_ops = &xfs_rmapbt_ops;
+ cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
+
+ cur->bc_private.a.agbp = agbp;
+ cur->bc_private.a.agno = agno;
+
+ return cur;
+}
+
+/*
+ * Calculate number of records in an rmap btree block.
+ */
+int
+xfs_rmapbt_maxrecs(
+ struct xfs_mount *mp,
+ int blocklen,
+ int leaf)
+{
+ blocklen -= XFS_RMAP_BLOCK_LEN;
+
+ if (leaf)
+ return blocklen / sizeof(struct xfs_rmap_rec);
+ return blocklen /
+ (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t));
+}
+
+/* Compute the maximum height of an rmap btree. */
+void
+xfs_rmapbt_compute_maxlevels(
+ struct xfs_mount *mp)
+{
+ mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp,
+ mp->m_rmap_mnr, mp->m_sb.sb_agblocks);
+}
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
new file mode 100644
index 000000000000..e73a55357dab
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __XFS_RMAP_BTREE_H__
+#define __XFS_RMAP_BTREE_H__
+
+struct xfs_buf;
+struct xfs_btree_cur;
+struct xfs_mount;
+
+/* rmaps only exist on crc enabled filesystems */
+#define XFS_RMAP_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN
+
+/*
+ * Record, key, and pointer address macros for btree blocks.
+ *
+ * (note that some of these may appear unused, but they are used in userspace)
+ */
+#define XFS_RMAP_REC_ADDR(block, index) \
+ ((struct xfs_rmap_rec *) \
+ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
+ (((index) - 1) * sizeof(struct xfs_rmap_rec))))
+
+#define XFS_RMAP_KEY_ADDR(block, index) \
+ ((struct xfs_rmap_key *) \
+ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
+ ((index) - 1) * 2 * sizeof(struct xfs_rmap_key)))
+
+#define XFS_RMAP_HIGH_KEY_ADDR(block, index) \
+ ((struct xfs_rmap_key *) \
+ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
+ sizeof(struct xfs_rmap_key) + \
+ ((index) - 1) * 2 * sizeof(struct xfs_rmap_key)))
+
+#define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \
+ ((xfs_rmap_ptr_t *) \
+ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \
+ (maxrecs) * 2 * sizeof(struct xfs_rmap_key) + \
+ ((index) - 1) * sizeof(xfs_rmap_ptr_t)))
+
+struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp,
+ struct xfs_trans *tp, struct xfs_buf *bp,
+ xfs_agnumber_t agno);
+int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf);
+extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp);
+
+#endif /* __XFS_RMAP_BTREE_H__ */
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index 12ca86778e02..0e3d4f5ec33c 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -24,6 +24,7 @@
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_ialloc.h"
#include "xfs_alloc.h"
@@ -36,6 +37,7 @@
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_log.h"
+#include "xfs_rmap_btree.h"
/*
* Physical superblock buffer manipulations. Shared with libxfs in userspace.
@@ -729,6 +731,11 @@ xfs_sb_mount_common(
mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2;
mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2;
+ mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 1);
+ mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 0);
+ mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2;
+ mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2;
+
mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
sbp->sb_inopblock);
@@ -738,6 +745,8 @@ xfs_sb_mount_common(
mp->m_ialloc_min_blks = sbp->sb_spino_align;
else
mp->m_ialloc_min_blks = mp->m_ialloc_blks;
+ mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
+ mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp);
}
/*
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index 16002b5ec4eb..0c5b30bd884c 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -38,6 +38,7 @@ extern const struct xfs_buf_ops xfs_agi_buf_ops;
extern const struct xfs_buf_ops xfs_agf_buf_ops;
extern const struct xfs_buf_ops xfs_agfl_buf_ops;
extern const struct xfs_buf_ops xfs_allocbt_buf_ops;
+extern const struct xfs_buf_ops xfs_rmapbt_buf_ops;
extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops;
extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
extern const struct xfs_buf_ops xfs_bmbt_buf_ops;
@@ -116,6 +117,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *);
#define XFS_INO_BTREE_REF 3
#define XFS_ALLOC_BTREE_REF 2
#define XFS_BMAP_BTREE_REF 2
+#define XFS_RMAP_BTREE_REF 2
#define XFS_DIR_BTREE_REF 2
#define XFS_INO_REF 2
#define XFS_ATTR_BTREE_REF 1
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 68cb1e7bf2bb..301ef2f4dbd6 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -64,6 +64,30 @@ xfs_calc_buf_res(
}
/*
+ * Per-extent log reservation for the btree changes involved in freeing or
+ * allocating an extent. In classic XFS there were two trees that will be
+ * modified (bnobt + cntbt). With rmap enabled, there are three trees
+ * (rmapbt). The number of blocks reserved is based on the formula:
+ *
+ * num trees * ((2 blocks/level * max depth) - 1)
+ *
+ * Keep in mind that max depth is calculated separately for each type of tree.
+ */
+static uint
+xfs_allocfree_log_count(
+ struct xfs_mount *mp,
+ uint num_ops)
+{
+ uint blocks;
+
+ blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1);
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
+
+ return blocks;
+}
+
+/*
* Logging inodes is really tricksy. They are logged in memory format,
* which means that what we write into the log doesn't directly translate into
* the amount of space they use on disk.
@@ -126,7 +150,7 @@ xfs_calc_inode_res(
*/
STATIC uint
xfs_calc_finobt_res(
- struct xfs_mount *mp,
+ struct xfs_mount *mp,
int alloc,
int modify)
{
@@ -137,7 +161,7 @@ xfs_calc_finobt_res(
res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1));
if (alloc)
- res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ res += xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1));
if (modify)
res += (uint)XFS_FSB_TO_B(mp, 1);
@@ -153,9 +177,9 @@ xfs_calc_finobt_res(
* item logged to try to account for the overhead of the transaction mechanism.
*
* Note: Most of the reservations underestimate the number of allocation
- * groups into which they could free extents in the xfs_bmap_finish() call.
+ * groups into which they could free extents in the xfs_defer_finish() call.
* This is because the number in the worst case is quite high and quite
- * unusual. In order to fix this we need to change xfs_bmap_finish() to free
+ * unusual. In order to fix this we need to change xfs_defer_finish() to free
* extents in only a single AG at a time. This will require changes to the
* EFI code as well, however, so that the EFI for the extents not freed is
* logged again in each transaction. See SGI PV #261917.
@@ -188,10 +212,10 @@ xfs_calc_write_reservation(
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
XFS_FSB_TO_B(mp, 1))));
}
@@ -217,10 +241,10 @@ xfs_calc_itruncate_reservation(
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(5, 0) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(2 + mp->m_ialloc_blks +
mp->m_in_maxlevels, 0)));
@@ -247,7 +271,7 @@ xfs_calc_rename_reservation(
xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 3),
XFS_FSB_TO_B(mp, 1))));
}
@@ -286,7 +310,7 @@ xfs_calc_link_reservation(
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1))));
}
@@ -324,7 +348,7 @@ xfs_calc_remove_reservation(
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
XFS_FSB_TO_B(mp, 1))));
}
@@ -371,7 +395,7 @@ xfs_calc_create_resv_alloc(
mp->m_sb.sb_sectsize +
xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1));
}
@@ -399,7 +423,7 @@ xfs_calc_icreate_resv_alloc(
return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
mp->m_sb.sb_sectsize +
xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_finobt_res(mp, 0, 0);
}
@@ -483,7 +507,7 @@ xfs_calc_ifree_reservation(
xfs_calc_buf_res(1, 0) +
xfs_calc_buf_res(2 + mp->m_ialloc_blks +
mp->m_in_maxlevels, 0) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_finobt_res(mp, 0, 1);
}
@@ -513,7 +537,7 @@ xfs_calc_growdata_reservation(
struct xfs_mount *mp)
{
return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1));
}
@@ -535,7 +559,7 @@ xfs_calc_growrtalloc_reservation(
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_inode_res(mp, 1) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1));
}
@@ -611,7 +635,7 @@ xfs_calc_addafork_reservation(
xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
XFS_FSB_TO_B(mp, 1)) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
XFS_FSB_TO_B(mp, 1));
}
@@ -634,7 +658,7 @@ xfs_calc_attrinval_reservation(
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
XFS_FSB_TO_B(mp, 1))));
}
@@ -701,7 +725,7 @@ xfs_calc_attrrm_reservation(
XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
(xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
- xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+ xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
XFS_FSB_TO_B(mp, 1))));
}
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
index 797815012c0e..0eb46ed6d404 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.h
+++ b/fs/xfs/libxfs/xfs_trans_resv.h
@@ -68,16 +68,6 @@ struct xfs_trans_resv {
#define M_RES(mp) (&(mp)->m_resv)
/*
- * Per-extent log reservation for the allocation btree changes
- * involved in freeing or allocating an extent.
- * 2 trees * (2 blocks/level * max depth - 1) * block size
- */
-#define XFS_ALLOCFREE_LOG_RES(mp,nx) \
- ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * (mp)->m_ag_maxlevels - 1)))
-#define XFS_ALLOCFREE_LOG_COUNT(mp,nx) \
- ((nx) * (2 * (2 * (mp)->m_ag_maxlevels - 1)))
-
-/*
* Per-directory log reservation for any directory change.
* dir blocks: (1 btree block per level + data block + free block) * dblock size
* bmap btree: (levels + 2) * max depth * block size
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index b79dc66b2ecd..3d503647f26b 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -108,8 +108,8 @@ typedef enum {
} xfs_lookup_t;
typedef enum {
- XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi,
- XFS_BTNUM_FINOi, XFS_BTNUM_MAX
+ XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi,
+ XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX
} xfs_btnum_t;
struct xfs_name {
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index cd4a850564f2..4ece4f2ffc72 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -25,6 +25,7 @@
#include "xfs_bit.h"
#include "xfs_mount.h"
#include "xfs_da_format.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_trans.h"
@@ -40,6 +41,7 @@
#include "xfs_trace.h"
#include "xfs_icache.h"
#include "xfs_log.h"
+#include "xfs_rmap_btree.h"
/* Kernel only BMAP related definitions and functions */
@@ -79,95 +81,6 @@ xfs_zero_extent(
GFP_NOFS, true);
}
-/* Sort bmap items by AG. */
-static int
-xfs_bmap_free_list_cmp(
- void *priv,
- struct list_head *a,
- struct list_head *b)
-{
- struct xfs_mount *mp = priv;
- struct xfs_bmap_free_item *ra;
- struct xfs_bmap_free_item *rb;
-
- ra = container_of(a, struct xfs_bmap_free_item, xbfi_list);
- rb = container_of(b, struct xfs_bmap_free_item, xbfi_list);
- return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) -
- XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock);
-}
-
-/*
- * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
- * caller. Frees all the extents that need freeing, which must be done
- * last due to locking considerations. We never free any extents in
- * the first transaction.
- *
- * If an inode *ip is provided, rejoin it to the transaction if
- * the transaction was committed.
- */
-int /* error */
-xfs_bmap_finish(
- struct xfs_trans **tp, /* transaction pointer addr */
- struct xfs_bmap_free *flist, /* i/o: list extents to free */
- struct xfs_inode *ip)
-{
- struct xfs_efd_log_item *efd; /* extent free data */
- struct xfs_efi_log_item *efi; /* extent free intention */
- int error; /* error return value */
- int committed;/* xact committed or not */
- struct xfs_bmap_free_item *free; /* free extent item */
-
- ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES);
- if (flist->xbf_count == 0)
- return 0;
-
- list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp);
-
- efi = xfs_trans_get_efi(*tp, flist->xbf_count);
- list_for_each_entry(free, &flist->xbf_flist, xbfi_list)
- xfs_trans_log_efi_extent(*tp, efi, free->xbfi_startblock,
- free->xbfi_blockcount);
-
- error = __xfs_trans_roll(tp, ip, &committed);
- if (error) {
- /*
- * If the transaction was committed, drop the EFD reference
- * since we're bailing out of here. The other reference is
- * dropped when the EFI hits the AIL.
- *
- * If the transaction was not committed, the EFI is freed by the
- * EFI item unlock handler on abort. Also, we have a new
- * transaction so we should return committed=1 even though we're
- * returning an error.
- */
- if (committed) {
- xfs_efi_release(efi);
- xfs_force_shutdown((*tp)->t_mountp,
- SHUTDOWN_META_IO_ERROR);
- }
- return error;
- }
-
- /*
- * Get an EFD and free each extent in the list, logging to the EFD in
- * the process. The remaining bmap free list is cleaned up by the caller
- * on error.
- */
- efd = xfs_trans_get_efd(*tp, efi, flist->xbf_count);
- while (!list_empty(&flist->xbf_flist)) {
- free = list_first_entry(&flist->xbf_flist,
- struct xfs_bmap_free_item, xbfi_list);
- error = xfs_trans_free_extent(*tp, efd, free->xbfi_startblock,
- free->xbfi_blockcount);
- if (error)
- return error;
-
- xfs_bmap_del_free(flist, free);
- }
-
- return 0;
-}
-
int
xfs_bmap_rtalloc(
struct xfs_bmalloca *ap) /* bmap alloc argument struct */
@@ -214,9 +127,9 @@ xfs_bmap_rtalloc(
/*
* Lock out modifications to both the RT bitmap and summary inodes
*/
- xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP);
xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
- xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
+ xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM);
xfs_trans_ijoin(ap->tp, mp->m_rsumip, XFS_ILOCK_EXCL);
/*
@@ -773,7 +686,7 @@ xfs_bmap_punch_delalloc_range(
xfs_bmbt_irec_t imap;
int nimaps = 1;
xfs_fsblock_t firstblock;
- xfs_bmap_free_t flist;
+ struct xfs_defer_ops dfops;
/*
* Map the range first and check that it is a delalloc extent
@@ -804,18 +717,18 @@ xfs_bmap_punch_delalloc_range(
WARN_ON(imap.br_blockcount == 0);
/*
- * Note: while we initialise the firstblock/flist pair, they
+ * Note: while we initialise the firstblock/dfops pair, they
* should never be used because blocks should never be
* allocated or freed for a delalloc extent and hence we need
* don't cancel or finish them after the xfs_bunmapi() call.
*/
- xfs_bmap_init(&flist, &firstblock);
+ xfs_defer_init(&dfops, &firstblock);
error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock,
- &flist, &done);
+ &dfops, &done);
if (error)
break;
- ASSERT(!flist.xbf_count && list_empty(&flist.xbf_flist));
+ ASSERT(!xfs_defer_has_unfinished_work(&dfops));
next_block:
start_fsb++;
remaining--;
@@ -972,7 +885,7 @@ xfs_alloc_file_space(
int rt;
xfs_trans_t *tp;
xfs_bmbt_irec_t imaps[1], *imapp;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
uint qblocks, resblks, resrtextents;
int error;
@@ -1063,17 +976,17 @@ xfs_alloc_file_space(
xfs_trans_ijoin(tp, ip, 0);
- xfs_bmap_init(&free_list, &firstfsb);
+ xfs_defer_init(&dfops, &firstfsb);
error = xfs_bmapi_write(tp, ip, startoffset_fsb,
allocatesize_fsb, alloc_type, &firstfsb,
- resblks, imapp, &nimaps, &free_list);
+ resblks, imapp, &nimaps, &dfops);
if (error)
goto error0;
/*
* Complete the transaction
*/
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto error0;
@@ -1096,7 +1009,7 @@ xfs_alloc_file_space(
return error;
error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
error1: /* Just cancel transaction */
@@ -1114,7 +1027,7 @@ xfs_unmap_extent(
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
- struct xfs_bmap_free free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t firstfsb;
uint resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
int error;
@@ -1133,13 +1046,13 @@ xfs_unmap_extent(
xfs_trans_ijoin(tp, ip, 0);
- xfs_bmap_init(&free_list, &firstfsb);
+ xfs_defer_init(&dfops, &firstfsb);
error = xfs_bunmapi(tp, ip, startoffset_fsb, len_fsb, 0, 2, &firstfsb,
- &free_list, done);
+ &dfops, done);
if (error)
goto out_bmap_cancel;
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, ip);
if (error)
goto out_bmap_cancel;
@@ -1149,7 +1062,7 @@ out_unlock:
return error;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
goto out_unlock;
@@ -1338,7 +1251,7 @@ xfs_shift_file_space(
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
int error;
- struct xfs_bmap_free free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
xfs_fileoff_t stop_fsb;
xfs_fileoff_t next_fsb;
@@ -1416,19 +1329,19 @@ xfs_shift_file_space(
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/*
* We are using the write transaction in which max 2 bmbt
* updates are allowed
*/
error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
- &done, stop_fsb, &first_block, &free_list,
+ &done, stop_fsb, &first_block, &dfops,
direction, XFS_BMAP_MAX_SHIFT_EXTENTS);
if (error)
goto out_bmap_cancel;
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
@@ -1438,7 +1351,7 @@ xfs_shift_file_space(
return error;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
return error;
@@ -1622,6 +1535,10 @@ xfs_swap_extents(
__uint64_t tmp;
int lock_flags;
+ /* XXX: we can't do this with rmap, will fix later */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ return -EOPNOTSUPP;
+
tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
if (!tempifp) {
error = -ENOMEM;
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index f20071432ca6..68a621a8e0c0 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -21,7 +21,7 @@
/* Kernel only BMAP related definitions and functions */
struct xfs_bmbt_irec;
-struct xfs_bmap_free_item;
+struct xfs_extent_free_item;
struct xfs_ifork;
struct xfs_inode;
struct xfs_mount;
@@ -40,8 +40,6 @@ int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv,
xfs_bmap_format_t formatter, void *arg);
/* functions in xfs_bmap.c that are only needed by xfs_bmap_util.c */
-void xfs_bmap_del_free(struct xfs_bmap_free *flist,
- struct xfs_bmap_free_item *free);
int xfs_bmap_extsize_align(struct xfs_mount *mp, struct xfs_bmbt_irec *gotp,
struct xfs_bmbt_irec *prevp, xfs_extlen_t extsz,
int rt, int eof, int delay, int convert,
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 272c3f8b6f7d..4ff499aa7338 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -179,7 +179,7 @@ xfs_ioc_trim(
* matter as trimming blocks is an advisory interface.
*/
if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
- range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)) ||
+ range.minlen > XFS_FSB_TO_B(mp, mp->m_ag_max_usable) ||
range.len < mp->m_sb.sb_blocksize)
return -EINVAL;
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index ccb0811963b2..7a30b8f11db7 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
#include "xfs_bmap_util.h"
@@ -307,7 +308,7 @@ xfs_qm_dqalloc(
xfs_buf_t **O_bpp)
{
xfs_fsblock_t firstblock;
- xfs_bmap_free_t flist;
+ struct xfs_defer_ops dfops;
xfs_bmbt_irec_t map;
int nmaps, error;
xfs_buf_t *bp;
@@ -320,7 +321,7 @@ xfs_qm_dqalloc(
/*
* Initialize the bmap freelist prior to calling bmapi code.
*/
- xfs_bmap_init(&flist, &firstblock);
+ xfs_defer_init(&dfops, &firstblock);
xfs_ilock(quotip, XFS_ILOCK_EXCL);
/*
* Return if this type of quotas is turned off while we didn't
@@ -336,7 +337,7 @@ xfs_qm_dqalloc(
error = xfs_bmapi_write(tp, quotip, offset_fsb,
XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA,
&firstblock, XFS_QM_DQALLOC_SPACE_RES(mp),
- &map, &nmaps, &flist);
+ &map, &nmaps, &dfops);
if (error)
goto error0;
ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
@@ -368,7 +369,7 @@ xfs_qm_dqalloc(
dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
/*
- * xfs_bmap_finish() may commit the current transaction and
+ * xfs_defer_finish() may commit the current transaction and
* start a second transaction if the freelist is not empty.
*
* Since we still want to modify this buffer, we need to
@@ -382,7 +383,7 @@ xfs_qm_dqalloc(
xfs_trans_bhold(tp, bp);
- error = xfs_bmap_finish(tpp, &flist, NULL);
+ error = xfs_defer_finish(tpp, &dfops, NULL);
if (error)
goto error1;
@@ -398,7 +399,7 @@ xfs_qm_dqalloc(
return 0;
error1:
- xfs_bmap_cancel(&flist);
+ xfs_defer_cancel(&dfops);
error0:
xfs_iunlock(quotip, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 2e4f67f68856..3d224702fbc0 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -90,7 +90,9 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
#define XFS_ERRTAG_STRATCMPL_IOERR 19
#define XFS_ERRTAG_DIOWRITE_IOERR 20
#define XFS_ERRTAG_BMAPIFORMAT 21
-#define XFS_ERRTAG_MAX 22
+#define XFS_ERRTAG_FREE_EXTENT 22
+#define XFS_ERRTAG_RMAP_FINISH_ONE 23
+#define XFS_ERRTAG_MAX 24
/*
* Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -117,6 +119,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
#define XFS_RANDOM_STRATCMPL_IOERR (XFS_RANDOM_DEFAULT/10)
#define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10)
#define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT
+#define XFS_RANDOM_FREE_EXTENT 1
+#define XFS_RANDOM_RMAP_FINISH_ONE 1
#ifdef DEBUG
extern int xfs_error_test_active;
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index a1b2dd828b9d..fe1bfee35898 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -246,7 +246,7 @@ const struct export_operations xfs_export_operations = {
.fh_to_parent = xfs_fs_fh_to_parent,
.get_parent = xfs_fs_get_parent,
.commit_metadata = xfs_fs_nfs_commit_metadata,
-#ifdef CONFIG_NFSD_BLOCKLAYOUT
+#ifdef CONFIG_EXPORTFS_BLOCK_OPS
.get_uuid = xfs_fs_get_uuid,
.map_blocks = xfs_fs_map_blocks,
.commit_blocks = xfs_fs_commit_blocks,
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index ab779460ecbf..d7bc14906af8 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -20,12 +20,15 @@
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
#include "xfs_mount.h"
#include "xfs_trans.h"
#include "xfs_trans_priv.h"
#include "xfs_buf_item.h"
#include "xfs_extfree_item.h"
#include "xfs_log.h"
+#include "xfs_btree.h"
+#include "xfs_rmap.h"
kmem_zone_t *xfs_efi_zone;
@@ -486,3 +489,69 @@ xfs_efd_init(
return efdp;
}
+
+/*
+ * Process an extent free intent item that was recovered from
+ * the log. We need to free the extents that it describes.
+ */
+int
+xfs_efi_recover(
+ struct xfs_mount *mp,
+ struct xfs_efi_log_item *efip)
+{
+ struct xfs_efd_log_item *efdp;
+ struct xfs_trans *tp;
+ int i;
+ int error = 0;
+ xfs_extent_t *extp;
+ xfs_fsblock_t startblock_fsb;
+ struct xfs_owner_info oinfo;
+
+ ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));
+
+ /*
+ * First check the validity of the extents described by the
+ * EFI. If any are bad, then assume that all are bad and
+ * just toss the EFI.
+ */
+ for (i = 0; i < efip->efi_format.efi_nextents; i++) {
+ extp = &efip->efi_format.efi_extents[i];
+ startblock_fsb = XFS_BB_TO_FSB(mp,
+ XFS_FSB_TO_DADDR(mp, extp->ext_start));
+ if (startblock_fsb == 0 ||
+ extp->ext_len == 0 ||
+ startblock_fsb >= mp->m_sb.sb_dblocks ||
+ extp->ext_len >= mp->m_sb.sb_agblocks) {
+ /*
+ * This will pull the EFI from the AIL and
+ * free the memory associated with it.
+ */
+ set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
+ xfs_efi_release(efip);
+ return -EIO;
+ }
+ }
+
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+ if (error)
+ return error;
+ efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
+
+ xfs_rmap_skip_owner_update(&oinfo);
+ for (i = 0; i < efip->efi_format.efi_nextents; i++) {
+ extp = &efip->efi_format.efi_extents[i];
+ error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
+ extp->ext_len, &oinfo);
+ if (error)
+ goto abort_error;
+
+ }
+
+ set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
+ error = xfs_trans_commit(tp);
+ return error;
+
+abort_error:
+ xfs_trans_cancel(tp);
+ return error;
+}
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 8fa8651705e1..a32c794a86b7 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -98,4 +98,7 @@ int xfs_efi_copy_format(xfs_log_iovec_t *buf,
void xfs_efi_item_free(xfs_efi_log_item_t *);
void xfs_efi_release(struct xfs_efi_log_item *);
+int xfs_efi_recover(struct xfs_mount *mp,
+ struct xfs_efi_log_item *efip);
+
#endif /* __XFS_EXTFREE_ITEM_H__ */
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index a51353a1f87f..4a33a3304369 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -22,6 +22,7 @@
#include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
#include "xfs_bmap_util.h"
@@ -385,7 +386,7 @@ xfs_filestream_new_ag(
}
flags = (ap->userdata ? XFS_PICK_USERDATA : 0) |
- (ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0);
+ (ap->dfops->dop_low ? XFS_PICK_LOWSPACE : 0);
err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen);
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 7191c3878b4a..0f96847b90e1 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_inode.h"
@@ -32,6 +33,7 @@
#include "xfs_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_alloc.h"
+#include "xfs_rmap_btree.h"
#include "xfs_ialloc.h"
#include "xfs_fsops.h"
#include "xfs_itable.h"
@@ -40,6 +42,7 @@
#include "xfs_trace.h"
#include "xfs_log.h"
#include "xfs_filestream.h"
+#include "xfs_rmap.h"
/*
* File system operations
@@ -103,7 +106,9 @@ xfs_fs_geometry(
(xfs_sb_version_hasfinobt(&mp->m_sb) ?
XFS_FSOP_GEOM_FLAGS_FINOBT : 0) |
(xfs_sb_version_hassparseinodes(&mp->m_sb) ?
- XFS_FSOP_GEOM_FLAGS_SPINODES : 0);
+ XFS_FSOP_GEOM_FLAGS_SPINODES : 0) |
+ (xfs_sb_version_hasrmapbt(&mp->m_sb) ?
+ XFS_FSOP_GEOM_FLAGS_RMAPBT : 0);
geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ?
mp->m_sb.sb_logsectsize : BBSIZE;
geo->rtsectsize = mp->m_sb.sb_blocksize;
@@ -239,10 +244,16 @@ xfs_growfs_data_private(
agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ agf->agf_roots[XFS_BTNUM_RMAPi] =
+ cpu_to_be32(XFS_RMAP_BLOCK(mp));
+ agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1);
+ }
+
agf->agf_flfirst = cpu_to_be32(1);
agf->agf_fllast = 0;
agf->agf_flcount = 0;
- tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
+ tmpsize = agsize - mp->m_ag_prealloc_blocks;
agf->agf_freeblks = cpu_to_be32(tmpsize);
agf->agf_longest = cpu_to_be32(tmpsize);
if (xfs_sb_version_hascrc(&mp->m_sb))
@@ -339,7 +350,7 @@ xfs_growfs_data_private(
agno, 0);
arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
- arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+ arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
arec->ar_blockcount = cpu_to_be32(
agsize - be32_to_cpu(arec->ar_startblock));
@@ -368,7 +379,7 @@ xfs_growfs_data_private(
agno, 0);
arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);
- arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
+ arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);
arec->ar_blockcount = cpu_to_be32(
agsize - be32_to_cpu(arec->ar_startblock));
nfree += be32_to_cpu(arec->ar_blockcount);
@@ -378,6 +389,72 @@ xfs_growfs_data_private(
if (error)
goto error0;
+ /* RMAP btree root block */
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
+ struct xfs_rmap_rec *rrec;
+ struct xfs_btree_block *block;
+
+ bp = xfs_growfs_get_hdr_buf(mp,
+ XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)),
+ BTOBB(mp->m_sb.sb_blocksize), 0,
+ &xfs_rmapbt_buf_ops);
+ if (!bp) {
+ error = -ENOMEM;
+ goto error0;
+ }
+
+ xfs_btree_init_block(mp, bp, XFS_RMAP_CRC_MAGIC, 0, 0,
+ agno, XFS_BTREE_CRC_BLOCKS);
+ block = XFS_BUF_TO_BLOCK(bp);
+
+
+ /*
+ * mark the AG header regions as static metadata The BNO
+ * btree block is the first block after the headers, so
+ * it's location defines the size of region the static
+ * metadata consumes.
+ *
+ * Note: unlike mkfs, we never have to account for log
+ * space when growing the data regions
+ */
+ rrec = XFS_RMAP_REC_ADDR(block, 1);
+ rrec->rm_startblock = 0;
+ rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp));
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account freespace btree root blocks */
+ rrec = XFS_RMAP_REC_ADDR(block, 2);
+ rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(2);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account inode btree root blocks */
+ rrec = XFS_RMAP_REC_ADDR(block, 3);
+ rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) -
+ XFS_IBT_BLOCK(mp));
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ /* account for rmap btree root */
+ rrec = XFS_RMAP_REC_ADDR(block, 4);
+ rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp));
+ rrec->rm_blockcount = cpu_to_be32(1);
+ rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);
+ rrec->rm_offset = 0;
+ be16_add_cpu(&block->bb_numrecs, 1);
+
+ error = xfs_bwrite(bp);
+ xfs_buf_relse(bp);
+ if (error)
+ goto error0;
+ }
+
/*
* INO btree root block
*/
@@ -435,6 +512,8 @@ xfs_growfs_data_private(
* There are new blocks in the old last a.g.
*/
if (new) {
+ struct xfs_owner_info oinfo;
+
/*
* Change the agi length.
*/
@@ -462,14 +541,20 @@ xfs_growfs_data_private(
be32_to_cpu(agi->agi_length));
xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
+
/*
* Free the new space.
+ *
+ * XFS_RMAP_OWN_NULL is used here to tell the rmap btree that
+ * this doesn't actually exist in the rmap btree.
*/
- error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno,
- be32_to_cpu(agf->agf_length) - new), new);
- if (error) {
+ xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL);
+ error = xfs_free_extent(tp,
+ XFS_AGB_TO_FSB(mp, agno,
+ be32_to_cpu(agf->agf_length) - new),
+ new, &oinfo);
+ if (error)
goto error0;
- }
}
/*
@@ -501,6 +586,7 @@ xfs_growfs_data_private(
} else
mp->m_maxicount = 0;
xfs_set_low_space_thresholds(mp);
+ mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
/* update secondary superblocks. */
for (agno = 1; agno < nagcount; agno++) {
@@ -638,7 +724,7 @@ xfs_fs_counts(
cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
cnt->freeino = percpu_counter_read_positive(&mp->m_ifree);
cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) -
- XFS_ALLOC_SET_ASIDE(mp);
+ mp->m_alloc_set_aside;
spin_lock(&mp->m_sb_lock);
cnt->freertx = mp->m_sb.sb_frextents;
@@ -726,7 +812,7 @@ xfs_reserve_blocks(
error = -ENOSPC;
do {
free = percpu_counter_sum(&mp->m_fdblocks) -
- XFS_ALLOC_SET_ASIDE(mp);
+ mp->m_alloc_set_aside;
if (!free)
break;
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8825bcfd314c..e08eaea6327b 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -25,6 +25,7 @@
#include "xfs_trans_resv.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
@@ -1122,7 +1123,7 @@ xfs_create(
struct xfs_inode *ip = NULL;
struct xfs_trans *tp = NULL;
int error;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
bool unlock_dp_on_error = false;
prid_t prid;
@@ -1182,7 +1183,7 @@ xfs_create(
XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT);
unlock_dp_on_error = true;
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/*
* Reserve disk quota and the inode.
@@ -1219,7 +1220,7 @@ xfs_create(
unlock_dp_on_error = false;
error = xfs_dir_createname(tp, dp, name, ip->i_ino,
- &first_block, &free_list, resblks ?
+ &first_block, &dfops, resblks ?
resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
if (error) {
ASSERT(error != -ENOSPC);
@@ -1253,7 +1254,7 @@ xfs_create(
*/
xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
@@ -1269,7 +1270,7 @@ xfs_create(
return 0;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
out_release_inode:
@@ -1401,7 +1402,7 @@ xfs_link(
xfs_mount_t *mp = tdp->i_mount;
xfs_trans_t *tp;
int error;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
int resblks;
@@ -1452,7 +1453,7 @@ xfs_link(
goto error_return;
}
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/*
* Handle initial link state of O_TMPFILE inode
@@ -1464,7 +1465,7 @@ xfs_link(
}
error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
- &first_block, &free_list, resblks);
+ &first_block, &dfops, resblks);
if (error)
goto error_return;
xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -1482,9 +1483,9 @@ xfs_link(
if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
xfs_trans_set_sync(tp);
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error) {
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
goto error_return;
}
@@ -1526,7 +1527,7 @@ xfs_itruncate_extents(
{
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp = *tpp;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
xfs_fileoff_t first_unmap_block;
xfs_fileoff_t last_block;
@@ -1562,12 +1563,12 @@ xfs_itruncate_extents(
ASSERT(first_unmap_block < last_block);
unmap_len = last_block - first_unmap_block + 1;
while (!done) {
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
error = xfs_bunmapi(tp, ip,
first_unmap_block, unmap_len,
xfs_bmapi_aflag(whichfork),
XFS_ITRUNC_MAX_EXTENTS,
- &first_block, &free_list,
+ &first_block, &dfops,
&done);
if (error)
goto out_bmap_cancel;
@@ -1576,7 +1577,7 @@ xfs_itruncate_extents(
* Duplicate the transaction that has the permanent
* reservation and commit the old transaction.
*/
- error = xfs_bmap_finish(&tp, &free_list, ip);
+ error = xfs_defer_finish(&tp, &dfops, ip);
if (error)
goto out_bmap_cancel;
@@ -1602,7 +1603,7 @@ out_bmap_cancel:
* the transaction can be properly aborted. We just need to make sure
* we're not holding any resources that we were not when we came in.
*/
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
goto out;
}
@@ -1743,7 +1744,7 @@ STATIC int
xfs_inactive_ifree(
struct xfs_inode *ip)
{
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
@@ -1780,8 +1781,8 @@ xfs_inactive_ifree(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
- xfs_bmap_init(&free_list, &first_block);
- error = xfs_ifree(tp, ip, &free_list);
+ xfs_defer_init(&dfops, &first_block);
+ error = xfs_ifree(tp, ip, &dfops);
if (error) {
/*
* If we fail to free the inode, shut down. The cancel
@@ -1807,11 +1808,11 @@ xfs_inactive_ifree(
* Just ignore errors at this point. There is nothing we can do except
* to try to keep going. Make sure it's not a silent error.
*/
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error) {
- xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
+ xfs_notice(mp, "%s: xfs_defer_finish returned error %d",
__func__, error);
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
}
error = xfs_trans_commit(tp);
if (error)
@@ -2367,7 +2368,7 @@ int
xfs_ifree(
xfs_trans_t *tp,
xfs_inode_t *ip,
- xfs_bmap_free_t *flist)
+ struct xfs_defer_ops *dfops)
{
int error;
struct xfs_icluster xic = { 0 };
@@ -2386,7 +2387,7 @@ xfs_ifree(
if (error)
return error;
- error = xfs_difree(tp, ip->i_ino, flist, &xic);
+ error = xfs_difree(tp, ip->i_ino, dfops, &xic);
if (error)
return error;
@@ -2474,7 +2475,7 @@ xfs_iunpin_wait(
* directory entry.
*
* This is still safe from a transactional point of view - it is not until we
- * get to xfs_bmap_finish() that we have the possibility of multiple
+ * get to xfs_defer_finish() that we have the possibility of multiple
* transactions in this operation. Hence as long as we remove the directory
* entry and drop the link count in the first transaction of the remove
* operation, there are no transactional constraints on the ordering here.
@@ -2489,7 +2490,7 @@ xfs_remove(
xfs_trans_t *tp = NULL;
int is_dir = S_ISDIR(VFS_I(ip)->i_mode);
int error = 0;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
uint resblks;
@@ -2571,9 +2572,9 @@ xfs_remove(
if (error)
goto out_trans_cancel;
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
error = xfs_dir_removename(tp, dp, name, ip->i_ino,
- &first_block, &free_list, resblks);
+ &first_block, &dfops, resblks);
if (error) {
ASSERT(error != -ENOENT);
goto out_bmap_cancel;
@@ -2587,7 +2588,7 @@ xfs_remove(
if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
xfs_trans_set_sync(tp);
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
@@ -2601,7 +2602,7 @@ xfs_remove(
return 0;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
std_return:
@@ -2662,7 +2663,7 @@ xfs_sort_for_rename(
static int
xfs_finish_rename(
struct xfs_trans *tp,
- struct xfs_bmap_free *free_list)
+ struct xfs_defer_ops *dfops)
{
int error;
@@ -2673,9 +2674,9 @@ xfs_finish_rename(
if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC))
xfs_trans_set_sync(tp);
- error = xfs_bmap_finish(&tp, free_list, NULL);
+ error = xfs_defer_finish(&tp, dfops, NULL);
if (error) {
- xfs_bmap_cancel(free_list);
+ xfs_defer_cancel(dfops);
xfs_trans_cancel(tp);
return error;
}
@@ -2697,7 +2698,7 @@ xfs_cross_rename(
struct xfs_inode *dp2,
struct xfs_name *name2,
struct xfs_inode *ip2,
- struct xfs_bmap_free *free_list,
+ struct xfs_defer_ops *dfops,
xfs_fsblock_t *first_block,
int spaceres)
{
@@ -2709,14 +2710,14 @@ xfs_cross_rename(
/* Swap inode number for dirent in first parent */
error = xfs_dir_replace(tp, dp1, name1,
ip2->i_ino,
- first_block, free_list, spaceres);
+ first_block, dfops, spaceres);
if (error)
goto out_trans_abort;
/* Swap inode number for dirent in second parent */
error = xfs_dir_replace(tp, dp2, name2,
ip1->i_ino,
- first_block, free_list, spaceres);
+ first_block, dfops, spaceres);
if (error)
goto out_trans_abort;
@@ -2731,7 +2732,7 @@ xfs_cross_rename(
if (S_ISDIR(VFS_I(ip2)->i_mode)) {
error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot,
dp1->i_ino, first_block,
- free_list, spaceres);
+ dfops, spaceres);
if (error)
goto out_trans_abort;
@@ -2758,7 +2759,7 @@ xfs_cross_rename(
if (S_ISDIR(VFS_I(ip1)->i_mode)) {
error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot,
dp2->i_ino, first_block,
- free_list, spaceres);
+ dfops, spaceres);
if (error)
goto out_trans_abort;
@@ -2797,10 +2798,10 @@ xfs_cross_rename(
}
xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
- return xfs_finish_rename(tp, free_list);
+ return xfs_finish_rename(tp, dfops);
out_trans_abort:
- xfs_bmap_cancel(free_list);
+ xfs_defer_cancel(dfops);
xfs_trans_cancel(tp);
return error;
}
@@ -2855,7 +2856,7 @@ xfs_rename(
{
struct xfs_mount *mp = src_dp->i_mount;
struct xfs_trans *tp;
- struct xfs_bmap_free free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
struct xfs_inode *wip = NULL; /* whiteout inode */
struct xfs_inode *inodes[__XFS_SORT_INODES];
@@ -2944,13 +2945,13 @@ xfs_rename(
goto out_trans_cancel;
}
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/* RENAME_EXCHANGE is unique from here on. */
if (flags & RENAME_EXCHANGE)
return xfs_cross_rename(tp, src_dp, src_name, src_ip,
target_dp, target_name, target_ip,
- &free_list, &first_block, spaceres);
+ &dfops, &first_block, spaceres);
/*
* Set up the target.
@@ -2972,7 +2973,7 @@ xfs_rename(
*/
error = xfs_dir_createname(tp, target_dp, target_name,
src_ip->i_ino, &first_block,
- &free_list, spaceres);
+ &dfops, spaceres);
if (error)
goto out_bmap_cancel;
@@ -3012,7 +3013,7 @@ xfs_rename(
*/
error = xfs_dir_replace(tp, target_dp, target_name,
src_ip->i_ino,
- &first_block, &free_list, spaceres);
+ &first_block, &dfops, spaceres);
if (error)
goto out_bmap_cancel;
@@ -3047,7 +3048,7 @@ xfs_rename(
*/
error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot,
target_dp->i_ino,
- &first_block, &free_list, spaceres);
+ &first_block, &dfops, spaceres);
ASSERT(error != -EEXIST);
if (error)
goto out_bmap_cancel;
@@ -3086,10 +3087,10 @@ xfs_rename(
*/
if (wip) {
error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino,
- &first_block, &free_list, spaceres);
+ &first_block, &dfops, spaceres);
} else
error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino,
- &first_block, &free_list, spaceres);
+ &first_block, &dfops, spaceres);
if (error)
goto out_bmap_cancel;
@@ -3124,13 +3125,13 @@ xfs_rename(
if (new_parent)
xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
- error = xfs_finish_rename(tp, &free_list);
+ error = xfs_finish_rename(tp, &dfops);
if (wip)
IRELE(wip);
return error;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
out_release_wip:
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 8eb78ec4a6e2..e1a411e08f00 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -27,7 +27,7 @@
struct xfs_dinode;
struct xfs_inode;
struct xfs_buf;
-struct xfs_bmap_free;
+struct xfs_defer_ops;
struct xfs_bmbt_irec;
struct xfs_inode_log_item;
struct xfs_mount;
@@ -398,7 +398,7 @@ uint xfs_ilock_attr_map_shared(struct xfs_inode *);
uint xfs_ip2xflags(struct xfs_inode *);
int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
- struct xfs_bmap_free *);
+ struct xfs_defer_ops *);
int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *,
int, xfs_fsize_t);
void xfs_iext_realloc(xfs_inode_t *, int, int);
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 9a7c87809d3b..96a70fd1f5d6 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -232,7 +232,7 @@ xfs_open_by_handle(
}
if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
- error = -EACCES;
+ error = -EPERM;
goto out_dput;
}
@@ -387,6 +387,7 @@ xfs_attrlist_by_handle(
{
int error = -ENOMEM;
attrlist_cursor_kern_t *cursor;
+ struct xfs_fsop_attrlist_handlereq __user *p = arg;
xfs_fsop_attrlist_handlereq_t al_hreq;
struct dentry *dentry;
char *kbuf;
@@ -419,6 +420,11 @@ xfs_attrlist_by_handle(
if (error)
goto out_kfree;
+ if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
+ error = -EFAULT;
+ goto out_kfree;
+ }
+
if (copy_to_user(al_hreq.buffer, kbuf, al_hreq.buflen))
error = -EFAULT;
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 620fc9120444..2114d53df433 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -23,6 +23,7 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_bmap_btree.h"
@@ -128,7 +129,7 @@ xfs_iomap_write_direct(
int quota_flag;
int rt;
xfs_trans_t *tp;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
uint qblocks, resblks, resrtextents;
int error;
int lockmode;
@@ -231,18 +232,18 @@ xfs_iomap_write_direct(
* From this point onwards we overwrite the imap pointer that the
* caller gave to us.
*/
- xfs_bmap_init(&free_list, &firstfsb);
+ xfs_defer_init(&dfops, &firstfsb);
nimaps = 1;
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
bmapi_flags, &firstfsb, resblks, imap,
- &nimaps, &free_list);
+ &nimaps, &dfops);
if (error)
goto out_bmap_cancel;
/*
* Complete the transaction
*/
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
@@ -266,7 +267,7 @@ out_unlock:
return error;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
out_trans_cancel:
xfs_trans_cancel(tp);
@@ -685,7 +686,7 @@ xfs_iomap_write_allocate(
xfs_fileoff_t offset_fsb, last_block;
xfs_fileoff_t end_fsb, map_start_fsb;
xfs_fsblock_t first_block;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_filblks_t count_fsb;
xfs_trans_t *tp;
int nimaps;
@@ -727,7 +728,7 @@ xfs_iomap_write_allocate(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, 0);
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/*
* it is possible that the extents have changed since
@@ -783,11 +784,11 @@ xfs_iomap_write_allocate(
error = xfs_bmapi_write(tp, ip, map_start_fsb,
count_fsb, 0, &first_block,
nres, imap, &nimaps,
- &free_list);
+ &dfops);
if (error)
goto trans_cancel;
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto trans_cancel;
@@ -821,7 +822,7 @@ xfs_iomap_write_allocate(
}
trans_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
xfs_trans_cancel(tp);
error0:
xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -842,7 +843,7 @@ xfs_iomap_write_unwritten(
int nimaps;
xfs_trans_t *tp;
xfs_bmbt_irec_t imap;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
xfs_fsize_t i_size;
uint resblks;
int error;
@@ -886,11 +887,11 @@ xfs_iomap_write_unwritten(
/*
* Modify the unwritten extent state of the buffer.
*/
- xfs_bmap_init(&free_list, &firstfsb);
+ xfs_defer_init(&dfops, &firstfsb);
nimaps = 1;
error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb,
XFS_BMAPI_CONVERT, &firstfsb, resblks,
- &imap, &nimaps, &free_list);
+ &imap, &nimaps, &dfops);
if (error)
goto error_on_bmapi_transaction;
@@ -909,7 +910,7 @@ xfs_iomap_write_unwritten(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
}
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto error_on_bmapi_transaction;
@@ -936,7 +937,7 @@ xfs_iomap_write_unwritten(
return 0;
error_on_bmapi_transaction:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
xfs_trans_cancel(tp);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return error;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 835997843846..e8638fd2c0c3 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -43,6 +43,7 @@
#include "xfs_bmap_btree.h"
#include "xfs_error.h"
#include "xfs_dir2.h"
+#include "xfs_rmap_item.h"
#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)
@@ -1911,6 +1912,8 @@ xlog_recover_reorder_trans(
case XFS_LI_QUOTAOFF:
case XFS_LI_EFD:
case XFS_LI_EFI:
+ case XFS_LI_RUI:
+ case XFS_LI_RUD:
trace_xfs_log_recover_item_reorder_tail(log,
trans, item, pass);
list_move_tail(&item->ri_list, &inode_list);
@@ -2228,6 +2231,7 @@ xlog_recover_get_buf_lsn(
case XFS_ABTC_CRC_MAGIC:
case XFS_ABTB_MAGIC:
case XFS_ABTC_MAGIC:
+ case XFS_RMAP_CRC_MAGIC:
case XFS_IBT_CRC_MAGIC:
case XFS_IBT_MAGIC: {
struct xfs_btree_block *btb = blk;
@@ -2396,6 +2400,9 @@ xlog_recover_validate_buf_type(
case XFS_BMAP_MAGIC:
bp->b_ops = &xfs_bmbt_buf_ops;
break;
+ case XFS_RMAP_CRC_MAGIC:
+ bp->b_ops = &xfs_rmapbt_buf_ops;
+ break;
default:
xfs_warn(mp, "Bad btree block magic!");
ASSERT(0);
@@ -3415,6 +3422,99 @@ xlog_recover_efd_pass2(
}
/*
+ * This routine is called to create an in-core extent rmap update
+ * item from the rui format structure which was logged on disk.
+ * It allocates an in-core rui, copies the extents from the format
+ * structure into it, and adds the rui to the AIL with the given
+ * LSN.
+ */
+STATIC int
+xlog_recover_rui_pass2(
+ struct xlog *log,
+ struct xlog_recover_item *item,
+ xfs_lsn_t lsn)
+{
+ int error;
+ struct xfs_mount *mp = log->l_mp;
+ struct xfs_rui_log_item *ruip;
+ struct xfs_rui_log_format *rui_formatp;
+
+ rui_formatp = item->ri_buf[0].i_addr;
+
+ ruip = xfs_rui_init(mp, rui_formatp->rui_nextents);
+ error = xfs_rui_copy_format(&item->ri_buf[0], &ruip->rui_format);
+ if (error) {
+ xfs_rui_item_free(ruip);
+ return error;
+ }
+ atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents);
+
+ spin_lock(&log->l_ailp->xa_lock);
+ /*
+ * The RUI has two references. One for the RUD and one for RUI to ensure
+ * it makes it into the AIL. Insert the RUI into the AIL directly and
+ * drop the RUI reference. Note that xfs_trans_ail_update() drops the
+ * AIL lock.
+ */
+ xfs_trans_ail_update(log->l_ailp, &ruip->rui_item, lsn);
+ xfs_rui_release(ruip);
+ return 0;
+}
+
+
+/*
+ * This routine is called when an RUD format structure is found in a committed
+ * transaction in the log. Its purpose is to cancel the corresponding RUI if it
+ * was still in the log. To do this it searches the AIL for the RUI with an id
+ * equal to that in the RUD format structure. If we find it we drop the RUD
+ * reference, which removes the RUI from the AIL and frees it.
+ */
+STATIC int
+xlog_recover_rud_pass2(
+ struct xlog *log,
+ struct xlog_recover_item *item)
+{
+ struct xfs_rud_log_format *rud_formatp;
+ struct xfs_rui_log_item *ruip = NULL;
+ struct xfs_log_item *lip;
+ __uint64_t rui_id;
+ struct xfs_ail_cursor cur;
+ struct xfs_ail *ailp = log->l_ailp;
+
+ rud_formatp = item->ri_buf[0].i_addr;
+ ASSERT(item->ri_buf[0].i_len == sizeof(struct xfs_rud_log_format));
+ rui_id = rud_formatp->rud_rui_id;
+
+ /*
+ * Search for the RUI with the id in the RUD format structure in the
+ * AIL.
+ */
+ spin_lock(&ailp->xa_lock);
+ lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
+ while (lip != NULL) {
+ if (lip->li_type == XFS_LI_RUI) {
+ ruip = (struct xfs_rui_log_item *)lip;
+ if (ruip->rui_format.rui_id == rui_id) {
+ /*
+ * Drop the RUD reference to the RUI. This
+ * removes the RUI from the AIL and frees it.
+ */
+ spin_unlock(&ailp->xa_lock);
+ xfs_rui_release(ruip);
+ spin_lock(&ailp->xa_lock);
+ break;
+ }
+ }
+ lip = xfs_trans_ail_cursor_next(ailp, &cur);
+ }
+
+ xfs_trans_ail_cursor_done(&cur);
+ spin_unlock(&ailp->xa_lock);
+
+ return 0;
+}
+
+/*
* This routine is called when an inode create format structure is found in a
* committed transaction in the log. It's purpose is to initialise the inodes
* being allocated on disk. This requires us to get inode cluster buffers that
@@ -3639,6 +3739,8 @@ xlog_recover_ra_pass2(
case XFS_LI_EFI:
case XFS_LI_EFD:
case XFS_LI_QUOTAOFF:
+ case XFS_LI_RUI:
+ case XFS_LI_RUD:
default:
break;
}
@@ -3662,6 +3764,8 @@ xlog_recover_commit_pass1(
case XFS_LI_EFD:
case XFS_LI_DQUOT:
case XFS_LI_ICREATE:
+ case XFS_LI_RUI:
+ case XFS_LI_RUD:
/* nothing to do in pass 1 */
return 0;
default:
@@ -3692,6 +3796,10 @@ xlog_recover_commit_pass2(
return xlog_recover_efi_pass2(log, item, trans->r_lsn);
case XFS_LI_EFD:
return xlog_recover_efd_pass2(log, item);
+ case XFS_LI_RUI:
+ return xlog_recover_rui_pass2(log, item, trans->r_lsn);
+ case XFS_LI_RUD:
+ return xlog_recover_rud_pass2(log, item);
case XFS_LI_DQUOT:
return xlog_recover_dquot_pass2(log, buffer_list, item,
trans->r_lsn);
@@ -4164,126 +4272,156 @@ xlog_recover_process_data(
return 0;
}
-/*
- * Process an extent free intent item that was recovered from
- * the log. We need to free the extents that it describes.
- */
+/* Recover the EFI if necessary. */
STATIC int
xlog_recover_process_efi(
- xfs_mount_t *mp,
- xfs_efi_log_item_t *efip)
+ struct xfs_mount *mp,
+ struct xfs_ail *ailp,
+ struct xfs_log_item *lip)
{
- xfs_efd_log_item_t *efdp;
- xfs_trans_t *tp;
- int i;
- int error = 0;
- xfs_extent_t *extp;
- xfs_fsblock_t startblock_fsb;
-
- ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags));
+ struct xfs_efi_log_item *efip;
+ int error;
/*
- * First check the validity of the extents described by the
- * EFI. If any are bad, then assume that all are bad and
- * just toss the EFI.
+ * Skip EFIs that we've already processed.
*/
- for (i = 0; i < efip->efi_format.efi_nextents; i++) {
- extp = &(efip->efi_format.efi_extents[i]);
- startblock_fsb = XFS_BB_TO_FSB(mp,
- XFS_FSB_TO_DADDR(mp, extp->ext_start));
- if ((startblock_fsb == 0) ||
- (extp->ext_len == 0) ||
- (startblock_fsb >= mp->m_sb.sb_dblocks) ||
- (extp->ext_len >= mp->m_sb.sb_agblocks)) {
- /*
- * This will pull the EFI from the AIL and
- * free the memory associated with it.
- */
- set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
- xfs_efi_release(efip);
- return -EIO;
- }
- }
+ efip = container_of(lip, struct xfs_efi_log_item, efi_item);
+ if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags))
+ return 0;
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
- if (error)
- return error;
- efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents);
+ spin_unlock(&ailp->xa_lock);
+ error = xfs_efi_recover(mp, efip);
+ spin_lock(&ailp->xa_lock);
- for (i = 0; i < efip->efi_format.efi_nextents; i++) {
- extp = &(efip->efi_format.efi_extents[i]);
- error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
- extp->ext_len);
- if (error)
- goto abort_error;
+ return error;
+}
- }
+/* Release the EFI since we're cancelling everything. */
+STATIC void
+xlog_recover_cancel_efi(
+ struct xfs_mount *mp,
+ struct xfs_ail *ailp,
+ struct xfs_log_item *lip)
+{
+ struct xfs_efi_log_item *efip;
- set_bit(XFS_EFI_RECOVERED, &efip->efi_flags);
- error = xfs_trans_commit(tp);
- return error;
+ efip = container_of(lip, struct xfs_efi_log_item, efi_item);
+
+ spin_unlock(&ailp->xa_lock);
+ xfs_efi_release(efip);
+ spin_lock(&ailp->xa_lock);
+}
+
+/* Recover the RUI if necessary. */
+STATIC int
+xlog_recover_process_rui(
+ struct xfs_mount *mp,
+ struct xfs_ail *ailp,
+ struct xfs_log_item *lip)
+{
+ struct xfs_rui_log_item *ruip;
+ int error;
+
+ /*
+ * Skip RUIs that we've already processed.
+ */
+ ruip = container_of(lip, struct xfs_rui_log_item, rui_item);
+ if (test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags))
+ return 0;
+
+ spin_unlock(&ailp->xa_lock);
+ error = xfs_rui_recover(mp, ruip);
+ spin_lock(&ailp->xa_lock);
-abort_error:
- xfs_trans_cancel(tp);
return error;
}
+/* Release the RUI since we're cancelling everything. */
+STATIC void
+xlog_recover_cancel_rui(
+ struct xfs_mount *mp,
+ struct xfs_ail *ailp,
+ struct xfs_log_item *lip)
+{
+ struct xfs_rui_log_item *ruip;
+
+ ruip = container_of(lip, struct xfs_rui_log_item, rui_item);
+
+ spin_unlock(&ailp->xa_lock);
+ xfs_rui_release(ruip);
+ spin_lock(&ailp->xa_lock);
+}
+
+/* Is this log item a deferred action intent? */
+static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
+{
+ switch (lip->li_type) {
+ case XFS_LI_EFI:
+ case XFS_LI_RUI:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
- * When this is called, all of the EFIs which did not have
- * corresponding EFDs should be in the AIL. What we do now
- * is free the extents associated with each one.
+ * When this is called, all of the log intent items which did not have
+ * corresponding log done items should be in the AIL. What we do now
+ * is update the data structures associated with each one.
*
- * Since we process the EFIs in normal transactions, they
- * will be removed at some point after the commit. This prevents
- * us from just walking down the list processing each one.
- * We'll use a flag in the EFI to skip those that we've already
- * processed and use the AIL iteration mechanism's generation
- * count to try to speed this up at least a bit.
+ * Since we process the log intent items in normal transactions, they
+ * will be removed at some point after the commit. This prevents us
+ * from just walking down the list processing each one. We'll use a
+ * flag in the intent item to skip those that we've already processed
+ * and use the AIL iteration mechanism's generation count to try to
+ * speed this up at least a bit.
*
- * When we start, we know that the EFIs are the only things in
- * the AIL. As we process them, however, other items are added
- * to the AIL. Since everything added to the AIL must come after
- * everything already in the AIL, we stop processing as soon as
- * we see something other than an EFI in the AIL.
+ * When we start, we know that the intents are the only things in the
+ * AIL. As we process them, however, other items are added to the
+ * AIL.
*/
STATIC int
-xlog_recover_process_efis(
+xlog_recover_process_intents(
struct xlog *log)
{
struct xfs_log_item *lip;
- struct xfs_efi_log_item *efip;
int error = 0;
struct xfs_ail_cursor cur;
struct xfs_ail *ailp;
+ xfs_lsn_t last_lsn;
ailp = log->l_ailp;
spin_lock(&ailp->xa_lock);
lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
+ last_lsn = xlog_assign_lsn(log->l_curr_cycle, log->l_curr_block);
while (lip != NULL) {
/*
- * We're done when we see something other than an EFI.
- * There should be no EFIs left in the AIL now.
+ * We're done when we see something other than an intent.
+ * There should be no intents left in the AIL now.
*/
- if (lip->li_type != XFS_LI_EFI) {
+ if (!xlog_item_is_intent(lip)) {
#ifdef DEBUG
for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur))
- ASSERT(lip->li_type != XFS_LI_EFI);
+ ASSERT(!xlog_item_is_intent(lip));
#endif
break;
}
/*
- * Skip EFIs that we've already processed.
+ * We should never see a redo item with a LSN higher than
+ * the last transaction we found in the log at the start
+ * of recovery.
*/
- efip = container_of(lip, struct xfs_efi_log_item, efi_item);
- if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) {
- lip = xfs_trans_ail_cursor_next(ailp, &cur);
- continue;
- }
+ ASSERT(XFS_LSN_CMP(last_lsn, lip->li_lsn) >= 0);
- spin_unlock(&ailp->xa_lock);
- error = xlog_recover_process_efi(log->l_mp, efip);
- spin_lock(&ailp->xa_lock);
+ switch (lip->li_type) {
+ case XFS_LI_EFI:
+ error = xlog_recover_process_efi(log->l_mp, ailp, lip);
+ break;
+ case XFS_LI_RUI:
+ error = xlog_recover_process_rui(log->l_mp, ailp, lip);
+ break;
+ }
if (error)
goto out;
lip = xfs_trans_ail_cursor_next(ailp, &cur);
@@ -4295,15 +4433,14 @@ out:
}
/*
- * A cancel occurs when the mount has failed and we're bailing out. Release all
- * pending EFIs so they don't pin the AIL.
+ * A cancel occurs when the mount has failed and we're bailing out.
+ * Release all pending log intent items so they don't pin the AIL.
*/
STATIC int
-xlog_recover_cancel_efis(
+xlog_recover_cancel_intents(
struct xlog *log)
{
struct xfs_log_item *lip;
- struct xfs_efi_log_item *efip;
int error = 0;
struct xfs_ail_cursor cur;
struct xfs_ail *ailp;
@@ -4313,22 +4450,25 @@ xlog_recover_cancel_efis(
lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
while (lip != NULL) {
/*
- * We're done when we see something other than an EFI.
- * There should be no EFIs left in the AIL now.
+ * We're done when we see something other than an intent.
+ * There should be no intents left in the AIL now.
*/
- if (lip->li_type != XFS_LI_EFI) {
+ if (!xlog_item_is_intent(lip)) {
#ifdef DEBUG
for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur))
- ASSERT(lip->li_type != XFS_LI_EFI);
+ ASSERT(!xlog_item_is_intent(lip));
#endif
break;
}
- efip = container_of(lip, struct xfs_efi_log_item, efi_item);
-
- spin_unlock(&ailp->xa_lock);
- xfs_efi_release(efip);
- spin_lock(&ailp->xa_lock);
+ switch (lip->li_type) {
+ case XFS_LI_EFI:
+ xlog_recover_cancel_efi(log->l_mp, ailp, lip);
+ break;
+ case XFS_LI_RUI:
+ xlog_recover_cancel_rui(log->l_mp, ailp, lip);
+ break;
+ }
lip = xfs_trans_ail_cursor_next(ailp, &cur);
}
@@ -5023,6 +5163,7 @@ xlog_do_recover(
xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
return error;
}
+ mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
xlog_recover_check_summary(log);
@@ -5139,16 +5280,17 @@ xlog_recover_finish(
*/
if (log->l_flags & XLOG_RECOVERY_NEEDED) {
int error;
- error = xlog_recover_process_efis(log);
+ error = xlog_recover_process_intents(log);
if (error) {
- xfs_alert(log->l_mp, "Failed to recover EFIs");
+ xfs_alert(log->l_mp, "Failed to recover intents");
return error;
}
+
/*
- * Sync the log to get all the EFIs out of the AIL.
+ * Sync the log to get all the intents out of the AIL.
* This isn't absolutely necessary, but it helps in
* case the unlink transactions would have problems
- * pushing the EFIs out of the way.
+ * pushing the intents out of the way.
*/
xfs_log_force(log->l_mp, XFS_LOG_SYNC);
@@ -5173,7 +5315,7 @@ xlog_recover_cancel(
int error = 0;
if (log->l_flags & XLOG_RECOVERY_NEEDED)
- error = xlog_recover_cancel_efis(log);
+ error = xlog_recover_cancel_intents(log);
return error;
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 970c19ba2f56..faeead671f9f 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -24,6 +24,7 @@
#include "xfs_bit.h"
#include "xfs_sb.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_inode.h"
@@ -41,6 +42,7 @@
#include "xfs_trace.h"
#include "xfs_icache.h"
#include "xfs_sysfs.h"
+#include "xfs_rmap_btree.h"
static DEFINE_MUTEX(xfs_uuid_table_mutex);
@@ -230,6 +232,8 @@ xfs_initialize_perag(
if (maxagi)
*maxagi = index;
+
+ mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
return 0;
out_unwind:
@@ -679,6 +683,7 @@ xfs_mountfs(
xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
xfs_ialloc_compute_maxlevels(mp);
+ xfs_rmapbt_compute_maxlevels(mp);
xfs_set_maxicount(mp);
@@ -1216,7 +1221,7 @@ xfs_mod_fdblocks(
batch = XFS_FDBLOCKS_BATCH;
__percpu_counter_add(&mp->m_fdblocks, delta, batch);
- if (__percpu_counter_compare(&mp->m_fdblocks, XFS_ALLOC_SET_ASIDE(mp),
+ if (__percpu_counter_compare(&mp->m_fdblocks, mp->m_alloc_set_aside,
XFS_FDBLOCKS_BATCH) >= 0) {
/* we had space! */
return 0;
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index c1b798c72126..b36676cde103 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -116,9 +116,15 @@ typedef struct xfs_mount {
uint m_bmap_dmnr[2]; /* min bmap btree records */
uint m_inobt_mxr[2]; /* max inobt btree records */
uint m_inobt_mnr[2]; /* min inobt btree records */
+ uint m_rmap_mxr[2]; /* max rmap btree records */
+ uint m_rmap_mnr[2]; /* min rmap btree records */
uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */
uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */
uint m_in_maxlevels; /* max inobt btree levels. */
+ uint m_rmap_maxlevels; /* max rmap btree levels */
+ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */
+ uint m_alloc_set_aside; /* space we can't use */
+ uint m_ag_max_usable; /* max space per AG */
struct radix_tree_root m_perag_tree; /* per-ag accounting info */
spinlock_t m_perag_lock; /* lock for m_perag_tree */
struct mutex m_growlock; /* growfs mutex */
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 0cc8d8f74356..69e2986a3776 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -49,11 +49,14 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56);
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4);
XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16);
+ XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_key, 20);
+ XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_rec, 24);
XFS_CHECK_STRUCT_SIZE(struct xfs_timestamp, 8);
XFS_CHECK_STRUCT_SIZE(xfs_alloc_key_t, 8);
XFS_CHECK_STRUCT_SIZE(xfs_alloc_ptr_t, 4);
XFS_CHECK_STRUCT_SIZE(xfs_alloc_rec_t, 8);
XFS_CHECK_STRUCT_SIZE(xfs_inobt_ptr_t, 4);
+ XFS_CHECK_STRUCT_SIZE(xfs_rmap_ptr_t, 4);
/* dir/attr trees */
XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80);
diff --git a/fs/xfs/xfs_pnfs.h b/fs/xfs/xfs_pnfs.h
index 93f74853961b..e8339f74966b 100644
--- a/fs/xfs/xfs_pnfs.h
+++ b/fs/xfs/xfs_pnfs.h
@@ -1,7 +1,7 @@
#ifndef _XFS_PNFS_H
#define _XFS_PNFS_H 1
-#if defined(CONFIG_NFSD_BLOCKLAYOUT) || defined(CONFIG_NFSD_SCSILAYOUT)
+#ifdef CONFIG_EXPORTFS_BLOCK_OPS
int xfs_fs_get_uuid(struct super_block *sb, u8 *buf, u32 *len, u64 *offset);
int xfs_fs_map_blocks(struct inode *inode, loff_t offset, u64 length,
struct iomap *iomap, bool write, u32 *device_generation);
@@ -15,5 +15,5 @@ xfs_break_layouts(struct inode *inode, uint *iolock, bool with_imutex)
{
return 0;
}
-#endif /* CONFIG_NFSD_PNFS */
+#endif /* CONFIG_EXPORTFS_BLOCK_OPS */
#endif /* _XFS_PNFS_H */
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
new file mode 100644
index 000000000000..2500f28689d5
--- /dev/null
+++ b/fs/xfs/xfs_rmap_item.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_trans.h"
+#include "xfs_trans_priv.h"
+#include "xfs_buf_item.h"
+#include "xfs_rmap_item.h"
+#include "xfs_log.h"
+#include "xfs_rmap.h"
+
+
+kmem_zone_t *xfs_rui_zone;
+kmem_zone_t *xfs_rud_zone;
+
+static inline struct xfs_rui_log_item *RUI_ITEM(struct xfs_log_item *lip)
+{
+ return container_of(lip, struct xfs_rui_log_item, rui_item);
+}
+
+void
+xfs_rui_item_free(
+ struct xfs_rui_log_item *ruip)
+{
+ if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS)
+ kmem_free(ruip);
+ else
+ kmem_zone_free(xfs_rui_zone, ruip);
+}
+
+/*
+ * This returns the number of iovecs needed to log the given rui item.
+ * We only need 1 iovec for an rui item. It just logs the rui_log_format
+ * structure.
+ */
+static inline int
+xfs_rui_item_sizeof(
+ struct xfs_rui_log_item *ruip)
+{
+ return sizeof(struct xfs_rui_log_format) +
+ (ruip->rui_format.rui_nextents - 1) *
+ sizeof(struct xfs_map_extent);
+}
+
+STATIC void
+xfs_rui_item_size(
+ struct xfs_log_item *lip,
+ int *nvecs,
+ int *nbytes)
+{
+ *nvecs += 1;
+ *nbytes += xfs_rui_item_sizeof(RUI_ITEM(lip));
+}
+
+/*
+ * This is called to fill in the vector of log iovecs for the
+ * given rui log item. We use only 1 iovec, and we point that
+ * at the rui_log_format structure embedded in the rui item.
+ * It is at this point that we assert that all of the extent
+ * slots in the rui item have been filled.
+ */
+STATIC void
+xfs_rui_item_format(
+ struct xfs_log_item *lip,
+ struct xfs_log_vec *lv)
+{
+ struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
+ struct xfs_log_iovec *vecp = NULL;
+
+ ASSERT(atomic_read(&ruip->rui_next_extent) ==
+ ruip->rui_format.rui_nextents);
+
+ ruip->rui_format.rui_type = XFS_LI_RUI;
+ ruip->rui_format.rui_size = 1;
+
+ xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format,
+ xfs_rui_item_sizeof(ruip));
+}
+
+/*
+ * Pinning has no meaning for an rui item, so just return.
+ */
+STATIC void
+xfs_rui_item_pin(
+ struct xfs_log_item *lip)
+{
+}
+
+/*
+ * The unpin operation is the last place an RUI is manipulated in the log. It is
+ * either inserted in the AIL or aborted in the event of a log I/O error. In
+ * either case, the RUI transaction has been successfully committed to make it
+ * this far. Therefore, we expect whoever committed the RUI to either construct
+ * and commit the RUD or drop the RUD's reference in the event of error. Simply
+ * drop the log's RUI reference now that the log is done with it.
+ */
+STATIC void
+xfs_rui_item_unpin(
+ struct xfs_log_item *lip,
+ int remove)
+{
+ struct xfs_rui_log_item *ruip = RUI_ITEM(lip);
+
+ xfs_rui_release(ruip);
+}
+
+/*
+ * RUI items have no locking or pushing. However, since RUIs are pulled from
+ * the AIL when their corresponding RUDs are committed to disk, their situation
+ * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller
+ * will eventually flush the log. This should help in getting the RUI out of
+ * the AIL.
+ */
+STATIC uint
+xfs_rui_item_push(
+ struct xfs_log_item *lip,
+ struct list_head *buffer_list)
+{
+ return XFS_ITEM_PINNED;
+}
+
+/*
+ * The RUI has been either committed or aborted if the transaction has been
+ * cancelled. If the transaction was cancelled, an RUD isn't going to be
+ * constructed and thus we free the RUI here directly.
+ */
+STATIC void
+xfs_rui_item_unlock(
+ struct xfs_log_item *lip)
+{
+ if (lip->li_flags & XFS_LI_ABORTED)
+ xfs_rui_item_free(RUI_ITEM(lip));
+}
+
+/*
+ * The RUI is logged only once and cannot be moved in the log, so simply return
+ * the lsn at which it's been logged.
+ */
+STATIC xfs_lsn_t
+xfs_rui_item_committed(
+ struct xfs_log_item *lip,
+ xfs_lsn_t lsn)
+{
+ return lsn;
+}
+
+/*
+ * The RUI dependency tracking op doesn't do squat. It can't because
+ * it doesn't know where the free extent is coming from. The dependency
+ * tracking has to be handled by the "enclosing" metadata object. For
+ * example, for inodes, the inode is locked throughout the extent freeing
+ * so the dependency should be recorded there.
+ */
+STATIC void
+xfs_rui_item_committing(
+ struct xfs_log_item *lip,
+ xfs_lsn_t lsn)
+{
+}
+
+/*
+ * This is the ops vector shared by all rui log items.
+ */
+static const struct xfs_item_ops xfs_rui_item_ops = {
+ .iop_size = xfs_rui_item_size,
+ .iop_format = xfs_rui_item_format,
+ .iop_pin = xfs_rui_item_pin,
+ .iop_unpin = xfs_rui_item_unpin,
+ .iop_unlock = xfs_rui_item_unlock,
+ .iop_committed = xfs_rui_item_committed,
+ .iop_push = xfs_rui_item_push,
+ .iop_committing = xfs_rui_item_committing,
+};
+
+/*
+ * Allocate and initialize an rui item with the given number of extents.
+ */
+struct xfs_rui_log_item *
+xfs_rui_init(
+ struct xfs_mount *mp,
+ uint nextents)
+
+{
+ struct xfs_rui_log_item *ruip;
+ uint size;
+
+ ASSERT(nextents > 0);
+ if (nextents > XFS_RUI_MAX_FAST_EXTENTS) {
+ size = (uint)(sizeof(struct xfs_rui_log_item) +
+ ((nextents - 1) * sizeof(struct xfs_map_extent)));
+ ruip = kmem_zalloc(size, KM_SLEEP);
+ } else {
+ ruip = kmem_zone_zalloc(xfs_rui_zone, KM_SLEEP);
+ }
+
+ xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops);
+ ruip->rui_format.rui_nextents = nextents;
+ ruip->rui_format.rui_id = (uintptr_t)(void *)ruip;
+ atomic_set(&ruip->rui_next_extent, 0);
+ atomic_set(&ruip->rui_refcount, 2);
+
+ return ruip;
+}
+
+/*
+ * Copy an RUI format buffer from the given buf, and into the destination
+ * RUI format structure. The RUI/RUD items were designed not to need any
+ * special alignment handling.
+ */
+int
+xfs_rui_copy_format(
+ struct xfs_log_iovec *buf,
+ struct xfs_rui_log_format *dst_rui_fmt)
+{
+ struct xfs_rui_log_format *src_rui_fmt;
+ uint len;
+
+ src_rui_fmt = buf->i_addr;
+ len = sizeof(struct xfs_rui_log_format) +
+ (src_rui_fmt->rui_nextents - 1) *
+ sizeof(struct xfs_map_extent);
+
+ if (buf->i_len != len)
+ return -EFSCORRUPTED;
+
+ memcpy((char *)dst_rui_fmt, (char *)src_rui_fmt, len);
+ return 0;
+}
+
+/*
+ * Freeing the RUI requires that we remove it from the AIL if it has already
+ * been placed there. However, the RUI may not yet have been placed in the AIL
+ * when called by xfs_rui_release() from RUD processing due to the ordering of
+ * committed vs unpin operations in bulk insert operations. Hence the reference
+ * count to ensure only the last caller frees the RUI.
+ */
+void
+xfs_rui_release(
+ struct xfs_rui_log_item *ruip)
+{
+ if (atomic_dec_and_test(&ruip->rui_refcount)) {
+ xfs_trans_ail_remove(&ruip->rui_item, SHUTDOWN_LOG_IO_ERROR);
+ xfs_rui_item_free(ruip);
+ }
+}
+
+static inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip)
+{
+ return container_of(lip, struct xfs_rud_log_item, rud_item);
+}
+
+STATIC void
+xfs_rud_item_size(
+ struct xfs_log_item *lip,
+ int *nvecs,
+ int *nbytes)
+{
+ *nvecs += 1;
+ *nbytes += sizeof(struct xfs_rud_log_format);
+}
+
+/*
+ * This is called to fill in the vector of log iovecs for the
+ * given rud log item. We use only 1 iovec, and we point that
+ * at the rud_log_format structure embedded in the rud item.
+ * It is at this point that we assert that all of the extent
+ * slots in the rud item have been filled.
+ */
+STATIC void
+xfs_rud_item_format(
+ struct xfs_log_item *lip,
+ struct xfs_log_vec *lv)
+{
+ struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
+ struct xfs_log_iovec *vecp = NULL;
+
+ rudp->rud_format.rud_type = XFS_LI_RUD;
+ rudp->rud_format.rud_size = 1;
+
+ xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format,
+ sizeof(struct xfs_rud_log_format));
+}
+
+/*
+ * Pinning has no meaning for an rud item, so just return.
+ */
+STATIC void
+xfs_rud_item_pin(
+ struct xfs_log_item *lip)
+{
+}
+
+/*
+ * Since pinning has no meaning for an rud item, unpinning does
+ * not either.
+ */
+STATIC void
+xfs_rud_item_unpin(
+ struct xfs_log_item *lip,
+ int remove)
+{
+}
+
+/*
+ * There isn't much you can do to push on an rud item. It is simply stuck
+ * waiting for the log to be flushed to disk.
+ */
+STATIC uint
+xfs_rud_item_push(
+ struct xfs_log_item *lip,
+ struct list_head *buffer_list)
+{
+ return XFS_ITEM_PINNED;
+}
+
+/*
+ * The RUD is either committed or aborted if the transaction is cancelled. If
+ * the transaction is cancelled, drop our reference to the RUI and free the
+ * RUD.
+ */
+STATIC void
+xfs_rud_item_unlock(
+ struct xfs_log_item *lip)
+{
+ struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
+
+ if (lip->li_flags & XFS_LI_ABORTED) {
+ xfs_rui_release(rudp->rud_ruip);
+ kmem_zone_free(xfs_rud_zone, rudp);
+ }
+}
+
+/*
+ * When the rud item is committed to disk, all we need to do is delete our
+ * reference to our partner rui item and then free ourselves. Since we're
+ * freeing ourselves we must return -1 to keep the transaction code from
+ * further referencing this item.
+ */
+STATIC xfs_lsn_t
+xfs_rud_item_committed(
+ struct xfs_log_item *lip,
+ xfs_lsn_t lsn)
+{
+ struct xfs_rud_log_item *rudp = RUD_ITEM(lip);
+
+ /*
+ * Drop the RUI reference regardless of whether the RUD has been
+ * aborted. Once the RUD transaction is constructed, it is the sole
+ * responsibility of the RUD to release the RUI (even if the RUI is
+ * aborted due to log I/O error).
+ */
+ xfs_rui_release(rudp->rud_ruip);
+ kmem_zone_free(xfs_rud_zone, rudp);
+
+ return (xfs_lsn_t)-1;
+}
+
+/*
+ * The RUD dependency tracking op doesn't do squat. It can't because
+ * it doesn't know where the free extent is coming from. The dependency
+ * tracking has to be handled by the "enclosing" metadata object. For
+ * example, for inodes, the inode is locked throughout the extent freeing
+ * so the dependency should be recorded there.
+ */
+STATIC void
+xfs_rud_item_committing(
+ struct xfs_log_item *lip,
+ xfs_lsn_t lsn)
+{
+}
+
+/*
+ * This is the ops vector shared by all rud log items.
+ */
+static const struct xfs_item_ops xfs_rud_item_ops = {
+ .iop_size = xfs_rud_item_size,
+ .iop_format = xfs_rud_item_format,
+ .iop_pin = xfs_rud_item_pin,
+ .iop_unpin = xfs_rud_item_unpin,
+ .iop_unlock = xfs_rud_item_unlock,
+ .iop_committed = xfs_rud_item_committed,
+ .iop_push = xfs_rud_item_push,
+ .iop_committing = xfs_rud_item_committing,
+};
+
+/*
+ * Allocate and initialize an rud item with the given number of extents.
+ */
+struct xfs_rud_log_item *
+xfs_rud_init(
+ struct xfs_mount *mp,
+ struct xfs_rui_log_item *ruip)
+
+{
+ struct xfs_rud_log_item *rudp;
+
+ rudp = kmem_zone_zalloc(xfs_rud_zone, KM_SLEEP);
+ xfs_log_item_init(mp, &rudp->rud_item, XFS_LI_RUD, &xfs_rud_item_ops);
+ rudp->rud_ruip = ruip;
+ rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id;
+
+ return rudp;
+}
+
+/*
+ * Process an rmap update intent item that was recovered from the log.
+ * We need to update the rmapbt.
+ */
+int
+xfs_rui_recover(
+ struct xfs_mount *mp,
+ struct xfs_rui_log_item *ruip)
+{
+ int i;
+ int error = 0;
+ struct xfs_map_extent *rmap;
+ xfs_fsblock_t startblock_fsb;
+ bool op_ok;
+ struct xfs_rud_log_item *rudp;
+ enum xfs_rmap_intent_type type;
+ int whichfork;
+ xfs_exntst_t state;
+ struct xfs_trans *tp;
+ struct xfs_btree_cur *rcur = NULL;
+
+ ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags));
+
+ /*
+ * First check the validity of the extents described by the
+ * RUI. If any are bad, then assume that all are bad and
+ * just toss the RUI.
+ */
+ for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
+ rmap = &ruip->rui_format.rui_extents[i];
+ startblock_fsb = XFS_BB_TO_FSB(mp,
+ XFS_FSB_TO_DADDR(mp, rmap->me_startblock));
+ switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
+ case XFS_RMAP_EXTENT_MAP:
+ case XFS_RMAP_EXTENT_UNMAP:
+ case XFS_RMAP_EXTENT_CONVERT:
+ case XFS_RMAP_EXTENT_ALLOC:
+ case XFS_RMAP_EXTENT_FREE:
+ op_ok = true;
+ break;
+ default:
+ op_ok = false;
+ break;
+ }
+ if (!op_ok || startblock_fsb == 0 ||
+ rmap->me_len == 0 ||
+ startblock_fsb >= mp->m_sb.sb_dblocks ||
+ rmap->me_len >= mp->m_sb.sb_agblocks ||
+ (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS)) {
+ /*
+ * This will pull the RUI from the AIL and
+ * free the memory associated with it.
+ */
+ set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags);
+ xfs_rui_release(ruip);
+ return -EIO;
+ }
+ }
+
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
+ if (error)
+ return error;
+ rudp = xfs_trans_get_rud(tp, ruip);
+
+ for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
+ rmap = &ruip->rui_format.rui_extents[i];
+ state = (rmap->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
+ XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
+ whichfork = (rmap->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
+ XFS_ATTR_FORK : XFS_DATA_FORK;
+ switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
+ case XFS_RMAP_EXTENT_MAP:
+ type = XFS_RMAP_MAP;
+ break;
+ case XFS_RMAP_EXTENT_UNMAP:
+ type = XFS_RMAP_UNMAP;
+ break;
+ case XFS_RMAP_EXTENT_CONVERT:
+ type = XFS_RMAP_CONVERT;
+ break;
+ case XFS_RMAP_EXTENT_ALLOC:
+ type = XFS_RMAP_ALLOC;
+ break;
+ case XFS_RMAP_EXTENT_FREE:
+ type = XFS_RMAP_FREE;
+ break;
+ default:
+ error = -EFSCORRUPTED;
+ goto abort_error;
+ }
+ error = xfs_trans_log_finish_rmap_update(tp, rudp, type,
+ rmap->me_owner, whichfork,
+ rmap->me_startoff, rmap->me_startblock,
+ rmap->me_len, state, &rcur);
+ if (error)
+ goto abort_error;
+
+ }
+
+ xfs_rmap_finish_one_cleanup(tp, rcur, error);
+ set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags);
+ error = xfs_trans_commit(tp);
+ return error;
+
+abort_error:
+ xfs_rmap_finish_one_cleanup(tp, rcur, error);
+ xfs_trans_cancel(tp);
+ return error;
+}
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
new file mode 100644
index 000000000000..aefcc3a318a5
--- /dev/null
+++ b/fs/xfs/xfs_rmap_item.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __XFS_RMAP_ITEM_H__
+#define __XFS_RMAP_ITEM_H__
+
+/*
+ * There are (currently) three pairs of rmap btree redo item types: map, unmap,
+ * and convert. The common abbreviations for these are RUI (rmap update
+ * intent) and RUD (rmap update done). The redo item type is encoded in the
+ * flags field of each xfs_map_extent.
+ *
+ * *I items should be recorded in the *first* of a series of rolled
+ * transactions, and the *D items should be recorded in the same transaction
+ * that records the associated rmapbt updates. Typically, the first
+ * transaction will record a bmbt update, followed by some number of
+ * transactions containing rmapbt updates, and finally transactions with any
+ * bnobt/cntbt updates.
+ *
+ * Should the system crash after the commit of the first transaction but
+ * before the commit of the final transaction in a series, log recovery will
+ * use the redo information recorded by the intent items to replay the
+ * (rmapbt/bnobt/cntbt) metadata updates in the non-first transaction.
+ */
+
+/* kernel only RUI/RUD definitions */
+
+struct xfs_mount;
+struct kmem_zone;
+
+/*
+ * Max number of extents in fast allocation path.
+ */
+#define XFS_RUI_MAX_FAST_EXTENTS 16
+
+/*
+ * Define RUI flag bits. Manipulated by set/clear/test_bit operators.
+ */
+#define XFS_RUI_RECOVERED 1
+
+/*
+ * This is the "rmap update intent" log item. It is used to log the fact that
+ * some reverse mappings need to change. It is used in conjunction with the
+ * "rmap update done" log item described below.
+ *
+ * These log items follow the same rules as struct xfs_efi_log_item; see the
+ * comments about that structure (in xfs_extfree_item.h) for more details.
+ */
+struct xfs_rui_log_item {
+ struct xfs_log_item rui_item;
+ atomic_t rui_refcount;
+ atomic_t rui_next_extent;
+ unsigned long rui_flags; /* misc flags */
+ struct xfs_rui_log_format rui_format;
+};
+
+/*
+ * This is the "rmap update done" log item. It is used to log the fact that
+ * some rmapbt updates mentioned in an earlier rui item have been performed.
+ */
+struct xfs_rud_log_item {
+ struct xfs_log_item rud_item;
+ struct xfs_rui_log_item *rud_ruip;
+ struct xfs_rud_log_format rud_format;
+};
+
+extern struct kmem_zone *xfs_rui_zone;
+extern struct kmem_zone *xfs_rud_zone;
+
+struct xfs_rui_log_item *xfs_rui_init(struct xfs_mount *, uint);
+struct xfs_rud_log_item *xfs_rud_init(struct xfs_mount *,
+ struct xfs_rui_log_item *);
+int xfs_rui_copy_format(struct xfs_log_iovec *buf,
+ struct xfs_rui_log_format *dst_rui_fmt);
+void xfs_rui_item_free(struct xfs_rui_log_item *);
+void xfs_rui_release(struct xfs_rui_log_item *);
+int xfs_rui_recover(struct xfs_mount *mp, struct xfs_rui_log_item *ruip);
+
+#endif /* __XFS_RMAP_ITEM_H__ */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 3938b37d1043..802bcc326d9f 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -23,6 +23,7 @@
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
#include "xfs_bmap_util.h"
@@ -769,7 +770,7 @@ xfs_growfs_rt_alloc(
xfs_daddr_t d; /* disk block address */
int error; /* error return value */
xfs_fsblock_t firstblock;/* first block allocated in xaction */
- struct xfs_bmap_free flist; /* list of freed blocks */
+ struct xfs_defer_ops dfops; /* list of freed blocks */
xfs_fsblock_t fsbno; /* filesystem block for bno */
struct xfs_bmbt_irec map; /* block map output */
int nmap; /* number of block maps */
@@ -794,14 +795,14 @@ xfs_growfs_rt_alloc(
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_bmap_init(&flist, &firstblock);
+ xfs_defer_init(&dfops, &firstblock);
/*
* Allocate blocks to the bitmap file.
*/
nmap = 1;
error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks,
XFS_BMAPI_METADATA, &firstblock,
- resblks, &map, &nmap, &flist);
+ resblks, &map, &nmap, &dfops);
if (!error && nmap < 1)
error = -ENOSPC;
if (error)
@@ -809,7 +810,7 @@ xfs_growfs_rt_alloc(
/*
* Free any blocks freed up in the transaction, then commit.
*/
- error = xfs_bmap_finish(&tp, &flist, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
error = xfs_trans_commit(tp);
@@ -862,7 +863,7 @@ xfs_growfs_rt_alloc(
return 0;
out_bmap_cancel:
- xfs_bmap_cancel(&flist);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
return error;
diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c
index d266e835ecc3..6e812fe0fd43 100644
--- a/fs/xfs/xfs_stats.c
+++ b/fs/xfs/xfs_stats.c
@@ -61,6 +61,7 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf)
{ "bmbt2", XFSSTAT_END_BMBT_V2 },
{ "ibt2", XFSSTAT_END_IBT_V2 },
{ "fibt2", XFSSTAT_END_FIBT_V2 },
+ { "rmapbt", XFSSTAT_END_RMAP_V2 },
/* we print both series of quota information together */
{ "qm", XFSSTAT_END_QM },
};
diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h
index 483b0eff1988..657865f51e78 100644
--- a/fs/xfs/xfs_stats.h
+++ b/fs/xfs/xfs_stats.h
@@ -197,7 +197,23 @@ struct xfsstats {
__uint32_t xs_fibt_2_alloc;
__uint32_t xs_fibt_2_free;
__uint32_t xs_fibt_2_moves;
-#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_FIBT_V2+6)
+#define XFSSTAT_END_RMAP_V2 (XFSSTAT_END_FIBT_V2+15)
+ __uint32_t xs_rmap_2_lookup;
+ __uint32_t xs_rmap_2_compare;
+ __uint32_t xs_rmap_2_insrec;
+ __uint32_t xs_rmap_2_delrec;
+ __uint32_t xs_rmap_2_newroot;
+ __uint32_t xs_rmap_2_killroot;
+ __uint32_t xs_rmap_2_increment;
+ __uint32_t xs_rmap_2_decrement;
+ __uint32_t xs_rmap_2_lshift;
+ __uint32_t xs_rmap_2_rshift;
+ __uint32_t xs_rmap_2_split;
+ __uint32_t xs_rmap_2_join;
+ __uint32_t xs_rmap_2_alloc;
+ __uint32_t xs_rmap_2_free;
+ __uint32_t xs_rmap_2_moves;
+#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_RMAP_V2+6)
__uint32_t xs_qm_dqreclaims;
__uint32_t xs_qm_dqreclaim_misses;
__uint32_t xs_qm_dquot_dups;
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 0303f1005f88..24ef83ef04de 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -46,6 +46,7 @@
#include "xfs_quota.h"
#include "xfs_sysfs.h"
#include "xfs_ondisk.h"
+#include "xfs_rmap_item.h"
#include <linux/namei.h>
#include <linux/init.h>
@@ -1075,7 +1076,7 @@ xfs_fs_statfs(
statp->f_blocks = sbp->sb_dblocks - lsize;
spin_unlock(&mp->m_sb_lock);
- statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp);
+ statp->f_bfree = fdblocks - mp->m_alloc_set_aside;
statp->f_bavail = statp->f_bfree;
fakeinos = statp->f_bfree << sbp->sb_inopblog;
@@ -1573,6 +1574,10 @@ xfs_fs_fill_super(
}
}
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ xfs_alert(mp,
+ "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!");
+
error = xfs_mountfs(mp);
if (error)
goto out_filestream_unmount;
@@ -1697,7 +1702,7 @@ xfs_init_zones(void)
goto out_free_ioend_bioset;
xfs_bmap_free_item_zone = kmem_zone_init(
- sizeof(struct xfs_bmap_free_item),
+ sizeof(struct xfs_extent_free_item),
"xfs_bmap_free_item");
if (!xfs_bmap_free_item_zone)
goto out_destroy_log_ticket_zone;
@@ -1765,8 +1770,24 @@ xfs_init_zones(void)
if (!xfs_icreate_zone)
goto out_destroy_ili_zone;
+ xfs_rud_zone = kmem_zone_init(sizeof(struct xfs_rud_log_item),
+ "xfs_rud_item");
+ if (!xfs_rud_zone)
+ goto out_destroy_icreate_zone;
+
+ xfs_rui_zone = kmem_zone_init((sizeof(struct xfs_rui_log_item) +
+ ((XFS_RUI_MAX_FAST_EXTENTS - 1) *
+ sizeof(struct xfs_map_extent))),
+ "xfs_rui_item");
+ if (!xfs_rui_zone)
+ goto out_destroy_rud_zone;
+
return 0;
+ out_destroy_rud_zone:
+ kmem_zone_destroy(xfs_rud_zone);
+ out_destroy_icreate_zone:
+ kmem_zone_destroy(xfs_icreate_zone);
out_destroy_ili_zone:
kmem_zone_destroy(xfs_ili_zone);
out_destroy_inode_zone:
@@ -1805,6 +1826,8 @@ xfs_destroy_zones(void)
* destroy caches.
*/
rcu_barrier();
+ kmem_zone_destroy(xfs_rui_zone);
+ kmem_zone_destroy(xfs_rud_zone);
kmem_zone_destroy(xfs_icreate_zone);
kmem_zone_destroy(xfs_ili_zone);
kmem_zone_destroy(xfs_inode_zone);
@@ -1854,6 +1877,9 @@ init_xfs_fs(void)
printk(KERN_INFO XFS_VERSION_STRING " with "
XFS_BUILD_OPTIONS " enabled\n");
+ xfs_extent_free_init_defer_op();
+ xfs_rmap_update_init_defer_op();
+
xfs_dir_startup();
error = xfs_init_zones();
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 08a46c6181fd..58142aeeeea6 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -26,6 +26,7 @@
#include "xfs_mount.h"
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
+#include "xfs_defer.h"
#include "xfs_dir2.h"
#include "xfs_inode.h"
#include "xfs_ialloc.h"
@@ -172,7 +173,7 @@ xfs_symlink(
struct xfs_inode *ip = NULL;
int error = 0;
int pathlen;
- struct xfs_bmap_free free_list;
+ struct xfs_defer_ops dfops;
xfs_fsblock_t first_block;
bool unlock_dp_on_error = false;
xfs_fileoff_t first_fsb;
@@ -269,7 +270,7 @@ xfs_symlink(
* Initialize the bmap freelist prior to calling either
* bmapi or the directory create code.
*/
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
/*
* Allocate an inode for the symlink.
@@ -313,7 +314,7 @@ xfs_symlink(
error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
XFS_BMAPI_METADATA, &first_block, resblks,
- mval, &nmaps, &free_list);
+ mval, &nmaps, &dfops);
if (error)
goto out_bmap_cancel;
@@ -361,7 +362,7 @@ xfs_symlink(
* Create the directory entry for the symlink.
*/
error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
- &first_block, &free_list, resblks);
+ &first_block, &dfops, resblks);
if (error)
goto out_bmap_cancel;
xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -376,7 +377,7 @@ xfs_symlink(
xfs_trans_set_sync(tp);
}
- error = xfs_bmap_finish(&tp, &free_list, NULL);
+ error = xfs_defer_finish(&tp, &dfops, NULL);
if (error)
goto out_bmap_cancel;
@@ -392,7 +393,7 @@ xfs_symlink(
return 0;
out_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
out_trans_cancel:
xfs_trans_cancel(tp);
out_release_inode:
@@ -426,7 +427,7 @@ xfs_inactive_symlink_rmt(
int done;
int error;
xfs_fsblock_t first_block;
- xfs_bmap_free_t free_list;
+ struct xfs_defer_ops dfops;
int i;
xfs_mount_t *mp;
xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
@@ -465,7 +466,7 @@ xfs_inactive_symlink_rmt(
* Find the block(s) so we can inval and unmap them.
*/
done = 0;
- xfs_bmap_init(&free_list, &first_block);
+ xfs_defer_init(&dfops, &first_block);
nmaps = ARRAY_SIZE(mval);
error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
mval, &nmaps, 0);
@@ -485,17 +486,17 @@ xfs_inactive_symlink_rmt(
xfs_trans_binval(tp, bp);
}
/*
- * Unmap the dead block(s) to the free_list.
+ * Unmap the dead block(s) to the dfops.
*/
error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps,
- &first_block, &free_list, &done);
+ &first_block, &dfops, &done);
if (error)
goto error_bmap_cancel;
ASSERT(done);
/*
* Commit the first transaction. This logs the EFI and the inode.
*/
- error = xfs_bmap_finish(&tp, &free_list, ip);
+ error = xfs_defer_finish(&tp, &dfops, ip);
if (error)
goto error_bmap_cancel;
/*
@@ -525,7 +526,7 @@ xfs_inactive_symlink_rmt(
return 0;
error_bmap_cancel:
- xfs_bmap_cancel(&free_list);
+ xfs_defer_cancel(&dfops);
error_trans_cancel:
xfs_trans_cancel(tp);
error_unlock:
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c
index 13a029806805..7f17ae6d709a 100644
--- a/fs/xfs/xfs_trace.c
+++ b/fs/xfs/xfs_trace.c
@@ -22,7 +22,9 @@
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_da_format.h"
+#include "xfs_defer.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_da_btree.h"
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 145169093fe0..551b7e26980c 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -38,6 +38,7 @@ struct xlog_recover_item;
struct xfs_buf_log_format;
struct xfs_inode_log_format;
struct xfs_bmbt_irec;
+struct xfs_btree_cur;
DECLARE_EVENT_CLASS(xfs_attr_list_class,
TP_PROTO(struct xfs_attr_list_context *ctx),
@@ -2185,6 +2186,379 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall);
DEFINE_DISCARD_EVENT(xfs_discard_exclude);
DEFINE_DISCARD_EVENT(xfs_discard_busy);
+/* btree cursor events */
+DECLARE_EVENT_CLASS(xfs_btree_cur_class,
+ TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp),
+ TP_ARGS(cur, level, bp),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_btnum_t, btnum)
+ __field(int, level)
+ __field(int, nlevels)
+ __field(int, ptr)
+ __field(xfs_daddr_t, daddr)
+ ),
+ TP_fast_assign(
+ __entry->dev = cur->bc_mp->m_super->s_dev;
+ __entry->btnum = cur->bc_btnum;
+ __entry->level = level;
+ __entry->nlevels = cur->bc_nlevels;
+ __entry->ptr = cur->bc_ptrs[level];
+ __entry->daddr = bp ? bp->b_bn : -1;
+ ),
+ TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->btnum,
+ __entry->level,
+ __entry->nlevels,
+ __entry->ptr,
+ (unsigned long long)__entry->daddr)
+)
+
+#define DEFINE_BTREE_CUR_EVENT(name) \
+DEFINE_EVENT(xfs_btree_cur_class, name, \
+ TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \
+ TP_ARGS(cur, level, bp))
+DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys);
+DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range);
+
+/* deferred ops */
+struct xfs_defer_pending;
+struct xfs_defer_intake;
+struct xfs_defer_ops;
+
+DECLARE_EVENT_CLASS(xfs_defer_class,
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop),
+ TP_ARGS(mp, dop),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(void *, dop)
+ __field(bool, committed)
+ __field(bool, low)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp ? mp->m_super->s_dev : 0;
+ __entry->dop = dop;
+ __entry->committed = dop->dop_committed;
+ __entry->low = dop->dop_low;
+ ),
+ TP_printk("dev %d:%d ops %p committed %d low %d\n",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->dop,
+ __entry->committed,
+ __entry->low)
+)
+#define DEFINE_DEFER_EVENT(name) \
+DEFINE_EVENT(xfs_defer_class, name, \
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop), \
+ TP_ARGS(mp, dop))
+
+DECLARE_EVENT_CLASS(xfs_defer_error_class,
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error),
+ TP_ARGS(mp, dop, error),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(void *, dop)
+ __field(bool, committed)
+ __field(bool, low)
+ __field(int, error)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp ? mp->m_super->s_dev : 0;
+ __entry->dop = dop;
+ __entry->committed = dop->dop_committed;
+ __entry->low = dop->dop_low;
+ __entry->error = error;
+ ),
+ TP_printk("dev %d:%d ops %p committed %d low %d err %d\n",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->dop,
+ __entry->committed,
+ __entry->low,
+ __entry->error)
+)
+#define DEFINE_DEFER_ERROR_EVENT(name) \
+DEFINE_EVENT(xfs_defer_error_class, name, \
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \
+ TP_ARGS(mp, dop, error))
+
+DECLARE_EVENT_CLASS(xfs_defer_pending_class,
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp),
+ TP_ARGS(mp, dfp),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(int, type)
+ __field(void *, intent)
+ __field(bool, committed)
+ __field(int, nr)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp ? mp->m_super->s_dev : 0;
+ __entry->type = dfp->dfp_type->type;
+ __entry->intent = dfp->dfp_intent;
+ __entry->committed = dfp->dfp_committed;
+ __entry->nr = dfp->dfp_count;
+ ),
+ TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->type,
+ __entry->intent,
+ __entry->committed,
+ __entry->nr)
+)
+#define DEFINE_DEFER_PENDING_EVENT(name) \
+DEFINE_EVENT(xfs_defer_pending_class, name, \
+ TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), \
+ TP_ARGS(mp, dfp))
+
+DECLARE_EVENT_CLASS(xfs_phys_extent_deferred_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+ int type, xfs_agblock_t agbno, xfs_extlen_t len),
+ TP_ARGS(mp, agno, type, agbno, len),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(int, type)
+ __field(xfs_agblock_t, agbno)
+ __field(xfs_extlen_t, len)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->type = type;
+ __entry->agbno = agbno;
+ __entry->len = len;
+ ),
+ TP_printk("dev %d:%d op %d agno %u agbno %u len %u",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->type,
+ __entry->agno,
+ __entry->agbno,
+ __entry->len)
+);
+#define DEFINE_PHYS_EXTENT_DEFERRED_EVENT(name) \
+DEFINE_EVENT(xfs_phys_extent_deferred_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+ int type, \
+ xfs_agblock_t bno, \
+ xfs_extlen_t len), \
+ TP_ARGS(mp, agno, type, bno, len))
+
+DECLARE_EVENT_CLASS(xfs_map_extent_deferred_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+ int op,
+ xfs_agblock_t agbno,
+ xfs_ino_t ino,
+ int whichfork,
+ xfs_fileoff_t offset,
+ xfs_filblks_t len,
+ xfs_exntst_t state),
+ TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(xfs_ino_t, ino)
+ __field(xfs_agblock_t, agbno)
+ __field(int, whichfork)
+ __field(xfs_fileoff_t, l_loff)
+ __field(xfs_filblks_t, l_len)
+ __field(xfs_exntst_t, l_state)
+ __field(int, op)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->ino = ino;
+ __entry->agbno = agbno;
+ __entry->whichfork = whichfork;
+ __entry->l_loff = offset;
+ __entry->l_len = len;
+ __entry->l_state = state;
+ __entry->op = op;
+ ),
+ TP_printk("dev %d:%d op %d agno %u agbno %u owner %lld %s offset %llu len %llu state %d",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->op,
+ __entry->agno,
+ __entry->agbno,
+ __entry->ino,
+ __entry->whichfork == XFS_ATTR_FORK ? "attr" : "data",
+ __entry->l_loff,
+ __entry->l_len,
+ __entry->l_state)
+);
+#define DEFINE_MAP_EXTENT_DEFERRED_EVENT(name) \
+DEFINE_EVENT(xfs_map_extent_deferred_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+ int op, \
+ xfs_agblock_t agbno, \
+ xfs_ino_t ino, \
+ int whichfork, \
+ xfs_fileoff_t offset, \
+ xfs_filblks_t len, \
+ xfs_exntst_t state), \
+ TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state))
+
+DEFINE_DEFER_EVENT(xfs_defer_init);
+DEFINE_DEFER_EVENT(xfs_defer_cancel);
+DEFINE_DEFER_EVENT(xfs_defer_trans_roll);
+DEFINE_DEFER_EVENT(xfs_defer_trans_abort);
+DEFINE_DEFER_EVENT(xfs_defer_finish);
+DEFINE_DEFER_EVENT(xfs_defer_finish_done);
+
+DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error);
+DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error);
+DEFINE_DEFER_ERROR_EVENT(xfs_defer_op_finish_error);
+
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work);
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel);
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_commit);
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel);
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish);
+DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort);
+
+#define DEFINE_BMAP_FREE_DEFERRED_EVENT DEFINE_PHYS_EXTENT_DEFERRED_EVENT
+DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_defer);
+DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_deferred);
+
+/* rmap tracepoints */
+DECLARE_EVENT_CLASS(xfs_rmap_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten,
+ struct xfs_owner_info *oinfo),
+ TP_ARGS(mp, agno, agbno, len, unwritten, oinfo),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(xfs_agblock_t, agbno)
+ __field(xfs_extlen_t, len)
+ __field(uint64_t, owner)
+ __field(uint64_t, offset)
+ __field(unsigned long, flags)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->agbno = agbno;
+ __entry->len = len;
+ __entry->owner = oinfo->oi_owner;
+ __entry->offset = oinfo->oi_offset;
+ __entry->flags = oinfo->oi_flags;
+ if (unwritten)
+ __entry->flags |= XFS_RMAP_UNWRITTEN;
+ ),
+ TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%lx",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->agbno,
+ __entry->len,
+ __entry->owner,
+ __entry->offset,
+ __entry->flags)
+);
+#define DEFINE_RMAP_EVENT(name) \
+DEFINE_EVENT(xfs_rmap_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+ xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \
+ struct xfs_owner_info *oinfo), \
+ TP_ARGS(mp, agno, agbno, len, unwritten, oinfo))
+
+/* simple AG-based error/%ip tracepoint class */
+DECLARE_EVENT_CLASS(xfs_ag_error_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error,
+ unsigned long caller_ip),
+ TP_ARGS(mp, agno, error, caller_ip),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(int, error)
+ __field(unsigned long, caller_ip)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->error = error;
+ __entry->caller_ip = caller_ip;
+ ),
+ TP_printk("dev %d:%d agno %u error %d caller %ps",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->error,
+ (char *)__entry->caller_ip)
+);
+
+#define DEFINE_AG_ERROR_EVENT(name) \
+DEFINE_EVENT(xfs_ag_error_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error, \
+ unsigned long caller_ip), \
+ TP_ARGS(mp, agno, error, caller_ip))
+
+DEFINE_RMAP_EVENT(xfs_rmap_unmap);
+DEFINE_RMAP_EVENT(xfs_rmap_unmap_done);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_unmap_error);
+DEFINE_RMAP_EVENT(xfs_rmap_map);
+DEFINE_RMAP_EVENT(xfs_rmap_map_done);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_map_error);
+DEFINE_RMAP_EVENT(xfs_rmap_convert);
+DEFINE_RMAP_EVENT(xfs_rmap_convert_done);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_error);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_state);
+
+DECLARE_EVENT_CLASS(xfs_rmapbt_class,
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agblock_t agbno, xfs_extlen_t len,
+ uint64_t owner, uint64_t offset, unsigned int flags),
+ TP_ARGS(mp, agno, agbno, len, owner, offset, flags),
+ TP_STRUCT__entry(
+ __field(dev_t, dev)
+ __field(xfs_agnumber_t, agno)
+ __field(xfs_agblock_t, agbno)
+ __field(xfs_extlen_t, len)
+ __field(uint64_t, owner)
+ __field(uint64_t, offset)
+ __field(unsigned int, flags)
+ ),
+ TP_fast_assign(
+ __entry->dev = mp->m_super->s_dev;
+ __entry->agno = agno;
+ __entry->agbno = agbno;
+ __entry->len = len;
+ __entry->owner = owner;
+ __entry->offset = offset;
+ __entry->flags = flags;
+ ),
+ TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%x",
+ MAJOR(__entry->dev), MINOR(__entry->dev),
+ __entry->agno,
+ __entry->agbno,
+ __entry->len,
+ __entry->owner,
+ __entry->offset,
+ __entry->flags)
+);
+#define DEFINE_RMAPBT_EVENT(name) \
+DEFINE_EVENT(xfs_rmapbt_class, name, \
+ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
+ xfs_agblock_t agbno, xfs_extlen_t len, \
+ uint64_t owner, uint64_t offset, unsigned int flags), \
+ TP_ARGS(mp, agno, agbno, len, owner, offset, flags))
+
+#define DEFINE_RMAP_DEFERRED_EVENT DEFINE_MAP_EXTENT_DEFERRED_EVENT
+DEFINE_RMAP_DEFERRED_EVENT(xfs_rmap_defer);
+DEFINE_RMAP_DEFERRED_EVENT(xfs_rmap_deferred);
+
+DEFINE_BUSY_EVENT(xfs_rmapbt_alloc_block);
+DEFINE_BUSY_EVENT(xfs_rmapbt_free_block);
+DEFINE_RMAPBT_EVENT(xfs_rmap_update);
+DEFINE_RMAPBT_EVENT(xfs_rmap_insert);
+DEFINE_RMAPBT_EVENT(xfs_rmap_delete);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_insert_error);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_delete_error);
+DEFINE_AG_ERROR_EVENT(xfs_rmap_update_error);
+DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result);
+DEFINE_RMAPBT_EVENT(xfs_rmap_find_right_neighbor_result);
+DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result);
+
#endif /* _TRACE_XFS_H */
#undef TRACE_INCLUDE_PATH
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 9b2b9fa89331..e2bf86aad33d 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -33,6 +33,9 @@ struct xfs_trans;
struct xfs_trans_res;
struct xfs_dquot_acct;
struct xfs_busy_extent;
+struct xfs_rud_log_item;
+struct xfs_rui_log_item;
+struct xfs_btree_cur;
typedef struct xfs_log_item {
struct list_head li_ail; /* AIL pointers */
@@ -210,17 +213,14 @@ void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
-struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint);
-void xfs_trans_log_efi_extent(xfs_trans_t *,
- struct xfs_efi_log_item *,
- xfs_fsblock_t,
- xfs_extlen_t);
-struct xfs_efd_log_item *xfs_trans_get_efd(xfs_trans_t *,
+
+void xfs_extent_free_init_defer_op(void);
+struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *,
struct xfs_efi_log_item *,
uint);
int xfs_trans_free_extent(struct xfs_trans *,
struct xfs_efd_log_item *, xfs_fsblock_t,
- xfs_extlen_t);
+ xfs_extlen_t, struct xfs_owner_info *);
int xfs_trans_commit(struct xfs_trans *);
int __xfs_trans_roll(struct xfs_trans **, struct xfs_inode *, int *);
int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *);
@@ -236,4 +236,16 @@ void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp,
extern kmem_zone_t *xfs_trans_zone;
extern kmem_zone_t *xfs_log_item_desc_zone;
+/* rmap updates */
+enum xfs_rmap_intent_type;
+
+void xfs_rmap_update_init_defer_op(void);
+struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp,
+ struct xfs_rui_log_item *ruip);
+int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
+ struct xfs_rud_log_item *rudp, enum xfs_rmap_intent_type type,
+ __uint64_t owner, int whichfork, xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock, xfs_filblks_t blockcount,
+ xfs_exntst_t state, struct xfs_btree_cur **pcur);
+
#endif /* __XFS_TRANS_H__ */
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index a96ae540eb62..459ddec137a4 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -21,66 +21,15 @@
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
#include "xfs_mount.h"
+#include "xfs_defer.h"
#include "xfs_trans.h"
#include "xfs_trans_priv.h"
#include "xfs_extfree_item.h"
#include "xfs_alloc.h"
-
-/*
- * This routine is called to allocate an "extent free intention"
- * log item that will hold nextents worth of extents. The
- * caller must use all nextents extents, because we are not
- * flexible about this at all.
- */
-xfs_efi_log_item_t *
-xfs_trans_get_efi(xfs_trans_t *tp,
- uint nextents)
-{
- xfs_efi_log_item_t *efip;
-
- ASSERT(tp != NULL);
- ASSERT(nextents > 0);
-
- efip = xfs_efi_init(tp->t_mountp, nextents);
- ASSERT(efip != NULL);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- xfs_trans_add_item(tp, &efip->efi_item);
- return efip;
-}
-
-/*
- * This routine is called to indicate that the described
- * extent is to be logged as needing to be freed. It should
- * be called once for each extent to be freed.
- */
-void
-xfs_trans_log_efi_extent(xfs_trans_t *tp,
- xfs_efi_log_item_t *efip,
- xfs_fsblock_t start_block,
- xfs_extlen_t ext_len)
-{
- uint next_extent;
- xfs_extent_t *extp;
-
- tp->t_flags |= XFS_TRANS_DIRTY;
- efip->efi_item.li_desc->lid_flags |= XFS_LID_DIRTY;
-
- /*
- * atomic_inc_return gives us the value after the increment;
- * we want to use it as an array index so we need to subtract 1 from
- * it.
- */
- next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
- ASSERT(next_extent < efip->efi_format.efi_nextents);
- extp = &(efip->efi_format.efi_extents[next_extent]);
- extp->ext_start = start_block;
- extp->ext_len = ext_len;
-}
-
+#include "xfs_bmap.h"
+#include "xfs_trace.h"
/*
* This routine is called to allocate an "extent free done"
@@ -88,12 +37,12 @@ xfs_trans_log_efi_extent(xfs_trans_t *tp,
* caller must use all nextents extents, because we are not
* flexible about this at all.
*/
-xfs_efd_log_item_t *
-xfs_trans_get_efd(xfs_trans_t *tp,
- xfs_efi_log_item_t *efip,
- uint nextents)
+struct xfs_efd_log_item *
+xfs_trans_get_efd(struct xfs_trans *tp,
+ struct xfs_efi_log_item *efip,
+ uint nextents)
{
- xfs_efd_log_item_t *efdp;
+ struct xfs_efd_log_item *efdp;
ASSERT(tp != NULL);
ASSERT(nextents > 0);
@@ -118,13 +67,19 @@ xfs_trans_free_extent(
struct xfs_trans *tp,
struct xfs_efd_log_item *efdp,
xfs_fsblock_t start_block,
- xfs_extlen_t ext_len)
+ xfs_extlen_t ext_len,
+ struct xfs_owner_info *oinfo)
{
+ struct xfs_mount *mp = tp->t_mountp;
uint next_extent;
+ xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, start_block);
+ xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, start_block);
struct xfs_extent *extp;
int error;
- error = xfs_free_extent(tp, start_block, ext_len);
+ trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
+
+ error = xfs_free_extent(tp, start_block, ext_len, oinfo);
/*
* Mark the transaction dirty, even on error. This ensures the
@@ -145,3 +100,139 @@ xfs_trans_free_extent(
return error;
}
+
+/* Sort bmap items by AG. */
+static int
+xfs_extent_free_diff_items(
+ void *priv,
+ struct list_head *a,
+ struct list_head *b)
+{
+ struct xfs_mount *mp = priv;
+ struct xfs_extent_free_item *ra;
+ struct xfs_extent_free_item *rb;
+
+ ra = container_of(a, struct xfs_extent_free_item, xefi_list);
+ rb = container_of(b, struct xfs_extent_free_item, xefi_list);
+ return XFS_FSB_TO_AGNO(mp, ra->xefi_startblock) -
+ XFS_FSB_TO_AGNO(mp, rb->xefi_startblock);
+}
+
+/* Get an EFI. */
+STATIC void *
+xfs_extent_free_create_intent(
+ struct xfs_trans *tp,
+ unsigned int count)
+{
+ struct xfs_efi_log_item *efip;
+
+ ASSERT(tp != NULL);
+ ASSERT(count > 0);
+
+ efip = xfs_efi_init(tp->t_mountp, count);
+ ASSERT(efip != NULL);
+
+ /*
+ * Get a log_item_desc to point at the new item.
+ */
+ xfs_trans_add_item(tp, &efip->efi_item);
+ return efip;
+}
+
+/* Log a free extent to the intent item. */
+STATIC void
+xfs_extent_free_log_item(
+ struct xfs_trans *tp,
+ void *intent,
+ struct list_head *item)
+{
+ struct xfs_efi_log_item *efip = intent;
+ struct xfs_extent_free_item *free;
+ uint next_extent;
+ struct xfs_extent *extp;
+
+ free = container_of(item, struct xfs_extent_free_item, xefi_list);
+
+ tp->t_flags |= XFS_TRANS_DIRTY;
+ efip->efi_item.li_desc->lid_flags |= XFS_LID_DIRTY;
+
+ /*
+ * atomic_inc_return gives us the value after the increment;
+ * we want to use it as an array index so we need to subtract 1 from
+ * it.
+ */
+ next_extent = atomic_inc_return(&efip->efi_next_extent) - 1;
+ ASSERT(next_extent < efip->efi_format.efi_nextents);
+ extp = &efip->efi_format.efi_extents[next_extent];
+ extp->ext_start = free->xefi_startblock;
+ extp->ext_len = free->xefi_blockcount;
+}
+
+/* Get an EFD so we can process all the free extents. */
+STATIC void *
+xfs_extent_free_create_done(
+ struct xfs_trans *tp,
+ void *intent,
+ unsigned int count)
+{
+ return xfs_trans_get_efd(tp, intent, count);
+}
+
+/* Process a free extent. */
+STATIC int
+xfs_extent_free_finish_item(
+ struct xfs_trans *tp,
+ struct xfs_defer_ops *dop,
+ struct list_head *item,
+ void *done_item,
+ void **state)
+{
+ struct xfs_extent_free_item *free;
+ int error;
+
+ free = container_of(item, struct xfs_extent_free_item, xefi_list);
+ error = xfs_trans_free_extent(tp, done_item,
+ free->xefi_startblock,
+ free->xefi_blockcount,
+ &free->xefi_oinfo);
+ kmem_free(free);
+ return error;
+}
+
+/* Abort all pending EFIs. */
+STATIC void
+xfs_extent_free_abort_intent(
+ void *intent)
+{
+ xfs_efi_release(intent);
+}
+
+/* Cancel a free extent. */
+STATIC void
+xfs_extent_free_cancel_item(
+ struct list_head *item)
+{
+ struct xfs_extent_free_item *free;
+
+ free = container_of(item, struct xfs_extent_free_item, xefi_list);
+ kmem_free(free);
+}
+
+static const struct xfs_defer_op_type xfs_extent_free_defer_type = {
+ .type = XFS_DEFER_OPS_TYPE_FREE,
+ .max_items = XFS_EFI_MAX_FAST_EXTENTS,
+ .diff_items = xfs_extent_free_diff_items,
+ .create_intent = xfs_extent_free_create_intent,
+ .abort_intent = xfs_extent_free_abort_intent,
+ .log_item = xfs_extent_free_log_item,
+ .create_done = xfs_extent_free_create_done,
+ .finish_item = xfs_extent_free_finish_item,
+ .cancel_item = xfs_extent_free_cancel_item,
+};
+
+/* Register the deferred op type. */
+void
+xfs_extent_free_init_defer_op(void)
+{
+ xfs_defer_init_op_type(&xfs_extent_free_defer_type);
+}
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
new file mode 100644
index 000000000000..5a50ef881568
--- /dev/null
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2016 Oracle. All Rights Reserved.
+ *
+ * Author: Darrick J. Wong <darrick.wong@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.
+ *
+ * This program is distributed in the hope that it would 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 the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_trans.h"
+#include "xfs_trans_priv.h"
+#include "xfs_rmap_item.h"
+#include "xfs_alloc.h"
+#include "xfs_rmap.h"
+
+/* Set the map extent flags for this reverse mapping. */
+static void
+xfs_trans_set_rmap_flags(
+ struct xfs_map_extent *rmap,
+ enum xfs_rmap_intent_type type,
+ int whichfork,
+ xfs_exntst_t state)
+{
+ rmap->me_flags = 0;
+ if (state == XFS_EXT_UNWRITTEN)
+ rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
+ if (whichfork == XFS_ATTR_FORK)
+ rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
+ switch (type) {
+ case XFS_RMAP_MAP:
+ rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
+ break;
+ case XFS_RMAP_UNMAP:
+ rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP;
+ break;
+ case XFS_RMAP_CONVERT:
+ rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT;
+ break;
+ case XFS_RMAP_ALLOC:
+ rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC;
+ break;
+ case XFS_RMAP_FREE:
+ rmap->me_flags |= XFS_RMAP_EXTENT_FREE;
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+struct xfs_rud_log_item *
+xfs_trans_get_rud(
+ struct xfs_trans *tp,
+ struct xfs_rui_log_item *ruip)
+{
+ struct xfs_rud_log_item *rudp;
+
+ rudp = xfs_rud_init(tp->t_mountp, ruip);
+ xfs_trans_add_item(tp, &rudp->rud_item);
+ return rudp;
+}
+
+/*
+ * Finish an rmap update and log it to the RUD. Note that the transaction is
+ * marked dirty regardless of whether the rmap update succeeds or fails to
+ * support the RUI/RUD lifecycle rules.
+ */
+int
+xfs_trans_log_finish_rmap_update(
+ struct xfs_trans *tp,
+ struct xfs_rud_log_item *rudp,
+ enum xfs_rmap_intent_type type,
+ __uint64_t owner,
+ int whichfork,
+ xfs_fileoff_t startoff,
+ xfs_fsblock_t startblock,
+ xfs_filblks_t blockcount,
+ xfs_exntst_t state,
+ struct xfs_btree_cur **pcur)
+{
+ int error;
+
+ error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
+ startblock, blockcount, state, pcur);
+
+ /*
+ * Mark the transaction dirty, even on error. This ensures the
+ * transaction is aborted, which:
+ *
+ * 1.) releases the RUI and frees the RUD
+ * 2.) shuts down the filesystem
+ */
+ tp->t_flags |= XFS_TRANS_DIRTY;
+ rudp->rud_item.li_desc->lid_flags |= XFS_LID_DIRTY;
+
+ return error;
+}
+
+/* Sort rmap intents by AG. */
+static int
+xfs_rmap_update_diff_items(
+ void *priv,
+ struct list_head *a,
+ struct list_head *b)
+{
+ struct xfs_mount *mp = priv;
+ struct xfs_rmap_intent *ra;
+ struct xfs_rmap_intent *rb;
+
+ ra = container_of(a, struct xfs_rmap_intent, ri_list);
+ rb = container_of(b, struct xfs_rmap_intent, ri_list);
+ return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) -
+ XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock);
+}
+
+/* Get an RUI. */
+STATIC void *
+xfs_rmap_update_create_intent(
+ struct xfs_trans *tp,
+ unsigned int count)
+{
+ struct xfs_rui_log_item *ruip;
+
+ ASSERT(tp != NULL);
+ ASSERT(count > 0);
+
+ ruip = xfs_rui_init(tp->t_mountp, count);
+ ASSERT(ruip != NULL);
+
+ /*
+ * Get a log_item_desc to point at the new item.
+ */
+ xfs_trans_add_item(tp, &ruip->rui_item);
+ return ruip;
+}
+
+/* Log rmap updates in the intent item. */
+STATIC void
+xfs_rmap_update_log_item(
+ struct xfs_trans *tp,
+ void *intent,
+ struct list_head *item)
+{
+ struct xfs_rui_log_item *ruip = intent;
+ struct xfs_rmap_intent *rmap;
+ uint next_extent;
+ struct xfs_map_extent *map;
+
+ rmap = container_of(item, struct xfs_rmap_intent, ri_list);
+
+ tp->t_flags |= XFS_TRANS_DIRTY;
+ ruip->rui_item.li_desc->lid_flags |= XFS_LID_DIRTY;
+
+ /*
+ * atomic_inc_return gives us the value after the increment;
+ * we want to use it as an array index so we need to subtract 1 from
+ * it.
+ */
+ next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
+ ASSERT(next_extent < ruip->rui_format.rui_nextents);
+ map = &ruip->rui_format.rui_extents[next_extent];
+ map->me_owner = rmap->ri_owner;
+ map->me_startblock = rmap->ri_bmap.br_startblock;
+ map->me_startoff = rmap->ri_bmap.br_startoff;
+ map->me_len = rmap->ri_bmap.br_blockcount;
+ xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
+ rmap->ri_bmap.br_state);
+}
+
+/* Get an RUD so we can process all the deferred rmap updates. */
+STATIC void *
+xfs_rmap_update_create_done(
+ struct xfs_trans *tp,
+ void *intent,
+ unsigned int count)
+{
+ return xfs_trans_get_rud(tp, intent);
+}
+
+/* Process a deferred rmap update. */
+STATIC int
+xfs_rmap_update_finish_item(
+ struct xfs_trans *tp,
+ struct xfs_defer_ops *dop,
+ struct list_head *item,
+ void *done_item,
+ void **state)
+{
+ struct xfs_rmap_intent *rmap;
+ int error;
+
+ rmap = container_of(item, struct xfs_rmap_intent, ri_list);
+ error = xfs_trans_log_finish_rmap_update(tp, done_item,
+ rmap->ri_type,
+ rmap->ri_owner, rmap->ri_whichfork,
+ rmap->ri_bmap.br_startoff,
+ rmap->ri_bmap.br_startblock,
+ rmap->ri_bmap.br_blockcount,
+ rmap->ri_bmap.br_state,
+ (struct xfs_btree_cur **)state);
+ kmem_free(rmap);
+ return error;
+}
+
+/* Clean up after processing deferred rmaps. */
+STATIC void
+xfs_rmap_update_finish_cleanup(
+ struct xfs_trans *tp,
+ void *state,
+ int error)
+{
+ struct xfs_btree_cur *rcur = state;
+
+ xfs_rmap_finish_one_cleanup(tp, rcur, error);
+}
+
+/* Abort all pending RUIs. */
+STATIC void
+xfs_rmap_update_abort_intent(
+ void *intent)
+{
+ xfs_rui_release(intent);
+}
+
+/* Cancel a deferred rmap update. */
+STATIC void
+xfs_rmap_update_cancel_item(
+ struct list_head *item)
+{
+ struct xfs_rmap_intent *rmap;
+
+ rmap = container_of(item, struct xfs_rmap_intent, ri_list);
+ kmem_free(rmap);
+}
+
+static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
+ .type = XFS_DEFER_OPS_TYPE_RMAP,
+ .max_items = XFS_RUI_MAX_FAST_EXTENTS,
+ .diff_items = xfs_rmap_update_diff_items,
+ .create_intent = xfs_rmap_update_create_intent,
+ .abort_intent = xfs_rmap_update_abort_intent,
+ .log_item = xfs_rmap_update_log_item,
+ .create_done = xfs_rmap_update_create_done,
+ .finish_item = xfs_rmap_update_finish_item,
+ .finish_cleanup = xfs_rmap_update_finish_cleanup,
+ .cancel_item = xfs_rmap_update_cancel_item,
+};
+
+/* Register the deferred op type. */
+void
+xfs_rmap_update_init_defer_op(void)
+{
+ xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
+}
diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
index 54a8e65e18b6..7d026bf27713 100644
--- a/include/asm-generic/qrwlock.h
+++ b/include/asm-generic/qrwlock.h
@@ -25,7 +25,20 @@
#include <asm-generic/qrwlock_types.h>
/*
- * Writer states & reader shift and bias
+ * Writer states & reader shift and bias.
+ *
+ * | +0 | +1 | +2 | +3 |
+ * ----+----+----+----+----+
+ * LE | 78 | 56 | 34 | 12 | 0x12345678
+ * ----+----+----+----+----+
+ * | wr | rd |
+ * +----+----+----+----+
+ *
+ * ----+----+----+----+----+
+ * BE | 12 | 34 | 56 | 78 | 0x12345678
+ * ----+----+----+----+----+
+ * | rd | wr |
+ * +----+----+----+----+
*/
#define _QW_WAITING 1 /* A writer is waiting */
#define _QW_LOCKED 0xff /* A writer holds the lock */
@@ -134,12 +147,22 @@ static inline void queued_read_unlock(struct qrwlock *lock)
}
/**
+ * __qrwlock_write_byte - retrieve the write byte address of a queue rwlock
+ * @lock : Pointer to queue rwlock structure
+ * Return: the write byte address of a queue rwlock
+ */
+static inline u8 *__qrwlock_write_byte(struct qrwlock *lock)
+{
+ return (u8 *)lock + 3 * IS_BUILTIN(CONFIG_CPU_BIG_ENDIAN);
+}
+
+/**
* queued_write_unlock - release write lock of a queue rwlock
* @lock : Pointer to queue rwlock structure
*/
static inline void queued_write_unlock(struct qrwlock *lock)
{
- smp_store_release((u8 *)&lock->cnts, 0);
+ smp_store_release(__qrwlock_write_byte(lock), 0);
}
/*
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3edeaf88ebc0..44e070800b6d 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -308,6 +308,7 @@ struct drm_plane_helper_funcs;
* @mode_changed: crtc_state->mode or crtc_state->enable has been changed
* @active_changed: crtc_state->active has been toggled.
* @connectors_changed: connectors to this crtc have been updated
+ * @zpos_changed: zpos values of planes on this crtc have been updated
* @color_mgmt_changed: color management properties have changed (degamma or
* gamma LUT or CSC matrix)
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
@@ -344,6 +345,7 @@ struct drm_crtc_state {
bool mode_changed : 1;
bool active_changed : 1;
bool connectors_changed : 1;
+ bool zpos_changed : 1;
bool color_mgmt_changed : 1;
/* attached planes bitmask:
@@ -1409,6 +1411,9 @@ struct drm_connector {
* @src_w: width of visible portion of plane (in 16.16)
* @src_h: height of visible portion of plane (in 16.16)
* @rotation: rotation of the plane
+ * @zpos: priority of the given plane on crtc (optional)
+ * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1
+ * where N is the number of active planes for given crtc
* @state: backpointer to global drm_atomic_state
*/
struct drm_plane_state {
@@ -1429,6 +1434,10 @@ struct drm_plane_state {
/* Plane rotation */
unsigned int rotation;
+ /* Plane zpos */
+ unsigned int zpos;
+ unsigned int normalized_zpos;
+
struct drm_atomic_state *state;
};
@@ -1688,6 +1697,7 @@ enum drm_plane_type {
* @properties: property tracking for this plane
* @type: type of plane (overlay, primary, cursor)
* @state: current atomic state for this plane
+ * @zpos_property: zpos property for this plane
* @helper_private: mid-layer private data
*/
struct drm_plane {
@@ -1732,6 +1742,8 @@ struct drm_plane {
const struct drm_plane_helper_funcs *helper_private;
struct drm_plane_state *state;
+
+ struct drm_property *zpos_property;
};
/**
@@ -2958,6 +2970,14 @@ extern void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
uint degamma_lut_size,
bool has_ctm,
uint gamma_lut_size);
+
+int drm_plane_create_zpos_property(struct drm_plane *plane,
+ unsigned int zpos,
+ unsigned int min, unsigned int max);
+
+int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
+ unsigned int zpos);
+
/* Helpers */
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type);
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 4348d6d5877a..99c6d01d24f2 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -962,6 +962,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev,
*
* @bo: A pointer to a struct ttm_buffer_object.
* @evict: 1: This is an eviction. Don't try to pipeline.
+ * @interruptible: Sleep interruptible if waiting.
* @no_wait_gpu: Return immediately if the GPU is busy.
* @new_mem: struct ttm_mem_reg indicating where to move.
*
@@ -976,7 +977,7 @@ void ttm_mem_io_free(struct ttm_bo_device *bdev,
*/
extern int ttm_bo_move_ttm(struct ttm_buffer_object *bo,
- bool evict, bool no_wait_gpu,
+ bool evict, bool interruptible, bool no_wait_gpu,
struct ttm_mem_reg *new_mem);
/**
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 540da5149ba7..19b698ef3336 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -34,6 +34,7 @@
#define VGIC_MAX_SPI 1019
#define VGIC_MAX_RESERVED 1023
#define VGIC_MIN_LPI 8192
+#define KVM_IRQCHIP_NUM_PINS (1020 - 32)
enum vgic_type {
VGIC_V2, /* Good ol' GICv2 */
@@ -314,4 +315,10 @@ static inline int kvm_vgic_get_max_vcpus(void)
int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
+/**
+ * kvm_vgic_setup_default_irq_routing:
+ * Setup a default flat gsi routing table mapping all SPIs
+ */
+int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
+
#endif /* __KVM_ARM_VGIC_H */
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 3f103076d0bf..c357f27d5483 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -163,6 +163,7 @@ struct backing_dev_info {
wait_queue_head_t wb_waitq;
struct device *dev;
+ struct device *owner;
struct timer_list laptop_mode_wb_timer;
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 491a91717788..43b93a947e61 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -24,6 +24,7 @@ __printf(3, 4)
int bdi_register(struct backing_dev_info *bdi, struct device *parent,
const char *fmt, ...);
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner);
void bdi_unregister(struct backing_dev_info *bdi);
int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 314b3caa701c..1303b570b18c 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -113,6 +113,8 @@ extern int suid_dumpable;
extern int setup_arg_pages(struct linux_binprm * bprm,
unsigned long stack_top,
int executable_stack);
+extern int transfer_args_to_stack(struct linux_binprm *bprm,
+ unsigned long *sp_location);
extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
extern int copy_strings_kernel(int argc, const char *const *argv,
struct linux_binprm *bprm);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 583c10810e32..59ffaa68b11b 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -95,7 +95,7 @@ static inline bool bio_is_rw(struct bio *bio)
static inline bool bio_mergeable(struct bio *bio)
{
- if (bio->bi_rw & REQ_NOMERGE_FLAGS)
+ if (bio->bi_opf & REQ_NOMERGE_FLAGS)
return false;
return true;
@@ -318,7 +318,7 @@ struct bio_integrity_payload {
static inline struct bio_integrity_payload *bio_integrity(struct bio *bio)
{
- if (bio->bi_rw & REQ_INTEGRITY)
+ if (bio->bi_opf & REQ_INTEGRITY)
return bio->bi_integrity;
return NULL;
@@ -470,11 +470,14 @@ extern unsigned int bvec_nr_vecs(unsigned short idx);
int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
int bio_associate_current(struct bio *bio);
void bio_disassociate_task(struct bio *bio);
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src);
#else /* CONFIG_BLK_CGROUP */
static inline int bio_associate_blkcg(struct bio *bio,
struct cgroup_subsys_state *blkcg_css) { return 0; }
static inline int bio_associate_current(struct bio *bio) { return -ENOENT; }
static inline void bio_disassociate_task(struct bio *bio) { }
+static inline void bio_clone_blkcg_association(struct bio *dst,
+ struct bio *src) { }
#endif /* CONFIG_BLK_CGROUP */
#ifdef CONFIG_HIGHMEM
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 27bfc0b631a9..598bc999f4c2 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -266,13 +266,12 @@ static inline int bitmap_equal(const unsigned long *src1,
const unsigned long *src2, unsigned int nbits)
{
if (small_const_nbits(nbits))
- return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
+ return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
#ifdef CONFIG_S390
- else if (__builtin_constant_p(nbits) && (nbits % BITS_PER_LONG) == 0)
+ if (__builtin_constant_p(nbits) && (nbits % BITS_PER_LONG) == 0)
return !memcmp(src1, src2, nbits / 8);
#endif
- else
- return __bitmap_equal(src1, src2, nbits);
+ return __bitmap_equal(src1, src2, nbits);
}
static inline int bitmap_intersects(const unsigned long *src1,
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h
index f77150a4a96a..10648e300c93 100644
--- a/include/linux/blk-cgroup.h
+++ b/include/linux/blk-cgroup.h
@@ -714,9 +714,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q,
if (!throtl) {
blkg = blkg ?: q->root_blkg;
- blkg_rwstat_add(&blkg->stat_bytes, bio_op(bio), bio->bi_rw,
+ blkg_rwstat_add(&blkg->stat_bytes, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
- blkg_rwstat_add(&blkg->stat_ios, bio_op(bio), bio->bi_rw, 1);
+ blkg_rwstat_add(&blkg->stat_ios, bio_op(bio), bio->bi_opf, 1);
}
rcu_read_unlock();
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index f254eb264924..436f43f87da9 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -27,8 +27,9 @@ struct bio {
struct bio *bi_next; /* request queue link */
struct block_device *bi_bdev;
int bi_error;
- unsigned int bi_rw; /* bottom bits req flags,
- * top bits REQ_OP
+ unsigned int bi_opf; /* bottom bits req flags,
+ * top bits REQ_OP. Use
+ * accessors.
*/
unsigned short bi_flags; /* status, command, etc */
unsigned short bi_ioprio;
@@ -89,13 +90,13 @@ struct bio {
};
#define BIO_OP_SHIFT (8 * sizeof(unsigned int) - REQ_OP_BITS)
-#define bio_op(bio) ((bio)->bi_rw >> BIO_OP_SHIFT)
+#define bio_op(bio) ((bio)->bi_opf >> BIO_OP_SHIFT)
#define bio_set_op_attrs(bio, op, op_flags) do { \
WARN_ON(op >= (1 << REQ_OP_BITS)); \
- (bio)->bi_rw &= ((1 << BIO_OP_SHIFT) - 1); \
- (bio)->bi_rw |= ((unsigned int) (op) << BIO_OP_SHIFT); \
- (bio)->bi_rw |= op_flags; \
+ (bio)->bi_opf &= ((1 << BIO_OP_SHIFT) - 1); \
+ (bio)->bi_opf |= ((unsigned int) (op) << BIO_OP_SHIFT); \
+ (bio)->bi_opf |= op_flags; \
} while (0)
#define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs)
@@ -138,7 +139,7 @@ struct bio {
/*
* Request flags. For use in the cmd_flags field of struct request, and in
- * bi_rw of struct bio. Note that some flags are only valid in either one.
+ * bi_opf of struct bio. Note that some flags are only valid in either one.
*/
enum rq_flag_bits {
/* common flags */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index adf33079771e..2c210b6a7bcf 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -47,7 +47,6 @@ struct pr_ops;
*/
#define BLKCG_MAX_POLS 2
-struct request;
typedef void (rq_end_io_fn)(struct request *, int);
#define BLK_RL_SYNCFULL (1U << 0)
@@ -1673,7 +1672,7 @@ struct blk_dax_ctl {
struct block_device_operations {
int (*open) (struct block_device *, fmode_t);
void (*release) (struct gendisk *, fmode_t);
- int (*rw_page)(struct block_device *, sector_t, struct page *, int rw);
+ int (*rw_page)(struct block_device *, sector_t, struct page *, bool);
int (*ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
int (*compat_ioctl) (struct block_device *, fmode_t, unsigned, unsigned long);
long (*direct_access)(struct block_device *, sector_t, void **, pfn_t *,
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index 701b64a3b7c5..89b65b82d98f 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -74,7 +74,8 @@ static inline void bvec_iter_advance(const struct bio_vec *bv,
"Attempted to advance past end of bvec iter\n");
while (bytes) {
- unsigned len = min(bytes, bvec_iter_len(bv, *iter));
+ unsigned iter_len = bvec_iter_len(bv, *iter);
+ unsigned len = min(bytes, iter_len);
bytes -= len;
iter->bi_size -= len;
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 98044a8d1487..5ff3e9a4fe5f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -130,7 +130,7 @@ struct dentry_operations {
int (*d_revalidate)(struct dentry *, unsigned int);
int (*d_weak_revalidate)(struct dentry *, unsigned int);
int (*d_hash)(const struct dentry *, struct qstr *);
- int (*d_compare)(const struct dentry *, const struct dentry *,
+ int (*d_compare)(const struct dentry *,
unsigned int, const char *, const struct qstr *);
int (*d_delete)(const struct dentry *);
int (*d_init)(struct dentry *);
@@ -263,7 +263,7 @@ extern void d_rehash(struct dentry *);
extern void d_add(struct dentry *, struct inode *);
-extern void dentry_update_name_case(struct dentry *, struct qstr *);
+extern void dentry_update_name_case(struct dentry *, const struct qstr *);
/* used for rename() and baskets */
extern void d_move(struct dentry *, struct dentry *);
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
deleted file mode 100644
index 5246239a4953..000000000000
--- a/include/linux/dma-attrs.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef _DMA_ATTR_H
-#define _DMA_ATTR_H
-
-#include <linux/bitmap.h>
-#include <linux/bitops.h>
-#include <linux/bug.h>
-
-/**
- * an enum dma_attr represents an attribute associated with a DMA
- * mapping. The semantics of each attribute should be defined in
- * Documentation/DMA-attributes.txt.
- */
-enum dma_attr {
- DMA_ATTR_WRITE_BARRIER,
- DMA_ATTR_WEAK_ORDERING,
- DMA_ATTR_WRITE_COMBINE,
- DMA_ATTR_NON_CONSISTENT,
- DMA_ATTR_NO_KERNEL_MAPPING,
- DMA_ATTR_SKIP_CPU_SYNC,
- DMA_ATTR_FORCE_CONTIGUOUS,
- DMA_ATTR_ALLOC_SINGLE_PAGES,
- DMA_ATTR_MAX,
-};
-
-#define __DMA_ATTRS_LONGS BITS_TO_LONGS(DMA_ATTR_MAX)
-
-/**
- * struct dma_attrs - an opaque container for DMA attributes
- * @flags - bitmask representing a collection of enum dma_attr
- */
-struct dma_attrs {
- unsigned long flags[__DMA_ATTRS_LONGS];
-};
-
-#define DEFINE_DMA_ATTRS(x) \
- struct dma_attrs x = { \
- .flags = { [0 ... __DMA_ATTRS_LONGS-1] = 0 }, \
- }
-
-static inline void init_dma_attrs(struct dma_attrs *attrs)
-{
- bitmap_zero(attrs->flags, __DMA_ATTRS_LONGS);
-}
-
-/**
- * dma_set_attr - set a specific attribute
- * @attr: attribute to set
- * @attrs: struct dma_attrs (may be NULL)
- */
-static inline void dma_set_attr(enum dma_attr attr, struct dma_attrs *attrs)
-{
- if (attrs == NULL)
- return;
- BUG_ON(attr >= DMA_ATTR_MAX);
- __set_bit(attr, attrs->flags);
-}
-
-/**
- * dma_get_attr - check for a specific attribute
- * @attr: attribute to set
- * @attrs: struct dma_attrs (may be NULL)
- */
-static inline int dma_get_attr(enum dma_attr attr, struct dma_attrs *attrs)
-{
- if (attrs == NULL)
- return 0;
- BUG_ON(attr >= DMA_ATTR_MAX);
- return test_bit(attr, attrs->flags);
-}
-
-#endif /* _DMA_ATTR_H */
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 8443bbb5c071..81c5c8d167ad 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -39,7 +39,7 @@ int dma_direction_to_prot(enum dma_data_direction dir, bool coherent);
* the arch code to take care of attributes and cache maintenance
*/
struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
- struct dma_attrs *attrs, int prot, dma_addr_t *handle,
+ unsigned long attrs, int prot, dma_addr_t *handle,
void (*flush_page)(struct device *, const void *, phys_addr_t));
void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
dma_addr_t *handle);
@@ -56,9 +56,9 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
* directly as DMA mapping callbacks for simplicity
*/
void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
- enum dma_data_direction dir, struct dma_attrs *attrs);
+ enum dma_data_direction dir, unsigned long attrs);
void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs);
+ enum dma_data_direction dir, unsigned long attrs);
int iommu_dma_supported(struct device *dev, u64 mask);
int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 71c1b215ef66..66533e18276c 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -5,13 +5,58 @@
#include <linux/string.h>
#include <linux/device.h>
#include <linux/err.h>
-#include <linux/dma-attrs.h>
#include <linux/dma-debug.h>
#include <linux/dma-direction.h>
#include <linux/scatterlist.h>
#include <linux/kmemcheck.h>
#include <linux/bug.h>
+/**
+ * List of possible attributes associated with a DMA mapping. The semantics
+ * of each attribute should be defined in Documentation/DMA-attributes.txt.
+ *
+ * DMA_ATTR_WRITE_BARRIER: DMA to a memory region with this attribute
+ * forces all pending DMA writes to complete.
+ */
+#define DMA_ATTR_WRITE_BARRIER (1UL << 0)
+/*
+ * DMA_ATTR_WEAK_ORDERING: Specifies that reads and writes to the mapping
+ * may be weakly ordered, that is that reads and writes may pass each other.
+ */
+#define DMA_ATTR_WEAK_ORDERING (1UL << 1)
+/*
+ * DMA_ATTR_WRITE_COMBINE: Specifies that writes to the mapping may be
+ * buffered to improve performance.
+ */
+#define DMA_ATTR_WRITE_COMBINE (1UL << 2)
+/*
+ * DMA_ATTR_NON_CONSISTENT: Lets the platform to choose to return either
+ * consistent or non-consistent memory as it sees fit.
+ */
+#define DMA_ATTR_NON_CONSISTENT (1UL << 3)
+/*
+ * DMA_ATTR_NO_KERNEL_MAPPING: Lets the platform to avoid creating a kernel
+ * virtual mapping for the allocated buffer.
+ */
+#define DMA_ATTR_NO_KERNEL_MAPPING (1UL << 4)
+/*
+ * DMA_ATTR_SKIP_CPU_SYNC: Allows platform code to skip synchronization of
+ * the CPU cache for the given buffer assuming that it has been already
+ * transferred to 'device' domain.
+ */
+#define DMA_ATTR_SKIP_CPU_SYNC (1UL << 5)
+/*
+ * DMA_ATTR_FORCE_CONTIGUOUS: Forces contiguous allocation of the buffer
+ * in physical memory.
+ */
+#define DMA_ATTR_FORCE_CONTIGUOUS (1UL << 6)
+/*
+ * DMA_ATTR_ALLOC_SINGLE_PAGES: This is a hint to the DMA-mapping subsystem
+ * that it's probably not worth the time to try to allocate memory to in a way
+ * that gives better TLB efficiency.
+ */
+#define DMA_ATTR_ALLOC_SINGLE_PAGES (1UL << 7)
+
/*
* A dma_addr_t can hold any valid DMA or bus address for the platform.
* It can be given to a device to use as a DMA source or target. A CPU cannot
@@ -21,34 +66,35 @@
struct dma_map_ops {
void* (*alloc)(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs);
+ unsigned long attrs);
void (*free)(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs);
+ unsigned long attrs);
int (*mmap)(struct device *, struct vm_area_struct *,
- void *, dma_addr_t, size_t, struct dma_attrs *attrs);
+ void *, dma_addr_t, size_t,
+ unsigned long attrs);
int (*get_sgtable)(struct device *dev, struct sg_table *sgt, void *,
- dma_addr_t, size_t, struct dma_attrs *attrs);
+ dma_addr_t, size_t, unsigned long attrs);
dma_addr_t (*map_page)(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
/*
* map_sg returns 0 on error and a value > 0 on success.
* It should never return a value < 0.
*/
int (*map_sg)(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
void (*unmap_sg)(struct device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
@@ -123,7 +169,7 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev)
static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
dma_addr_t addr;
@@ -142,7 +188,7 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -158,7 +204,7 @@ static inline void dma_unmap_single_attrs(struct device *dev, dma_addr_t addr,
*/
static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
int i, ents;
@@ -176,7 +222,7 @@ static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
static inline void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -195,7 +241,7 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
kmemcheck_mark_initialized(page_address(page) + offset, size);
BUG_ON(!valid_dma_direction(dir));
- addr = ops->map_page(dev, page, offset, size, dir, NULL);
+ addr = ops->map_page(dev, page, offset, size, dir, 0);
debug_dma_map_page(dev, page, offset, size, dir, addr, false);
return addr;
@@ -208,7 +254,7 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
BUG_ON(!valid_dma_direction(dir));
if (ops->unmap_page)
- ops->unmap_page(dev, addr, size, dir, NULL);
+ ops->unmap_page(dev, addr, size, dir, 0);
debug_dma_unmap_page(dev, addr, size, dir, false);
}
@@ -289,10 +335,10 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
}
-#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
-#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
-#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
-#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
+#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
+#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size);
@@ -321,7 +367,7 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags);
*/
static inline int
dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
- dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, size_t size, unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!ops);
@@ -330,7 +376,7 @@ dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma, void *cpu_addr,
return dma_common_mmap(dev, vma, cpu_addr, dma_addr, size);
}
-#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
int
dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
@@ -338,7 +384,8 @@ dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
static inline int
dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
- dma_addr_t dma_addr, size_t size, struct dma_attrs *attrs)
+ dma_addr_t dma_addr, size_t size,
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!ops);
@@ -348,7 +395,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
return dma_common_get_sgtable(dev, sgt, cpu_addr, dma_addr, size);
}
-#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, NULL)
+#define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
#ifndef arch_dma_alloc_attrs
#define arch_dma_alloc_attrs(dev, flag) (true)
@@ -356,7 +403,7 @@ dma_get_sgtable_attrs(struct device *dev, struct sg_table *sgt, void *cpu_addr,
static inline void *dma_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
void *cpu_addr;
@@ -378,7 +425,7 @@ static inline void *dma_alloc_attrs(struct device *dev, size_t size,
static inline void dma_free_attrs(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -398,31 +445,27 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- return dma_alloc_attrs(dev, size, dma_handle, flag, NULL);
+ return dma_alloc_attrs(dev, size, dma_handle, flag, 0);
}
static inline void dma_free_coherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
- return dma_free_attrs(dev, size, cpu_addr, dma_handle, NULL);
+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, 0);
}
static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp)
{
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
- return dma_alloc_attrs(dev, size, dma_handle, gfp, &attrs);
+ return dma_alloc_attrs(dev, size, dma_handle, gfp,
+ DMA_ATTR_NON_CONSISTENT);
}
static inline void dma_free_noncoherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
- DEFINE_DMA_ATTRS(attrs);
-
- dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
- dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+ dma_free_attrs(dev, size, cpu_addr, dma_handle,
+ DMA_ATTR_NON_CONSISTENT);
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
@@ -646,9 +689,8 @@ static inline void dmam_release_declared_memory(struct device *dev)
static inline void *dma_alloc_wc(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t gfp)
{
- DEFINE_DMA_ATTRS(attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- return dma_alloc_attrs(dev, size, dma_addr, gfp, &attrs);
+ return dma_alloc_attrs(dev, size, dma_addr, gfp,
+ DMA_ATTR_WRITE_COMBINE);
}
#ifndef dma_alloc_writecombine
#define dma_alloc_writecombine dma_alloc_wc
@@ -657,9 +699,8 @@ static inline void *dma_alloc_wc(struct device *dev, size_t size,
static inline void dma_free_wc(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_addr)
{
- DEFINE_DMA_ATTRS(attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- return dma_free_attrs(dev, size, cpu_addr, dma_addr, &attrs);
+ return dma_free_attrs(dev, size, cpu_addr, dma_addr,
+ DMA_ATTR_WRITE_COMBINE);
}
#ifndef dma_free_writecombine
#define dma_free_writecombine dma_free_wc
@@ -670,9 +711,8 @@ static inline int dma_mmap_wc(struct device *dev,
void *cpu_addr, dma_addr_t dma_addr,
size_t size)
{
- DEFINE_DMA_ATTRS(attrs);
- dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
- return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size,
+ DMA_ATTR_WRITE_COMBINE);
}
#ifndef dma_mmap_writecombine
#define dma_mmap_writecombine dma_mmap_wc
diff --git a/include/linux/ds17287rtc.h b/include/linux/ds17287rtc.h
deleted file mode 100644
index d85d3f497b96..000000000000
--- a/include/linux/ds17287rtc.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * ds17287rtc.h - register definitions for the ds1728[57] RTC / CMOS RAM
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * (C) 2003 Guido Guenther <agx@sigxcpu.org>
- */
-#ifndef __LINUX_DS17287RTC_H
-#define __LINUX_DS17287RTC_H
-
-#include <linux/rtc.h> /* get the user-level API */
-#include <linux/mc146818rtc.h>
-
-/* Register A */
-#define DS_REGA_DV2 0x40 /* countdown chain */
-#define DS_REGA_DV1 0x20 /* oscillator enable */
-#define DS_REGA_DV0 0x10 /* bank select */
-
-/* bank 1 registers */
-#define DS_B1_MODEL 0x40 /* model number byte */
-#define DS_B1_SN1 0x41 /* serial number byte 1 */
-#define DS_B1_SN2 0x42 /* serial number byte 2 */
-#define DS_B1_SN3 0x43 /* serial number byte 3 */
-#define DS_B1_SN4 0x44 /* serial number byte 4 */
-#define DS_B1_SN5 0x45 /* serial number byte 5 */
-#define DS_B1_SN6 0x46 /* serial number byte 6 */
-#define DS_B1_CRC 0x47 /* CRC byte */
-#define DS_B1_CENTURY 0x48 /* Century byte */
-#define DS_B1_DALARM 0x49 /* date alarm */
-#define DS_B1_XCTRL4A 0x4a /* extendec control register 4a */
-#define DS_B1_XCTRL4B 0x4b /* extendec control register 4b */
-#define DS_B1_RTCADDR2 0x4e /* rtc address 2 */
-#define DS_B1_RTCADDR3 0x4f /* rtc address 3 */
-#define DS_B1_RAMLSB 0x50 /* extended ram LSB */
-#define DS_B1_RAMMSB 0x51 /* extended ram MSB */
-#define DS_B1_RAMDPORT 0x53 /* extended ram data port */
-
-/* register details */
-/* extended control register 4a */
-#define DS_XCTRL4A_VRT2 0x80 /* valid ram and time */
-#define DS_XCTRL4A_INCR 0x40 /* increment progress status */
-#define DS_XCTRL4A_BME 0x20 /* burst mode enable */
-#define DS_XCTRL4A_PAB 0x08 /* power active bar ctrl */
-#define DS_XCTRL4A_RF 0x04 /* ram clear flag */
-#define DS_XCTRL4A_WF 0x02 /* wake up alarm flag */
-#define DS_XCTRL4A_KF 0x01 /* kickstart flag */
-
-/* interrupt causes */
-#define DS_XCTRL4A_IFS (DS_XCTRL4A_RF|DS_XCTRL4A_WF|DS_XCTRL4A_KF)
-
-/* extended control register 4b */
-#define DS_XCTRL4B_ABE 0x80 /* auxiliary battery enable */
-#define DS_XCTRL4B_E32K 0x40 /* enable 32.768 kHz Output */
-#define DS_XCTRL4B_CS 0x20 /* crystal select */
-#define DS_XCTRL4B_RCE 0x10 /* ram clear enable */
-#define DS_XCTRL4B_PRS 0x08 /* PAB resec select */
-#define DS_XCTRL4B_RIE 0x04 /* ram clear interrupt enable */
-#define DS_XCTRL4B_WFE 0x02 /* wake up alarm interrupt enable */
-#define DS_XCTRL4B_KFE 0x01 /* kickstart interrupt enable */
-
-/* interrupt enable bits */
-#define DS_XCTRL4B_IFES (DS_XCTRL4B_RIE|DS_XCTRL4B_WFE|DS_XCTRL4B_KFE)
-
-#endif /* __LINUX_DS17287RTC_H */
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 4f1bbc68cd1b..546d68057e3b 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -1,6 +1,10 @@
#ifndef _DYNAMIC_DEBUG_H
#define _DYNAMIC_DEBUG_H
+#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
+#include <linux/jump_label.h>
+#endif
+
/*
* An instance of this structure is created in a special
* ELF section at every dynamic debug callsite. At runtime,
@@ -33,6 +37,12 @@ struct _ddebug {
#define _DPRINTK_FLAGS_DEFAULT 0
#endif
unsigned int flags:8;
+#ifdef HAVE_JUMP_LABEL
+ union {
+ struct static_key_true dd_key_true;
+ struct static_key_false dd_key_false;
+ } key;
+#endif
} __attribute__((aligned(8)));
@@ -60,7 +70,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
const struct net_device *dev,
const char *fmt, ...);
-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
+#define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init) \
static struct _ddebug __aligned(8) \
__attribute__((section("__verbose"))) name = { \
.modname = KBUILD_MODNAME, \
@@ -68,13 +78,51 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
.filename = __FILE__, \
.format = (fmt), \
.lineno = __LINE__, \
- .flags = _DPRINTK_FLAGS_DEFAULT, \
+ .flags = _DPRINTK_FLAGS_DEFAULT, \
+ dd_key_init(key, init) \
}
+#ifdef HAVE_JUMP_LABEL
+
+#define dd_key_init(key, init) key = (init)
+
+#ifdef DEBUG
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
+ DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
+ (STATIC_KEY_TRUE_INIT))
+
+#define DYNAMIC_DEBUG_BRANCH(descriptor) \
+ static_branch_likely(&descriptor.key.dd_key_true)
+#else
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
+ DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \
+ (STATIC_KEY_FALSE_INIT))
+
+#define DYNAMIC_DEBUG_BRANCH(descriptor) \
+ static_branch_unlikely(&descriptor.key.dd_key_false)
+#endif
+
+#else
+
+#define dd_key_init(key, init)
+
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
+ DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0)
+
+#ifdef DEBUG
+#define DYNAMIC_DEBUG_BRANCH(descriptor) \
+ likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+#else
+#define DYNAMIC_DEBUG_BRANCH(descriptor) \
+ unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
+#endif
+
+#endif
+
#define dynamic_pr_debug(fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
- if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
__dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
##__VA_ARGS__); \
} while (0)
@@ -82,7 +130,7 @@ do { \
#define dynamic_dev_dbg(dev, fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
- if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
__dynamic_dev_dbg(&descriptor, dev, fmt, \
##__VA_ARGS__); \
} while (0)
@@ -90,7 +138,7 @@ do { \
#define dynamic_netdev_dbg(dev, fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
- if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
__dynamic_netdev_dbg(&descriptor, dev, fmt, \
##__VA_ARGS__); \
} while (0)
@@ -100,7 +148,7 @@ do { \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \
__builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
- if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
print_hex_dump(KERN_DEBUG, prefix_str, \
prefix_type, rowsize, groupsize, \
buf, len, ascii); \
diff --git a/include/linux/extable.h b/include/linux/extable.h
new file mode 100644
index 000000000000..7effea4b257d
--- /dev/null
+++ b/include/linux/extable.h
@@ -0,0 +1,32 @@
+#ifndef _LINUX_EXTABLE_H
+#define _LINUX_EXTABLE_H
+
+#include <linux/stddef.h> /* for NULL */
+
+struct module;
+struct exception_table_entry;
+
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value);
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish);
+void sort_main_extable(void);
+void trim_init_extable(struct module *m);
+
+/* Given an address, look for it in the exception tables */
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
+#ifdef CONFIG_MODULES
+/* For extable.c to search modules' exception tables. */
+const struct exception_table_entry *search_module_extables(unsigned long addr);
+#else
+static inline const struct exception_table_entry *
+search_module_extables(unsigned long addr)
+{
+ return NULL;
+}
+#endif /*CONFIG_MODULES*/
+
+#endif /* _LINUX_EXTABLE_H */
diff --git a/include/linux/fence.h b/include/linux/fence.h
index 523ea3fbbddd..8cc719a63728 100644
--- a/include/linux/fence.h
+++ b/include/linux/fence.h
@@ -358,7 +358,7 @@ u64 fence_context_alloc(unsigned num);
#define FENCE_TRACE(f, fmt, args...) \
do { \
struct fence *__ff = (f); \
- if (config_enabled(CONFIG_FENCE_TRACE)) \
+ if (IS_ENABLED(CONFIG_FENCE_TRACE)) \
pr_info("f %llu#%u: " fmt, \
__ff->context, __ff->seqno, ##args); \
} while (0)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f3f0b4c8e8ac..3523bf62f328 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2747,11 +2747,6 @@ extern struct inode *new_inode(struct super_block *sb);
extern void free_inode_nonrcu(struct inode *inode);
extern int should_remove_suid(struct dentry *);
extern int file_remove_privs(struct file *);
-extern int dentry_needs_remove_privs(struct dentry *dentry);
-static inline int file_needs_remove_privs(struct file *file)
-{
- return dentry_needs_remove_privs(file->f_path.dentry);
-}
extern void __insert_inode_hash(struct inode *, unsigned long hashval);
static inline void insert_inode_hash(struct inode *inode)
diff --git a/include/linux/i8042.h b/include/linux/i8042.h
index 0f9bafa17a02..d98780ca9604 100644
--- a/include/linux/i8042.h
+++ b/include/linux/i8042.h
@@ -62,7 +62,6 @@ struct serio;
void i8042_lock_chip(void);
void i8042_unlock_chip(void);
int i8042_command(unsigned char *param, int command);
-bool i8042_check_port_owner(const struct serio *);
int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio));
int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
@@ -83,11 +82,6 @@ static inline int i8042_command(unsigned char *param, int command)
return -ENODEV;
}
-static inline bool i8042_check_port_owner(const struct serio *serio)
-{
- return false;
-}
-
static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
struct serio *serio))
{
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 68904469fba1..661af564fae8 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -76,7 +76,6 @@
#include <linux/types.h>
#include <linux/compiler.h>
-#include <linux/bug.h>
extern bool static_key_initialized;
@@ -115,20 +114,8 @@ enum jump_label_type {
struct module;
-#include <linux/atomic.h>
-
#ifdef HAVE_JUMP_LABEL
-static inline int static_key_count(struct static_key *key)
-{
- /*
- * -1 means the first static_key_slow_inc() is in progress.
- * static_key_enabled() must return true, so return 1 here.
- */
- int n = atomic_read(&key->enabled);
- return n >= 0 ? n : 1;
-}
-
#define JUMP_TYPE_FALSE 0UL
#define JUMP_TYPE_TRUE 1UL
#define JUMP_TYPE_MASK 1UL
@@ -157,16 +144,29 @@ extern int jump_label_text_reserved(void *start, void *end);
extern void static_key_slow_inc(struct static_key *key);
extern void static_key_slow_dec(struct static_key *key);
extern void jump_label_apply_nops(struct module *mod);
+extern int static_key_count(struct static_key *key);
+extern void static_key_enable(struct static_key *key);
+extern void static_key_disable(struct static_key *key);
+/*
+ * We should be using ATOMIC_INIT() for initializing .enabled, but
+ * the inclusion of atomic.h is problematic for inclusion of jump_label.h
+ * in 'low-level' headers. Thus, we are initializing .enabled with a
+ * raw value, but have added a BUILD_BUG_ON() to catch any issues in
+ * jump_label_init() see: kernel/jump_label.c.
+ */
#define STATIC_KEY_INIT_TRUE \
- { .enabled = ATOMIC_INIT(1), \
+ { .enabled = { 1 }, \
.entries = (void *)JUMP_TYPE_TRUE }
#define STATIC_KEY_INIT_FALSE \
- { .enabled = ATOMIC_INIT(0), \
+ { .enabled = { 0 }, \
.entries = (void *)JUMP_TYPE_FALSE }
#else /* !HAVE_JUMP_LABEL */
+#include <linux/atomic.h>
+#include <linux/bug.h>
+
static inline int static_key_count(struct static_key *key)
{
return atomic_read(&key->enabled);
@@ -216,14 +216,6 @@ static inline int jump_label_apply_nops(struct module *mod)
return 0;
}
-#define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
-#define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
-
-#endif /* HAVE_JUMP_LABEL */
-
-#define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
-#define jump_label_enabled static_key_enabled
-
static inline void static_key_enable(struct static_key *key)
{
int count = static_key_count(key);
@@ -244,6 +236,14 @@ static inline void static_key_disable(struct static_key *key)
static_key_slow_dec(key);
}
+#define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
+#define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
+
+#endif /* HAVE_JUMP_LABEL */
+
+#define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
+#define jump_label_enabled static_key_enabled
+
/* -------------------------------------------------------------------------- */
/*
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index aafd702f3e21..9c28b4d4c90b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -317,7 +317,13 @@ struct kvm_kernel_irq_routing_entry {
unsigned irqchip;
unsigned pin;
} irqchip;
- struct msi_msg msi;
+ struct {
+ u32 address_lo;
+ u32 address_hi;
+ u32 data;
+ u32 flags;
+ u32 devid;
+ } msi;
struct kvm_s390_adapter_int adapter;
struct kvm_hv_sint hv_sint;
};
@@ -1003,12 +1009,12 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
#ifdef CONFIG_S390
#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
+#elif defined(CONFIG_ARM64)
+#define KVM_MAX_IRQ_ROUTES 4096
#else
#define KVM_MAX_IRQ_ROUTES 1024
#endif
-int kvm_setup_default_irq_routing(struct kvm *kvm);
-int kvm_setup_empty_irq_routing(struct kvm *kvm);
int kvm_set_irq_routing(struct kvm *kvm,
const struct kvm_irq_routing_entry *entries,
unsigned nr,
@@ -1107,9 +1113,21 @@ struct kvm_device {
/* create, destroy, and name are mandatory */
struct kvm_device_ops {
const char *name;
+
+ /*
+ * create is called holding kvm->lock and any operations not suitable
+ * to do while holding the lock should be deferred to init (see
+ * below).
+ */
int (*create)(struct kvm_device *dev, u32 type);
/*
+ * init is called after create if create is successful and is called
+ * outside of holding kvm->lock.
+ */
+ void (*init)(struct kvm_device *dev);
+
+ /*
* Destroy is responsible for freeing dev.
*
* Destroy may be called before or after destructors are called
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 7ae397669d8b..101bf19c0f41 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1356,7 +1356,7 @@ union security_list_options {
struct super_block *newsb);
int (*sb_parse_opts_str)(char *options, struct security_mnt_opts *opts);
int (*dentry_init_security)(struct dentry *dentry, int mode,
- struct qstr *name, void **ctx,
+ const struct qstr *name, void **ctx,
u32 *ctxlen);
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
index 433e0c74d643..a585b4b5fa0e 100644
--- a/include/linux/mc146818rtc.h
+++ b/include/linux/mc146818rtc.h
@@ -14,6 +14,8 @@
#include <asm/io.h>
#include <linux/rtc.h> /* get the user-level API */
#include <asm/mc146818rtc.h> /* register access macros */
+#include <linux/bcd.h>
+#include <linux/delay.h>
#ifdef __KERNEL__
#include <linux/spinlock.h> /* spinlock_t */
@@ -120,4 +122,7 @@ struct cmos_rtc_board_info {
#define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */
+unsigned int mc146818_get_time(struct rtc_time *time);
+int mc146818_set_time(struct rtc_time *time);
+
#endif /* _MC146818RTC_H */
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 64184d27e3cd..d641a18abacb 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -226,6 +226,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg);
/**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns success
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *msg);
+
+/**
* cros_ec_remove - Remove a ChromeOS EC
*
* Call this to deregister a ChromeOS EC, then clean up any private data.
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
index 13b630c10d4c..7e7a8d4b4551 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -949,6 +949,37 @@ struct ec_params_pwm_set_fan_duty {
uint32_t percent;
} __packed;
+#define EC_CMD_PWM_SET_DUTY 0x25
+/* 16 bit duty cycle, 0xffff = 100% */
+#define EC_PWM_MAX_DUTY 0xffff
+
+enum ec_pwm_type {
+ /* All types, indexed by board-specific enum pwm_channel */
+ EC_PWM_TYPE_GENERIC = 0,
+ /* Keyboard backlight */
+ EC_PWM_TYPE_KB_LIGHT,
+ /* Display backlight */
+ EC_PWM_TYPE_DISPLAY_LIGHT,
+ EC_PWM_TYPE_COUNT,
+};
+
+struct ec_params_pwm_set_duty {
+ uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */
+ uint8_t pwm_type; /* ec_pwm_type */
+ uint8_t index; /* Type-specific index, or 0 if unique */
+} __packed;
+
+#define EC_CMD_PWM_GET_DUTY 0x26
+
+struct ec_params_pwm_get_duty {
+ uint8_t pwm_type; /* ec_pwm_type */
+ uint8_t index; /* Type-specific index, or 0 if unique */
+} __packed;
+
+struct ec_response_pwm_get_duty {
+ uint16_t duty; /* Duty cycle, EC_PWM_MAX_DUTY = 100% */
+} __packed;
+
/*****************************************************************************/
/*
* Lightbar commands. This looks worse than it is. Since we only use one HOST
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index e6f6910278f3..42da3552f7cb 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -220,6 +220,7 @@ enum {
MLX4_DEV_CAP_FLAG2_LB_SRC_CHK = 1ULL << 32,
MLX4_DEV_CAP_FLAG2_ROCE_V1_V2 = 1ULL << 33,
MLX4_DEV_CAP_FLAG2_DMFS_UC_MC_SNIFFER = 1ULL << 34,
+ MLX4_DEV_CAP_FLAG2_DIAG_PER_PORT = 1ULL << 35,
};
enum {
@@ -1342,6 +1343,9 @@ enum {
VXLAN_STEER_BY_INNER_VLAN = 1 << 4,
};
+enum {
+ MLX4_OP_MOD_QUERY_TRANSPORT_CI_ERRORS = 0x2,
+};
int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, u32 qpn,
enum mlx4_net_trans_promisc_mode mode);
@@ -1382,6 +1386,9 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr);
int mlx4_SYNC_TPT(struct mlx4_dev *dev);
int mlx4_test_interrupts(struct mlx4_dev *dev);
+int mlx4_query_diag_counters(struct mlx4_dev *dev, u8 op_modifier,
+ const u32 offset[], u32 value[],
+ size_t array_len, u8 port);
u32 mlx4_get_eqs_per_port(struct mlx4_dev *dev, u8 port);
bool mlx4_is_eq_vector_valid(struct mlx4_dev *dev, u8 port, int vector);
struct cpu_rmap *mlx4_get_cpu_rmap(struct mlx4_dev *dev, int port);
diff --git a/include/linux/mlx5/cq.h b/include/linux/mlx5/cq.h
index 2be976dd4966..2566f6d6444f 100644
--- a/include/linux/mlx5/cq.h
+++ b/include/linux/mlx5/cq.h
@@ -58,6 +58,8 @@ struct mlx5_core_cq {
void (*comp)(struct mlx5_core_cq *);
void *priv;
} tasklet_ctx;
+ int reset_notify_added;
+ struct list_head reset_notify;
};
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index a041b99fceac..ccea6fb16482 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -46,6 +46,7 @@
#include <linux/mlx5/device.h>
#include <linux/mlx5/doorbell.h>
+#include <linux/mlx5/srq.h>
enum {
MLX5_RQ_BITMASK_VSD = 1 << 1,
@@ -798,11 +799,10 @@ struct mlx5_cmd_mailbox *mlx5_alloc_cmd_mailbox_chain(struct mlx5_core_dev *dev,
void mlx5_free_cmd_mailbox_chain(struct mlx5_core_dev *dev,
struct mlx5_cmd_mailbox *head);
int mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_create_srq_mbox_in *in, int inlen,
- int is_xrc);
+ struct mlx5_srq_attr *in);
int mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq);
int mlx5_core_query_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
- struct mlx5_query_srq_mbox_out *out);
+ struct mlx5_srq_attr *out);
int mlx5_core_arm_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
u16 lwm, int is_srq);
void mlx5_init_mkey_table(struct mlx5_core_dev *dev);
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index ab310819ac36..7879bf411891 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -556,9 +556,9 @@ struct mlx5_destroy_qp_mbox_out {
struct mlx5_modify_qp_mbox_in {
struct mlx5_inbox_hdr hdr;
__be32 qpn;
- u8 rsvd1[4];
- __be32 optparam;
u8 rsvd0[4];
+ __be32 optparam;
+ u8 rsvd1[4];
struct mlx5_qp_context ctx;
u8 rsvd2[16];
};
diff --git a/include/linux/mlx5/srq.h b/include/linux/mlx5/srq.h
index f43ed054a3e0..33c97dc900f8 100644
--- a/include/linux/mlx5/srq.h
+++ b/include/linux/mlx5/srq.h
@@ -35,6 +35,31 @@
#include <linux/mlx5/driver.h>
+enum {
+ MLX5_SRQ_FLAG_ERR = (1 << 0),
+ MLX5_SRQ_FLAG_WQ_SIG = (1 << 1),
+};
+
+struct mlx5_srq_attr {
+ u32 type;
+ u32 flags;
+ u32 log_size;
+ u32 wqe_shift;
+ u32 log_page_size;
+ u32 wqe_cnt;
+ u32 srqn;
+ u32 xrcd;
+ u32 page_offset;
+ u32 cqn;
+ u32 pd;
+ u32 lwm;
+ u32 user_index;
+ u64 db_record;
+ u64 *pas;
+};
+
+struct mlx5_core_dev;
+
void mlx5_init_srq_table(struct mlx5_core_dev *dev);
void mlx5_cleanup_srq_table(struct mlx5_core_dev *dev);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index f2e4e90621ec..d572b78b65e1 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -68,8 +68,10 @@ extern char * const migratetype_names[MIGRATE_TYPES];
#ifdef CONFIG_CMA
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
+# define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)
#else
# define is_migrate_cma(migratetype) false
+# define is_migrate_cma_page(_page) false
#endif
#define for_each_migratetype_order(order, type) \
diff --git a/include/linux/module.h b/include/linux/module.h
index 3daf2b3a09d2..0c3207d26ac0 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -18,6 +18,7 @@
#include <linux/moduleparam.h>
#include <linux/jump_label.h>
#include <linux/export.h>
+#include <linux/extable.h> /* only as arch move module.h -> extable.h */
#include <linux/rbtree_latch.h>
#include <linux/percpu.h>
@@ -37,6 +38,7 @@ struct modversion_info {
};
struct module;
+struct exception_table_entry;
struct module_kobject {
struct kobject kobj;
@@ -155,18 +157,6 @@ extern void cleanup_module(void);
#define __INITRODATA_OR_MODULE __INITRODATA
#endif /*CONFIG_MODULES*/
-/* Archs provide a method of finding the correct exception table. */
-struct exception_table_entry;
-
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value);
-void sort_extable(struct exception_table_entry *start,
- struct exception_table_entry *finish);
-void sort_main_extable(void);
-void trim_init_extable(struct module *m);
-
/* Generic info of form tag = "info" */
#define MODULE_INFO(tag, info) __MODULE_INFO(tag, tag, info)
@@ -268,9 +258,6 @@ extern const typeof(name) __mod_##type##__##name##_device_table \
* files require multiple MODULE_FIRMWARE() specifiers */
#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
-/* Given an address, look for it in the exception tables */
-const struct exception_table_entry *search_exception_tables(unsigned long add);
-
struct notifier_block;
#ifdef CONFIG_MODULES
@@ -311,6 +298,8 @@ struct module_layout {
unsigned int text_size;
/* Size of RO section of the module (text+rodata) */
unsigned int ro_size;
+ /* Size of RO after init section */
+ unsigned int ro_after_init_size;
#ifdef CONFIG_MODULES_TREE_LOOKUP
struct mod_tree_node mtn;
@@ -575,8 +564,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
struct module *, unsigned long),
void *data);
-extern void __module_put_and_exit(struct module *mod, long code)
- __attribute__((noreturn));
+extern void __noreturn __module_put_and_exit(struct module *mod,
+ long code);
#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code)
#ifdef CONFIG_MODULE_UNLOAD
@@ -630,9 +619,6 @@ const char *module_address_lookup(unsigned long addr,
int lookup_module_symbol_name(unsigned long addr, char *symname);
int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name);
-/* For extable.c to search modules' exception tables. */
-const struct exception_table_entry *search_module_extables(unsigned long addr);
-
int register_module_notifier(struct notifier_block *nb);
int unregister_module_notifier(struct notifier_block *nb);
@@ -657,13 +643,6 @@ static inline bool is_livepatch_module(struct module *mod)
#else /* !CONFIG_MODULES... */
-/* Given an address, look for it in the exception tables. */
-static inline const struct exception_table_entry *
-search_module_extables(unsigned long addr)
-{
- return NULL;
-}
-
static inline struct module *__module_address(unsigned long addr)
{
return NULL;
@@ -788,12 +767,12 @@ extern int module_sysfs_initialized;
#ifdef CONFIG_DEBUG_SET_MODULE_RONX
extern void set_all_modules_text_rw(void);
extern void set_all_modules_text_ro(void);
-extern void module_enable_ro(const struct module *mod);
+extern void module_enable_ro(const struct module *mod, bool after_init);
extern void module_disable_ro(const struct module *mod);
#else
static inline void set_all_modules_text_rw(void) { }
static inline void set_all_modules_text_ro(void) { }
-static inline void module_enable_ro(const struct module *mod) { }
+static inline void module_enable_ro(const struct module *mod, bool after_init) { }
static inline void module_disable_ro(const struct module *mod) { }
#endif
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 4f0bfe5912b2..e8c81fbd5f9c 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -270,6 +270,8 @@ enum {
MSI_FLAG_MULTI_PCI_MSI = (1 << 2),
/* Support PCI MSIX interrupts */
MSI_FLAG_PCI_MSIX = (1 << 3),
+ /* Needs early activate, required for PCI */
+ MSI_FLAG_ACTIVATE_EARLY = (1 << 4),
};
int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index bfed6b367350..c6564ada9beb 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -643,4 +643,15 @@ enum pnfs_update_layout_reason {
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET,
};
+#define NFS4_OP_MAP_NUM_LONGS \
+ DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long))
+#define NFS4_OP_MAP_NUM_WORDS \
+ (NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32))
+struct nfs4_op_map {
+ union {
+ unsigned long longs[NFS4_OP_MAP_NUM_LONGS];
+ u32 words[NFS4_OP_MAP_NUM_WORDS];
+ } u;
+};
+
#endif
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 82b81a1c2438..7cc0deee5bde 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1185,17 +1185,6 @@ struct pnfs_ds_commit_info {
struct pnfs_commit_bucket *buckets;
};
-#define NFS4_OP_MAP_NUM_LONGS \
- DIV_ROUND_UP(LAST_NFS4_OP, 8 * sizeof(unsigned long))
-#define NFS4_OP_MAP_NUM_WORDS \
- (NFS4_OP_MAP_NUM_LONGS * sizeof(unsigned long) / sizeof(u32))
-struct nfs4_op_map {
- union {
- unsigned long longs[NFS4_OP_MAP_NUM_LONGS];
- u32 words[NFS4_OP_MAP_NUM_WORDS];
- } u;
-};
-
struct nfs41_state_protection {
u32 how;
struct nfs4_op_map enforce;
@@ -1543,7 +1532,7 @@ struct nfs_rpc_ops {
struct nfs_fattr *, struct nfs4_label *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
- int (*lookup) (struct inode *, struct qstr *,
+ int (*lookup) (struct inode *, const struct qstr *,
struct nfs_fh *, struct nfs_fattr *,
struct nfs4_label *);
int (*access) (struct inode *, struct nfs_access_entry *);
@@ -1551,18 +1540,18 @@ struct nfs_rpc_ops {
unsigned int);
int (*create) (struct inode *, struct dentry *,
struct iattr *, int);
- int (*remove) (struct inode *, struct qstr *);
+ int (*remove) (struct inode *, const struct qstr *);
void (*unlink_setup) (struct rpc_message *, struct inode *dir);
void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
int (*unlink_done) (struct rpc_task *, struct inode *);
void (*rename_setup) (struct rpc_message *msg, struct inode *dir);
void (*rename_rpc_prepare)(struct rpc_task *task, struct nfs_renamedata *);
int (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
- int (*link) (struct inode *, struct inode *, struct qstr *);
+ int (*link) (struct inode *, struct inode *, const struct qstr *);
int (*symlink) (struct inode *, struct dentry *, struct page *,
unsigned int, struct iattr *);
int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
- int (*rmdir) (struct inode *, struct qstr *);
+ int (*rmdir) (struct inode *, const struct qstr *);
int (*readdir) (struct dentry *, struct rpc_cred *,
u64, struct page **, unsigned int, int);
int (*mknod) (struct inode *, struct dentry *, struct iattr *,
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 81363b834900..66a1260b33de 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -510,7 +510,7 @@ static inline void wait_on_page_writeback(struct page *page)
extern void end_page_writeback(struct page *page);
void wait_for_stable_page(struct page *page);
-void page_endio(struct page *page, int rw, int err);
+void page_endio(struct page *page, bool is_write, int err);
/*
* Add an arbitrary waiter to a page's wait queue
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 8ed4326164cc..2b6b43cc0dd5 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -743,7 +743,9 @@ struct perf_event_context {
u64 parent_gen;
u64 generation;
int pin_count;
+#ifdef CONFIG_CGROUP_PERF
int nr_cgroups; /* cgroup evts */
+#endif
void *task_ctx_data; /* pmu specific data */
struct rcu_head rcu_head;
};
@@ -769,7 +771,9 @@ struct perf_cpu_context {
unsigned int hrtimer_active;
struct pmu *unique_pmu;
+#ifdef CONFIG_CGROUP_PERF
struct perf_cgroup *cgrp;
+#endif
};
struct perf_output_handle {
diff --git a/include/linux/rtc-ds2404.h b/include/linux/platform_data/rtc-ds2404.h
index 22c53825528f..22c53825528f 100644
--- a/include/linux/rtc-ds2404.h
+++ b/include/linux/platform_data/rtc-ds2404.h
diff --git a/include/linux/m48t86.h b/include/linux/platform_data/rtc-m48t86.h
index 915d6b4f0f89..915d6b4f0f89 100644
--- a/include/linux/m48t86.h
+++ b/include/linux/platform_data/rtc-m48t86.h
diff --git a/include/linux/rtc-v3020.h b/include/linux/platform_data/rtc-v3020.h
index e55d82cebf80..e55d82cebf80 100644
--- a/include/linux/rtc-v3020.h
+++ b/include/linux/platform_data/rtc-v3020.h
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 8dc155dab3ed..696a56be7d3e 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -266,39 +266,21 @@ extern asmlinkage void dump_stack(void) __cold;
* and other debug macros are compiled out unless either DEBUG is defined
* or CONFIG_DYNAMIC_DEBUG is set.
*/
-
-#ifdef CONFIG_PRINTK
-
-asmlinkage __printf(1, 2) __cold void __pr_emerg(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_alert(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_crit(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_err(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_warn(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_notice(const char *fmt, ...);
-asmlinkage __printf(1, 2) __cold void __pr_info(const char *fmt, ...);
-
-#define pr_emerg(fmt, ...) __pr_emerg(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_alert(fmt, ...) __pr_alert(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_crit(fmt, ...) __pr_crit(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_err(fmt, ...) __pr_err(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn(fmt, ...) __pr_warn(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_notice(fmt, ...) __pr_notice(pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info(fmt, ...) __pr_info(pr_fmt(fmt), ##__VA_ARGS__)
-
-#else
-
-#define pr_emerg(fmt, ...) printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_alert(fmt, ...) printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_crit(fmt, ...) printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_err(fmt, ...) printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn(fmt, ...) printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_notice(fmt, ...) printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_info(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
-
-#endif
-
-#define pr_warning pr_warn
-
+#define pr_emerg(fmt, ...) \
+ printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_alert(fmt, ...) \
+ printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_crit(fmt, ...) \
+ printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...) \
+ printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warning(fmt, ...) \
+ printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_warn pr_warning
+#define pr_notice(fmt, ...) \
+ printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_info(fmt, ...) \
+ printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
/*
* Like KERN_CONT, pr_cont() should only be used when continuing
* a line with no newline ('\n') enclosed. Otherwise it defaults
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index c038ae36b10e..f1bbae014889 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -5,7 +5,9 @@
#include <linux/mutex.h>
#include <linux/of.h>
+struct pwm_capture;
struct seq_file;
+
struct pwm_chip;
/**
@@ -148,11 +150,100 @@ static inline void pwm_get_args(const struct pwm_device *pwm,
}
/**
+ * pwm_init_state() - prepare a new state to be applied with pwm_apply_state()
+ * @pwm: PWM device
+ * @state: state to fill with the prepared PWM state
+ *
+ * This functions prepares a state that can later be tweaked and applied
+ * to the PWM device with pwm_apply_state(). This is a convenient function
+ * that first retrieves the current PWM state and the replaces the period
+ * and polarity fields with the reference values defined in pwm->args.
+ * Once the function returns, you can adjust the ->enabled and ->duty_cycle
+ * fields according to your needs before calling pwm_apply_state().
+ *
+ * ->duty_cycle is initially set to zero to avoid cases where the current
+ * ->duty_cycle value exceed the pwm_args->period one, which would trigger
+ * an error if the user calls pwm_apply_state() without adjusting ->duty_cycle
+ * first.
+ */
+static inline void pwm_init_state(const struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct pwm_args args;
+
+ /* First get the current state. */
+ pwm_get_state(pwm, state);
+
+ /* Then fill it with the reference config */
+ pwm_get_args(pwm, &args);
+
+ state->period = args.period;
+ state->polarity = args.polarity;
+ state->duty_cycle = 0;
+}
+
+/**
+ * pwm_get_relative_duty_cycle() - Get a relative duty cycle value
+ * @state: PWM state to extract the duty cycle from
+ * @scale: target scale of the relative duty cycle
+ *
+ * This functions converts the absolute duty cycle stored in @state (expressed
+ * in nanosecond) into a value relative to the period.
+ *
+ * For example if you want to get the duty_cycle expressed in percent, call:
+ *
+ * pwm_get_state(pwm, &state);
+ * duty = pwm_get_relative_duty_cycle(&state, 100);
+ */
+static inline unsigned int
+pwm_get_relative_duty_cycle(const struct pwm_state *state, unsigned int scale)
+{
+ if (!state->period)
+ return 0;
+
+ return DIV_ROUND_CLOSEST_ULL((u64)state->duty_cycle * scale,
+ state->period);
+}
+
+/**
+ * pwm_set_relative_duty_cycle() - Set a relative duty cycle value
+ * @state: PWM state to fill
+ * @duty_cycle: relative duty cycle value
+ * @scale: scale in which @duty_cycle is expressed
+ *
+ * This functions converts a relative into an absolute duty cycle (expressed
+ * in nanoseconds), and puts the result in state->duty_cycle.
+ *
+ * For example if you want to configure a 50% duty cycle, call:
+ *
+ * pwm_init_state(pwm, &state);
+ * pwm_set_relative_duty_cycle(&state, 50, 100);
+ * pwm_apply_state(pwm, &state);
+ *
+ * This functions returns -EINVAL if @duty_cycle and/or @scale are
+ * inconsistent (@scale == 0 or @duty_cycle > @scale).
+ */
+static inline int
+pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
+ unsigned int scale)
+{
+ if (!scale || duty_cycle > scale)
+ return -EINVAL;
+
+ state->duty_cycle = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle *
+ state->period,
+ scale);
+
+ return 0;
+}
+
+/**
* struct pwm_ops - PWM controller operations
* @request: optional hook for requesting a PWM
* @free: optional hook for freeing a PWM
* @config: configure duty cycles and period length for this PWM
* @set_polarity: configure the polarity of this PWM
+ * @capture: capture and report PWM signal
* @enable: enable PWM output toggling
* @disable: disable PWM output toggling
* @apply: atomically apply a new PWM config. The state argument
@@ -172,6 +263,8 @@ struct pwm_ops {
int duty_ns, int period_ns);
int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity);
+ int (*capture)(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_capture *result, unsigned long timeout);
int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm);
int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -212,6 +305,16 @@ struct pwm_chip {
bool can_sleep;
};
+/**
+ * struct pwm_capture - PWM capture data
+ * @period: period of the PWM signal (in nanoseconds)
+ * @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
+ */
+struct pwm_capture {
+ unsigned int period;
+ unsigned int duty_cycle;
+};
+
#if IS_ENABLED(CONFIG_PWM)
/* PWM user APIs */
struct pwm_device *pwm_request(int pwm_id, const char *label);
@@ -323,8 +426,9 @@ static inline void pwm_disable(struct pwm_device *pwm)
pwm_apply_state(pwm, &state);
}
-
/* PWM provider APIs */
+int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+ unsigned long timeout);
int pwm_set_chip_data(struct pwm_device *pwm, void *data);
void *pwm_get_chip_data(struct pwm_device *pwm);
@@ -376,6 +480,13 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
return -EINVAL;
}
+static inline int pwm_capture(struct pwm_device *pwm,
+ struct pwm_capture *result,
+ unsigned long timeout)
+{
+ return -EINVAL;
+}
+
static inline int pwm_set_polarity(struct pwm_device *pwm,
enum pwm_polarity polarity)
{
diff --git a/include/linux/ds1286.h b/include/linux/rtc/ds1286.h
index 45ea0aa0aeb9..45ea0aa0aeb9 100644
--- a/include/linux/ds1286.h
+++ b/include/linux/rtc/ds1286.h
diff --git a/include/linux/security.h b/include/linux/security.h
index 14df373ff2ca..7831cd57bcf7 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -240,7 +240,7 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb);
int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
int security_dentry_init_security(struct dentry *dentry, int mode,
- struct qstr *name, void **ctx,
+ const struct qstr *name, void **ctx,
u32 *ctxlen);
int security_inode_alloc(struct inode *inode);
@@ -591,7 +591,7 @@ static inline void security_inode_free(struct inode *inode)
static inline int security_dentry_init_security(struct dentry *dentry,
int mode,
- struct qstr *name,
+ const struct qstr *name,
void **ctx,
u32 *ctxlen)
{
diff --git a/include/linux/serio.h b/include/linux/serio.h
index df4ab5de1586..c733cff44e18 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -31,7 +31,8 @@ struct serio {
struct serio_device_id id;
- spinlock_t lock; /* protects critical sections from port's interrupt handler */
+ /* Protects critical sections from port's interrupt handler */
+ spinlock_t lock;
int (*write)(struct serio *, unsigned char);
int (*open)(struct serio *);
@@ -40,16 +41,29 @@ struct serio {
void (*stop)(struct serio *);
struct serio *parent;
- struct list_head child_node; /* Entry in parent->children list */
+ /* Entry in parent->children list */
+ struct list_head child_node;
struct list_head children;
- unsigned int depth; /* level of nesting in serio hierarchy */
+ /* Level of nesting in serio hierarchy */
+ unsigned int depth;
- struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */
- struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
+ /*
+ * serio->drv is accessed from interrupt handlers; when modifying
+ * caller should acquire serio->drv_mutex and serio->lock.
+ */
+ struct serio_driver *drv;
+ /* Protects serio->drv so attributes can pin current driver */
+ struct mutex drv_mutex;
struct device dev;
struct list_head node;
+
+ /*
+ * For use by PS/2 layer when several ports share hardware and
+ * may get indigestion when exposed to concurrent access (i8042).
+ */
+ struct mutex *ps2_cmd_mutex;
};
#define to_serio_port(d) container_of(d, struct serio, dev)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 1a4ea551aae5..4293808d8cfb 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -155,6 +155,18 @@ void kfree(const void *);
void kzfree(const void *);
size_t ksize(const void *);
+#ifdef CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR
+const char *__check_heap_object(const void *ptr, unsigned long n,
+ struct page *page);
+#else
+static inline const char *__check_heap_object(const void *ptr,
+ unsigned long n,
+ struct page *page)
+{
+ return NULL;
+}
+#endif
+
/*
* Some archs want to perform DMA into kmalloc caches and need a guaranteed
* alignment larger than the alignment of a 64-bit integer.
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index ed03c9f7f908..62a60eeacb0a 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -78,8 +78,6 @@ struct cache_detail {
struct hlist_head * hash_table;
rwlock_t hash_lock;
- atomic_t inuse; /* active user-space update or lookup */
-
char *name;
void (*cache_put)(struct kref *);
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index b6810c92b8bb..5c02b0691587 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -195,6 +195,8 @@ int rpc_clnt_add_xprt(struct rpc_clnt *, struct xprt_create *,
struct rpc_xprt *,
void *),
void *data);
+void rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
+ unsigned long timeo);
const char *rpc_proc_name(const struct rpc_task *task);
#endif /* __KERNEL__ */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 7ca44fb5b675..7321ae933867 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -268,6 +268,7 @@ struct svc_rqst {
* cache pages */
#define RQ_VICTIM (5) /* about to be shut down */
#define RQ_BUSY (6) /* request is busy */
+#define RQ_DATA (7) /* request has data */
unsigned long rq_flags; /* flags field */
void * rq_argp; /* decoded arguments */
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 79ba50856707..ab02a457da1f 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -25,7 +25,6 @@ struct svc_xprt_ops {
void (*xpo_detach)(struct svc_xprt *);
void (*xpo_free)(struct svc_xprt *);
int (*xpo_secure_port)(struct svc_rqst *);
- void (*xpo_adjust_wspace)(struct svc_xprt *);
};
struct svc_xprt_class {
@@ -69,6 +68,7 @@ struct svc_xprt {
struct svc_serv *xpt_server; /* service for transport */
atomic_t xpt_reserved; /* space on outq that is rsvd */
+ atomic_t xpt_nr_rqsts; /* Number of requests */
struct mutex xpt_mutex; /* to serialize sending data */
spinlock_t xpt_lock; /* protects sk_deferred
* and xpt_auth_cache */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 5e3e1b63dbb3..a16070dd03ee 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -218,7 +218,8 @@ struct rpc_xprt {
struct work_struct task_cleanup;
struct timer_list timer;
unsigned long last_used,
- idle_timeout;
+ idle_timeout,
+ max_reconnect_timeout;
/*
* Send stuff
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 017fced60242..5f81f8a187f2 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -6,7 +6,6 @@
#include <linux/types.h>
struct device;
-struct dma_attrs;
struct page;
struct scatterlist;
@@ -68,10 +67,10 @@ swiotlb_free_coherent(struct device *hwdev, size_t size,
extern dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern int
swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
@@ -83,12 +82,13 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
extern int
swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
- enum dma_data_direction dir, struct dma_attrs *attrs);
+ enum dma_data_direction dir,
+ unsigned long attrs);
extern void
swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void
swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 352b1542f5cc..cbd8990e2e77 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -105,6 +105,30 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)
+#ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES
+static inline int arch_within_stack_frames(const void * const stack,
+ const void * const stackend,
+ const void *obj, unsigned long len)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_HARDENED_USERCOPY
+extern void __check_object_size(const void *ptr, unsigned long n,
+ bool to_user);
+
+static inline void check_object_size(const void *ptr, unsigned long n,
+ bool to_user)
+{
+ __check_object_size(ptr, n, to_user);
+}
+#else
+static inline void check_object_size(const void *ptr, unsigned long n,
+ bool to_user)
+{ }
+#endif /* CONFIG_HARDENED_USERCOPY */
+
#endif /* __KERNEL__ */
#endif /* _LINUX_THREAD_INFO_H */
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 349557825428..f30c187ed785 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -114,8 +114,8 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
#ifndef user_access_begin
#define user_access_begin() do { } while (0)
#define user_access_end() do { } while (0)
-#define unsafe_get_user(x, ptr) __get_user(x, ptr)
-#define unsafe_put_user(x, ptr) __put_user(x, ptr)
+#define unsafe_get_user(x, ptr, err) do { if (unlikely(__get_user(x, ptr))) goto err; } while (0)
+#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0)
#endif
#endif /* __LINUX_UACCESS_H__ */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 6e6cb0c9d7cb..26c155bb639b 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -149,6 +149,19 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev,
return __virtio_test_bit(vdev, fbit);
}
+/**
+ * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
+ * @vdev: the device
+ */
+static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
+{
+ /*
+ * Note the reverse polarity of the quirk feature (compared to most
+ * other features), this is for compatibility with legacy systems.
+ */
+ return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+}
+
static inline
struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
vq_callback_t *c, const char *n)
diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h
new file mode 100644
index 000000000000..9638bfeb0d1f
--- /dev/null
+++ b/include/linux/virtio_vsock.h
@@ -0,0 +1,154 @@
+#ifndef _LINUX_VIRTIO_VSOCK_H
+#define _LINUX_VIRTIO_VSOCK_H
+
+#include <uapi/linux/virtio_vsock.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <net/af_vsock.h>
+
+#define VIRTIO_VSOCK_DEFAULT_MIN_BUF_SIZE 128
+#define VIRTIO_VSOCK_DEFAULT_BUF_SIZE (1024 * 256)
+#define VIRTIO_VSOCK_DEFAULT_MAX_BUF_SIZE (1024 * 256)
+#define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE (1024 * 4)
+#define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL
+#define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64)
+
+enum {
+ VSOCK_VQ_RX = 0, /* for host to guest data */
+ VSOCK_VQ_TX = 1, /* for guest to host data */
+ VSOCK_VQ_EVENT = 2,
+ VSOCK_VQ_MAX = 3,
+};
+
+/* Per-socket state (accessed via vsk->trans) */
+struct virtio_vsock_sock {
+ struct vsock_sock *vsk;
+
+ /* Protected by lock_sock(sk_vsock(trans->vsk)) */
+ u32 buf_size;
+ u32 buf_size_min;
+ u32 buf_size_max;
+
+ spinlock_t tx_lock;
+ spinlock_t rx_lock;
+
+ /* Protected by tx_lock */
+ u32 tx_cnt;
+ u32 buf_alloc;
+ u32 peer_fwd_cnt;
+ u32 peer_buf_alloc;
+
+ /* Protected by rx_lock */
+ u32 fwd_cnt;
+ u32 rx_bytes;
+ struct list_head rx_queue;
+};
+
+struct virtio_vsock_pkt {
+ struct virtio_vsock_hdr hdr;
+ struct work_struct work;
+ struct list_head list;
+ void *buf;
+ u32 len;
+ u32 off;
+ bool reply;
+};
+
+struct virtio_vsock_pkt_info {
+ u32 remote_cid, remote_port;
+ struct msghdr *msg;
+ u32 pkt_len;
+ u16 type;
+ u16 op;
+ u32 flags;
+ bool reply;
+};
+
+struct virtio_transport {
+ /* This must be the first field */
+ struct vsock_transport transport;
+
+ /* Takes ownership of the packet */
+ int (*send_pkt)(struct virtio_vsock_pkt *pkt);
+};
+
+ssize_t
+virtio_transport_stream_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len,
+ int type);
+int
+virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len, int flags);
+
+s64 virtio_transport_stream_has_data(struct vsock_sock *vsk);
+s64 virtio_transport_stream_has_space(struct vsock_sock *vsk);
+
+int virtio_transport_do_socket_init(struct vsock_sock *vsk,
+ struct vsock_sock *psk);
+u64 virtio_transport_get_buffer_size(struct vsock_sock *vsk);
+u64 virtio_transport_get_min_buffer_size(struct vsock_sock *vsk);
+u64 virtio_transport_get_max_buffer_size(struct vsock_sock *vsk);
+void virtio_transport_set_buffer_size(struct vsock_sock *vsk, u64 val);
+void virtio_transport_set_min_buffer_size(struct vsock_sock *vsk, u64 val);
+void virtio_transport_set_max_buffer_size(struct vsock_sock *vs, u64 val);
+int
+virtio_transport_notify_poll_in(struct vsock_sock *vsk,
+ size_t target,
+ bool *data_ready_now);
+int
+virtio_transport_notify_poll_out(struct vsock_sock *vsk,
+ size_t target,
+ bool *space_available_now);
+
+int virtio_transport_notify_recv_init(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data);
+int virtio_transport_notify_recv_pre_block(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data);
+int virtio_transport_notify_recv_pre_dequeue(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data);
+int virtio_transport_notify_recv_post_dequeue(struct vsock_sock *vsk,
+ size_t target, ssize_t copied, bool data_read,
+ struct vsock_transport_recv_notify_data *data);
+int virtio_transport_notify_send_init(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data);
+int virtio_transport_notify_send_pre_block(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data);
+int virtio_transport_notify_send_pre_enqueue(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data);
+int virtio_transport_notify_send_post_enqueue(struct vsock_sock *vsk,
+ ssize_t written, struct vsock_transport_send_notify_data *data);
+
+u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk);
+bool virtio_transport_stream_is_active(struct vsock_sock *vsk);
+bool virtio_transport_stream_allow(u32 cid, u32 port);
+int virtio_transport_dgram_bind(struct vsock_sock *vsk,
+ struct sockaddr_vm *addr);
+bool virtio_transport_dgram_allow(u32 cid, u32 port);
+
+int virtio_transport_connect(struct vsock_sock *vsk);
+
+int virtio_transport_shutdown(struct vsock_sock *vsk, int mode);
+
+void virtio_transport_release(struct vsock_sock *vsk);
+
+ssize_t
+virtio_transport_stream_enqueue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len);
+int
+virtio_transport_dgram_enqueue(struct vsock_sock *vsk,
+ struct sockaddr_vm *remote_addr,
+ struct msghdr *msg,
+ size_t len);
+
+void virtio_transport_destruct(struct vsock_sock *vsk);
+
+void virtio_transport_recv_pkt(struct virtio_vsock_pkt *pkt);
+void virtio_transport_free_pkt(struct virtio_vsock_pkt *pkt);
+void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt);
+u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 wanted);
+void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit);
+
+#endif /* _LINUX_VIRTIO_VSOCK_H */
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 760399a470bd..2bb5deb0012e 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -173,14 +173,14 @@ static inline void ww_acquire_fini(struct ww_acquire_ctx *ctx)
mutex_release(&ctx->dep_map, 0, _THIS_IP_);
DEBUG_LOCKS_WARN_ON(ctx->acquired);
- if (!config_enabled(CONFIG_PROVE_LOCKING))
+ if (!IS_ENABLED(CONFIG_PROVE_LOCKING))
/*
* lockdep will normally handle this,
* but fail without anyway
*/
ctx->done_acquire = 1;
- if (!config_enabled(CONFIG_DEBUG_LOCK_ALLOC))
+ if (!IS_ENABLED(CONFIG_DEBUG_LOCK_ALLOC))
/* ensure ww_acquire_fini will still fail if called twice */
ctx->acquired = ~0U;
#endif
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 946340ce7701..a4a9a55a0c42 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -98,7 +98,7 @@ struct vb2_threadio_data;
* #) Required ops for DMABUF types: attach_dmabuf, detach_dmabuf, map_dmabuf, unmap_dmabuf.
*/
struct vb2_mem_ops {
- void *(*alloc)(struct device *dev, const struct dma_attrs *attrs,
+ void *(*alloc)(struct device *dev, unsigned long attrs,
unsigned long size, enum dma_data_direction dma_dir,
gfp_t gfp_flags);
void (*put)(void *buf_priv);
@@ -408,7 +408,7 @@ struct vb2_buf_ops {
* @io_modes: supported io methods (see vb2_io_modes enum)
* @dev: device to use for the default allocation context if the driver
* doesn't fill in the @alloc_devs array.
- * @dma_attrs: DMA attributes to use for the DMA. May be NULL.
+ * @dma_attrs: DMA attributes to use for the DMA.
* @fileio_read_once: report EOF after reading the first buffer
* @fileio_write_immediately: queue buffer after each write() call
* @allow_zero_bytesused: allow bytesused == 0 to be passed to the driver
@@ -476,7 +476,7 @@ struct vb2_queue {
unsigned int type;
unsigned int io_modes;
struct device *dev;
- const struct dma_attrs *dma_attrs;
+ unsigned long dma_attrs;
unsigned fileio_read_once:1;
unsigned fileio_write_immediately:1;
unsigned allow_zero_bytesused:1;
diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h
index df2aabee3401..5604818d137e 100644
--- a/include/media/videobuf2-dma-contig.h
+++ b/include/media/videobuf2-dma-contig.h
@@ -16,8 +16,6 @@
#include <media/videobuf2-v4l2.h>
#include <linux/dma-mapping.h>
-struct dma_attrs;
-
static inline dma_addr_t
vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no)
{
diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h
index e9eb2d6791b3..f2758964ce6f 100644
--- a/include/net/af_vsock.h
+++ b/include/net/af_vsock.h
@@ -63,6 +63,8 @@ struct vsock_sock {
struct list_head accept_queue;
bool rejected;
struct delayed_work dwork;
+ struct delayed_work close_work;
+ bool close_work_scheduled;
u32 peer_shutdown;
bool sent_request;
bool ignore_connecting_rst;
@@ -165,6 +167,9 @@ static inline int vsock_core_init(const struct vsock_transport *t)
}
void vsock_core_exit(void);
+/* The transport may downcast this to access transport-specific functions */
+const struct vsock_transport *vsock_core_get_transport(void);
+
/**** UTILS ****/
void vsock_release_pending(struct sock *pending);
@@ -177,6 +182,7 @@ void vsock_remove_connected(struct vsock_sock *vsk);
struct sock *vsock_find_bound_socket(struct sockaddr_vm *addr);
struct sock *vsock_find_connected_socket(struct sockaddr_vm *src,
struct sockaddr_vm *dst);
+void vsock_remove_sock(struct vsock_sock *vsk);
void vsock_for_each_connected_socket(void (*fn)(struct sock *sk));
#endif /* __AF_VSOCK_H__ */
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index 384041669489..5ee7aab95eb8 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -94,6 +94,19 @@ enum ib_sa_selector {
IB_SA_BEST = 3
};
+/*
+ * There are 4 types of join states:
+ * FullMember, NonMember, SendOnlyNonMember, SendOnlyFullMember.
+ * The order corresponds to JoinState bits in MCMemberRecord.
+ */
+enum ib_sa_mc_join_states {
+ FULLMEMBER_JOIN,
+ NONMEMBER_JOIN,
+ SENDONLY_NONMEBER_JOIN,
+ SENDONLY_FULLMEMBER_JOIN,
+ NUM_JOIN_MEMBERSHIP_TYPES,
+};
+
#define IB_SA_CAP_MASK2_SENDONLY_FULL_MEM_SUPPORT BIT(12)
/*
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 7e440d41487a..8e90dd28bb75 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -562,6 +562,7 @@ enum ib_event_type {
IB_EVENT_QP_LAST_WQE_REACHED,
IB_EVENT_CLIENT_REREGISTER,
IB_EVENT_GID_CHANGE,
+ IB_EVENT_WQ_FATAL,
};
const char *__attribute_const__ ib_event_msg(enum ib_event_type event);
@@ -572,6 +573,7 @@ struct ib_event {
struct ib_cq *cq;
struct ib_qp *qp;
struct ib_srq *srq;
+ struct ib_wq *wq;
u8 port_num;
} element;
enum ib_event_type event;
@@ -1015,6 +1017,7 @@ struct ib_qp_init_attr {
* Only needed for special QP types, or when using the RW API.
*/
u8 port_num;
+ struct ib_rwq_ind_table *rwq_ind_tbl;
};
struct ib_qp_open_attr {
@@ -1323,6 +1326,8 @@ struct ib_ucontext {
struct list_head ah_list;
struct list_head xrcd_list;
struct list_head rule_list;
+ struct list_head wq_list;
+ struct list_head rwq_ind_tbl_list;
int closing;
struct pid *tgid;
@@ -1428,6 +1433,67 @@ struct ib_srq {
} ext;
};
+enum ib_wq_type {
+ IB_WQT_RQ
+};
+
+enum ib_wq_state {
+ IB_WQS_RESET,
+ IB_WQS_RDY,
+ IB_WQS_ERR
+};
+
+struct ib_wq {
+ struct ib_device *device;
+ struct ib_uobject *uobject;
+ void *wq_context;
+ void (*event_handler)(struct ib_event *, void *);
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+ u32 wq_num;
+ enum ib_wq_state state;
+ enum ib_wq_type wq_type;
+ atomic_t usecnt;
+};
+
+struct ib_wq_init_attr {
+ void *wq_context;
+ enum ib_wq_type wq_type;
+ u32 max_wr;
+ u32 max_sge;
+ struct ib_cq *cq;
+ void (*event_handler)(struct ib_event *, void *);
+};
+
+enum ib_wq_attr_mask {
+ IB_WQ_STATE = 1 << 0,
+ IB_WQ_CUR_STATE = 1 << 1,
+};
+
+struct ib_wq_attr {
+ enum ib_wq_state wq_state;
+ enum ib_wq_state curr_wq_state;
+};
+
+struct ib_rwq_ind_table {
+ struct ib_device *device;
+ struct ib_uobject *uobject;
+ atomic_t usecnt;
+ u32 ind_tbl_num;
+ u32 log_ind_tbl_size;
+ struct ib_wq **ind_tbl;
+};
+
+struct ib_rwq_ind_table_init_attr {
+ u32 log_ind_tbl_size;
+ /* Each entry is a pointer to Receive Work Queue */
+ struct ib_wq **ind_tbl;
+};
+
+/*
+ * @max_write_sge: Maximum SGE elements per RDMA WRITE request.
+ * @max_read_sge: Maximum SGE elements per RDMA READ request.
+ */
struct ib_qp {
struct ib_device *device;
struct ib_pd *pd;
@@ -1449,7 +1515,10 @@ struct ib_qp {
void (*event_handler)(struct ib_event *, void *);
void *qp_context;
u32 qp_num;
+ u32 max_write_sge;
+ u32 max_read_sge;
enum ib_qp_type qp_type;
+ struct ib_rwq_ind_table *rwq_ind_tbl;
};
struct ib_mr {
@@ -1506,6 +1575,7 @@ enum ib_flow_spec_type {
IB_FLOW_SPEC_IB = 0x22,
/* L3 header*/
IB_FLOW_SPEC_IPV4 = 0x30,
+ IB_FLOW_SPEC_IPV6 = 0x31,
/* L4 headers*/
IB_FLOW_SPEC_TCP = 0x40,
IB_FLOW_SPEC_UDP = 0x41
@@ -1567,6 +1637,18 @@ struct ib_flow_spec_ipv4 {
struct ib_flow_ipv4_filter mask;
};
+struct ib_flow_ipv6_filter {
+ u8 src_ip[16];
+ u8 dst_ip[16];
+};
+
+struct ib_flow_spec_ipv6 {
+ enum ib_flow_spec_type type;
+ u16 size;
+ struct ib_flow_ipv6_filter val;
+ struct ib_flow_ipv6_filter mask;
+};
+
struct ib_flow_tcp_udp_filter {
__be16 dst_port;
__be16 src_port;
@@ -1588,6 +1670,7 @@ union ib_flow_spec {
struct ib_flow_spec_ib ib;
struct ib_flow_spec_ipv4 ipv4;
struct ib_flow_spec_tcp_udp tcp_udp;
+ struct ib_flow_spec_ipv6 ipv6;
};
struct ib_flow_attr {
@@ -1921,7 +2004,18 @@ struct ib_device {
struct ifla_vf_stats *stats);
int (*set_vf_guid)(struct ib_device *device, int vf, u8 port, u64 guid,
int type);
-
+ struct ib_wq * (*create_wq)(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr,
+ struct ib_udata *udata);
+ int (*destroy_wq)(struct ib_wq *wq);
+ int (*modify_wq)(struct ib_wq *wq,
+ struct ib_wq_attr *attr,
+ u32 wq_attr_mask,
+ struct ib_udata *udata);
+ struct ib_rwq_ind_table * (*create_rwq_ind_table)(struct ib_device *device,
+ struct ib_rwq_ind_table_init_attr *init_attr,
+ struct ib_udata *udata);
+ int (*destroy_rwq_ind_table)(struct ib_rwq_ind_table *wq_ind_table);
struct ib_dma_mapping_ops *dma_ops;
struct module *owner;
@@ -1956,6 +2050,7 @@ struct ib_device {
* in fast paths.
*/
int (*get_port_immutable)(struct ib_device *, u8, struct ib_port_immutable *);
+ void (*get_dev_fw_str)(struct ib_device *, char *str, size_t str_len);
};
struct ib_client {
@@ -1991,6 +2086,8 @@ struct ib_client {
struct ib_device *ib_alloc_device(size_t size);
void ib_dealloc_device(struct ib_device *device);
+void ib_get_device_fw_str(struct ib_device *device, char *str, size_t str_len);
+
int ib_register_device(struct ib_device *device,
int (*port_callback)(struct ib_device *,
u8, struct kobject *));
@@ -2819,19 +2916,19 @@ static inline void ib_dma_unmap_single(struct ib_device *dev,
static inline u64 ib_dma_map_single_attrs(struct ib_device *dev,
void *cpu_addr, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long dma_attrs)
{
return dma_map_single_attrs(dev->dma_device, cpu_addr, size,
- direction, attrs);
+ direction, dma_attrs);
}
static inline void ib_dma_unmap_single_attrs(struct ib_device *dev,
u64 addr, size_t size,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long dma_attrs)
{
return dma_unmap_single_attrs(dev->dma_device, addr, size,
- direction, attrs);
+ direction, dma_attrs);
}
/**
@@ -2906,17 +3003,18 @@ static inline void ib_dma_unmap_sg(struct ib_device *dev,
static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long dma_attrs)
{
- return dma_map_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
+ return dma_map_sg_attrs(dev->dma_device, sg, nents, direction,
+ dma_attrs);
}
static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
- struct dma_attrs *attrs)
+ unsigned long dma_attrs)
{
- dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, attrs);
+ dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, dma_attrs);
}
/**
* ib_sg_dma_address - Return the DMA address from a scatter/gather entry
@@ -3167,6 +3265,15 @@ int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
u16 pkey, const union ib_gid *gid,
const struct sockaddr *addr);
+struct ib_wq *ib_create_wq(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr);
+int ib_destroy_wq(struct ib_wq *wq);
+int ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *attr,
+ u32 wq_attr_mask);
+struct ib_rwq_ind_table *ib_create_rwq_ind_table(struct ib_device *device,
+ struct ib_rwq_ind_table_init_attr*
+ wq_ind_table_init_attr);
+int ib_destroy_rwq_ind_table(struct ib_rwq_ind_table *wq_ind_table);
int ib_map_mr_sg(struct ib_mr *mr, struct scatterlist *sg, int sg_nents,
unsigned int *sg_offset, unsigned int page_size);
diff --git a/include/rdma/opa_port_info.h b/include/rdma/opa_port_info.h
index 2b95c2c336eb..9303e0e4f508 100644
--- a/include/rdma/opa_port_info.h
+++ b/include/rdma/opa_port_info.h
@@ -33,11 +33,6 @@
#if !defined(OPA_PORT_INFO_H)
#define OPA_PORT_INFO_H
-/* Temporary until HFI driver is updated */
-#ifndef USE_PI_LED_ENABLE
-#define USE_PI_LED_ENABLE 0
-#endif
-
#define OPA_PORT_LINK_MODE_NOP 0 /* No change */
#define OPA_PORT_LINK_MODE_OPA 4 /* Port mode is OPA */
@@ -274,23 +269,12 @@ enum port_info_field_masks {
OPA_PI_MASK_MTU_CAP = 0x0F,
};
-#if USE_PI_LED_ENABLE
struct opa_port_states {
u8 reserved;
u8 ledenable_offlinereason; /* 1 res, 1 bit, 6 bits */
u8 reserved2;
u8 portphysstate_portstate; /* 4 bits, 4 bits */
};
-#define PI_LED_ENABLE_SUP 1
-#else
-struct opa_port_states {
- u8 reserved;
- u8 offline_reason; /* 2 res, 6 bits */
- u8 reserved2;
- u8 portphysstate_portstate; /* 4 bits, 4 bits */
-};
-#define PI_LED_ENABLE_SUP 0
-#endif
struct opa_port_state_info {
struct opa_port_states port_states;
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
index afe44fde72a5..81fb1d15e8bb 100644
--- a/include/rdma/rdma_cm.h
+++ b/include/rdma/rdma_cm.h
@@ -333,11 +333,13 @@ int rdma_disconnect(struct rdma_cm_id *id);
* address.
* @id: Communication identifier associated with the request.
* @addr: Multicast address identifying the group to join.
+ * @join_state: Multicast JoinState bitmap requested by port.
+ * Bitmap is based on IB_SA_MCMEMBER_REC_JOIN_STATE bits.
* @context: User-defined context associated with the join request, returned
* to the user through the private_data pointer in multicast events.
*/
int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
- void *context);
+ u8 join_state, void *context);
/**
* rdma_leave_multicast - Leave the multicast group specified by the given
diff --git a/include/rdma/rdma_vt.h b/include/rdma/rdma_vt.h
index 9c9a27d42aaa..e31502107a58 100644
--- a/include/rdma/rdma_vt.h
+++ b/include/rdma/rdma_vt.h
@@ -158,6 +158,7 @@ struct rvt_driver_params {
u32 max_mad_size;
u8 qos_shift;
u8 max_rdma_atomic;
+ u8 reserved_operations;
};
/* Protection domain */
@@ -351,6 +352,9 @@ struct rvt_dev_info {
/* Driver specific properties */
struct rvt_driver_params dparms;
+ /* post send table */
+ const struct rvt_operation_params *post_parms;
+
struct rvt_mregion __rcu *dma_mr;
struct rvt_lkey_table lkey_table;
@@ -484,6 +488,9 @@ void rvt_unregister_device(struct rvt_dev_info *rvd);
int rvt_check_ah(struct ib_device *ibdev, struct ib_ah_attr *ah_attr);
int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port,
int port_index, u16 *pkey_table);
+int rvt_fast_reg_mr(struct rvt_qp *qp, struct ib_mr *ibmr, u32 key,
+ int access);
+int rvt_invalidate_rkey(struct rvt_qp *qp, u32 rkey);
int rvt_rkey_ok(struct rvt_qp *qp, struct rvt_sge *sge,
u32 len, u64 vaddr, u32 rkey, int acc);
int rvt_lkey_ok(struct rvt_lkey_table *rkt, struct rvt_pd *pd,
diff --git a/include/rdma/rdmavt_mr.h b/include/rdma/rdmavt_mr.h
index 5edffdca8c53..6b3c6c8b6b77 100644
--- a/include/rdma/rdmavt_mr.h
+++ b/include/rdma/rdmavt_mr.h
@@ -81,6 +81,7 @@ struct rvt_mregion {
u32 mapsz; /* size of the map array */
u8 page_shift; /* 0 - non unform/non powerof2 sizes */
u8 lkey_published; /* in global table */
+ atomic_t lkey_invalid; /* true if current lkey is invalid */
struct completion comp; /* complete when refcount goes to zero */
atomic_t refcount;
struct rvt_segarray *map[0]; /* the segments */
diff --git a/include/rdma/rdmavt_qp.h b/include/rdma/rdmavt_qp.h
index 6d23b879416a..bd34d0b56bf7 100644
--- a/include/rdma/rdmavt_qp.h
+++ b/include/rdma/rdmavt_qp.h
@@ -145,6 +145,12 @@
(RVT_PROCESS_SEND_OK | RVT_FLUSH_SEND)
/*
+ * Internal send flags
+ */
+#define RVT_SEND_RESERVE_USED IB_SEND_RESERVED_START
+#define RVT_SEND_COMPLETION_ONLY (IB_SEND_RESERVED_START << 1)
+
+/*
* Send work request queue entry.
* The size of the sg_list is determined when the QP is created and stored
* in qp->s_max_sge.
@@ -216,23 +222,43 @@ struct rvt_mmap_info {
* to send a RDMA read response or atomic operation.
*/
struct rvt_ack_entry {
- u8 opcode;
- u8 sent;
+ struct rvt_sge rdma_sge;
+ u64 atomic_data;
u32 psn;
u32 lpsn;
- union {
- struct rvt_sge rdma_sge;
- u64 atomic_data;
- };
+ u8 opcode;
+ u8 sent;
};
#define RC_QP_SCALING_INTERVAL 5
-/*
- * Variables prefixed with s_ are for the requester (sender).
- * Variables prefixed with r_ are for the responder (receiver).
- * Variables prefixed with ack_ are for responder replies.
+#define RVT_OPERATION_PRIV 0x00000001
+#define RVT_OPERATION_ATOMIC 0x00000002
+#define RVT_OPERATION_ATOMIC_SGE 0x00000004
+#define RVT_OPERATION_LOCAL 0x00000008
+#define RVT_OPERATION_USE_RESERVE 0x00000010
+
+#define RVT_OPERATION_MAX (IB_WR_RESERVED10 + 1)
+
+/**
+ * rvt_operation_params - op table entry
+ * @length - the length to copy into the swqe entry
+ * @qpt_support - a bit mask indicating QP type support
+ * @flags - RVT_OPERATION flags (see above)
*
+ * This supports table driven post send so that
+ * the driver can have differing an potentially
+ * different sets of operations.
+ *
+ **/
+
+struct rvt_operation_params {
+ size_t length;
+ u32 qpt_support;
+ u32 flags;
+};
+
+/*
* Common variables are protected by both r_rq.lock and s_lock in that order
* which only happens in modify_qp() or changing the QP 'state'.
*/
@@ -307,6 +333,7 @@ struct rvt_qp {
u32 s_next_psn; /* PSN for next request */
u32 s_avail; /* number of entries avail */
u32 s_ssn; /* SSN of tail entry */
+ atomic_t s_reserved_used; /* reserved entries in use */
spinlock_t s_lock ____cacheline_aligned_in_smp;
u32 s_flags;
@@ -343,6 +370,8 @@ struct rvt_qp {
struct rvt_sge_state s_ack_rdma_sge;
struct timer_list s_timer;
+ atomic_t local_ops_pending; /* number of fast_reg/local_inv reqs */
+
/*
* This sge list MUST be last. Do not add anything below here.
*/
@@ -436,6 +465,49 @@ static inline struct rvt_rwqe *rvt_get_rwqe_ptr(struct rvt_rq *rq, unsigned n)
rq->max_sge * sizeof(struct ib_sge)) * n);
}
+/**
+ * rvt_qp_wqe_reserve - reserve operation
+ * @qp - the rvt qp
+ * @wqe - the send wqe
+ *
+ * This routine used in post send to record
+ * a wqe relative reserved operation use.
+ */
+static inline void rvt_qp_wqe_reserve(
+ struct rvt_qp *qp,
+ struct rvt_swqe *wqe)
+{
+ wqe->wr.send_flags |= RVT_SEND_RESERVE_USED;
+ atomic_inc(&qp->s_reserved_used);
+}
+
+/**
+ * rvt_qp_wqe_unreserve - clean reserved operation
+ * @qp - the rvt qp
+ * @wqe - the send wqe
+ *
+ * This decrements the reserve use count.
+ *
+ * This call MUST precede the change to
+ * s_last to insure that post send sees a stable
+ * s_avail.
+ *
+ * An smp_mp__after_atomic() is used to insure
+ * the compiler does not juggle the order of the s_last
+ * ring index and the decrementing of s_reserved_used.
+ */
+static inline void rvt_qp_wqe_unreserve(
+ struct rvt_qp *qp,
+ struct rvt_swqe *wqe)
+{
+ if (unlikely(wqe->wr.send_flags & RVT_SEND_RESERVE_USED)) {
+ wqe->wr.send_flags &= ~RVT_SEND_RESERVE_USED;
+ atomic_dec(&qp->s_reserved_used);
+ /* insure no compiler re-order up to s_last change */
+ smp_mb__after_atomic();
+ }
+}
+
extern const int ib_rvt_state_ops[];
struct rvt_dev_info;
diff --git a/drivers/scsi/ibmvscsi/viosrp.h b/include/scsi/viosrp.h
index c1ab8a4c3161..974e07bd8e59 100644
--- a/drivers/scsi/ibmvscsi/viosrp.h
+++ b/include/scsi/viosrp.h
@@ -15,11 +15,6 @@
/* 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 contains structures and definitions for IBM RPA (RS/6000 */
/* platform architecture) implementation of the SRP (SCSI RDMA Protocol) */
/* standard. SRP is used on IBM iSeries and pSeries platforms to send SCSI */
@@ -93,7 +88,7 @@ struct viosrp_crq {
};
/* MADs are Management requests above and beyond the IUs defined in the SRP
- * standard.
+ * standard.
*/
enum viosrp_mad_types {
VIOSRP_EMPTY_IU_TYPE = 0x01,
@@ -131,7 +126,7 @@ enum viosrp_capability_flag {
CAP_LIST_DATA = 0x08,
};
-/*
+/*
* Common MAD header
*/
struct mad_common {
@@ -146,7 +141,7 @@ struct mad_common {
* client to the server. There is no way for the server to send
* an asynchronous message back to the client. The Empty IU is used
* to hang out a meaningless request to the server so that it can respond
- * asynchrouously with something like a SCSI AER
+ * asynchrouously with something like a SCSI AER
*/
struct viosrp_empty_iu {
struct mad_common common;
@@ -189,7 +184,7 @@ struct mad_migration_cap {
__be32 ecl;
};
-struct capabilities{
+struct capabilities {
__be32 flags;
char name[SRP_MAX_LOC_LEN];
char loc[SRP_MAX_LOC_LEN];
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index d8ab5101fad5..f6f3bc52c1ac 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -95,6 +95,6 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
bool target_sense_desc_format(struct se_device *dev);
sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
- struct request_queue *q, int block_size);
+ struct request_queue *q);
#endif /* TARGET_CORE_BACKEND_H */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index b316b44d03f3..fb8e3b6febdf 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -142,6 +142,7 @@ enum se_cmd_flags_table {
SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
SCF_ACK_KREF = 0x00400000,
SCF_USE_CPUID = 0x00800000,
+ SCF_TASK_ATTR_SET = 0x01000000,
};
/*
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index de44462a7680..5cd6faa6e0d1 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -163,7 +163,6 @@ int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
void core_tmr_release_req(struct se_tmr_req *);
int transport_generic_handle_tmr(struct se_cmd *);
void transport_generic_request_failure(struct se_cmd *, sense_reason_t);
-void __target_execute_cmd(struct se_cmd *);
int transport_lookup_tmr_lun(struct se_cmd *, u64);
void core_allocate_nexus_loss_ua(struct se_node_acl *acl);
diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h
index 65673d8b81ac..d336b890e31f 100644
--- a/include/trace/events/bcache.h
+++ b/include/trace/events/bcache.h
@@ -27,7 +27,7 @@ DECLARE_EVENT_CLASS(bcache_request,
__entry->sector = bio->bi_iter.bi_sector;
__entry->orig_sector = bio->bi_iter.bi_sector - 16;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
),
@@ -102,7 +102,7 @@ DECLARE_EVENT_CLASS(bcache_bio,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
),
@@ -138,7 +138,7 @@ TRACE_EVENT(bcache_read,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
__entry->cache_hit = hit;
__entry->bypass = bypass;
@@ -170,7 +170,7 @@ TRACE_EVENT(bcache_write,
__entry->inode = inode;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio->bi_iter.bi_size >> 9;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
__entry->writeback = writeback;
__entry->bypass = bypass;
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 5a2a7592068f..8f3a163b8166 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -274,7 +274,7 @@ TRACE_EVENT(block_bio_bounce,
bio->bi_bdev->bd_dev : 0;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -313,7 +313,7 @@ TRACE_EVENT(block_bio_complete,
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
__entry->error = error;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
),
@@ -341,7 +341,7 @@ DECLARE_EVENT_CLASS(block_bio_merge,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -409,7 +409,7 @@ TRACE_EVENT(block_bio_queue,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->nr_sector = bio_sectors(bio);
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -439,7 +439,7 @@ DECLARE_EVENT_CLASS(block_get_rq,
__entry->sector = bio ? bio->bi_iter.bi_sector : 0;
__entry->nr_sector = bio ? bio_sectors(bio) : 0;
blk_fill_rwbs(__entry->rwbs, bio ? bio_op(bio) : 0,
- bio ? bio->bi_rw : 0, __entry->nr_sector);
+ bio ? bio->bi_opf : 0, __entry->nr_sector);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -573,7 +573,7 @@ TRACE_EVENT(block_split,
__entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_iter.bi_sector;
__entry->new_sector = new_sector;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
),
@@ -617,7 +617,7 @@ TRACE_EVENT(block_bio_remap,
__entry->nr_sector = bio_sectors(bio);
__entry->old_dev = dev;
__entry->old_sector = from;
- blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw,
+ blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_opf,
bio->bi_iter.bi_size);
),
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index 5b81ef304388..e030d6f6c19a 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -66,6 +66,21 @@ struct btrfs_qgroup_extent_record;
{ BTRFS_BLOCK_GROUP_RAID6, "RAID6"}
#define BTRFS_UUID_SIZE 16
+#define TP_STRUCT__entry_fsid __array(u8, fsid, BTRFS_UUID_SIZE)
+
+#define TP_fast_assign_fsid(fs_info) \
+ memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE)
+
+#define TP_STRUCT__entry_btrfs(args...) \
+ TP_STRUCT__entry( \
+ TP_STRUCT__entry_fsid \
+ args)
+#define TP_fast_assign_btrfs(fs_info, args...) \
+ TP_fast_assign( \
+ TP_fast_assign_fsid(fs_info); \
+ args)
+#define TP_printk_btrfs(fmt, args...) \
+ TP_printk("%pU: " fmt, __entry->fsid, args)
TRACE_EVENT(btrfs_transaction_commit,
@@ -73,17 +88,17 @@ TRACE_EVENT(btrfs_transaction_commit,
TP_ARGS(root),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, generation )
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(root->fs_info,
__entry->generation = root->fs_info->generation;
__entry->root_objectid = root->root_key.objectid;
),
- TP_printk("root = %llu(%s), gen = %llu",
+ TP_printk_btrfs("root = %llu(%s), gen = %llu",
show_root_type(__entry->root_objectid),
(unsigned long long)__entry->generation)
);
@@ -94,7 +109,7 @@ DECLARE_EVENT_CLASS(btrfs__inode,
TP_ARGS(inode),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( ino_t, ino )
__field( blkcnt_t, blocks )
__field( u64, disk_i_size )
@@ -104,7 +119,7 @@ DECLARE_EVENT_CLASS(btrfs__inode,
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
__entry->ino = inode->i_ino;
__entry->blocks = inode->i_blocks;
__entry->disk_i_size = BTRFS_I(inode)->disk_i_size;
@@ -115,7 +130,7 @@ DECLARE_EVENT_CLASS(btrfs__inode,
BTRFS_I(inode)->root->root_key.objectid;
),
- TP_printk("root = %llu(%s), gen = %llu, ino = %lu, blocks = %llu, "
+ TP_printk_btrfs("root = %llu(%s), gen = %llu, ino = %lu, blocks = %llu, "
"disk_i_size = %llu, last_trans = %llu, logged_trans = %llu",
show_root_type(__entry->root_objectid),
(unsigned long long)__entry->generation,
@@ -175,7 +190,7 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
TP_CONDITION(map),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, root_objectid )
__field( u64, start )
__field( u64, len )
@@ -187,7 +202,7 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
__field( unsigned int, compress_type )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(root->fs_info,
__entry->root_objectid = root->root_key.objectid;
__entry->start = map->start;
__entry->len = map->len;
@@ -199,7 +214,7 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
__entry->compress_type = map->compress_type;
),
- TP_printk("root = %llu(%s), start = %llu, len = %llu, "
+ TP_printk_btrfs("root = %llu(%s), start = %llu, len = %llu, "
"orig_start = %llu, block_start = %llu(%s), "
"block_len = %llu, flags = %s, refs = %u, "
"compress_type = %u",
@@ -233,7 +248,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
TP_ARGS(inode, ordered),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( ino_t, ino )
__field( u64, file_offset )
__field( u64, start )
@@ -246,7 +261,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
__entry->ino = inode->i_ino;
__entry->file_offset = ordered->file_offset;
__entry->start = ordered->start;
@@ -260,7 +275,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
BTRFS_I(inode)->root->root_key.objectid;
),
- TP_printk("root = %llu(%s), ino = %llu, file_offset = %llu, "
+ TP_printk_btrfs("root = %llu(%s), ino = %llu, file_offset = %llu, "
"start = %llu, len = %llu, disk_len = %llu, "
"bytes_left = %llu, flags = %s, compress_type = %d, "
"refs = %d",
@@ -310,7 +325,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
TP_ARGS(page, inode, wbc),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( ino_t, ino )
__field( pgoff_t, index )
__field( long, nr_to_write )
@@ -324,7 +339,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
__entry->ino = inode->i_ino;
__entry->index = page->index;
__entry->nr_to_write = wbc->nr_to_write;
@@ -339,7 +354,7 @@ DECLARE_EVENT_CLASS(btrfs__writepage,
BTRFS_I(inode)->root->root_key.objectid;
),
- TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, "
+ TP_printk_btrfs("root = %llu(%s), ino = %lu, page_index = %lu, "
"nr_to_write = %ld, pages_skipped = %ld, range_start = %llu, "
"range_end = %llu, for_kupdate = %d, "
"for_reclaim = %d, range_cyclic = %d, writeback_index = %lu",
@@ -366,7 +381,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
TP_ARGS(page, start, end, uptodate),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( ino_t, ino )
__field( pgoff_t, index )
__field( u64, start )
@@ -375,7 +390,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(page->mapping->host->i_sb),
__entry->ino = page->mapping->host->i_ino;
__entry->index = page->index;
__entry->start = start;
@@ -385,7 +400,7 @@ TRACE_EVENT(btrfs_writepage_end_io_hook,
BTRFS_I(page->mapping->host)->root->root_key.objectid;
),
- TP_printk("root = %llu(%s), ino = %lu, page_index = %lu, start = %llu, "
+ TP_printk_btrfs("root = %llu(%s), ino = %lu, page_index = %lu, start = %llu, "
"end = %llu, uptodate = %d",
show_root_type(__entry->root_objectid),
(unsigned long)__entry->ino, (unsigned long)__entry->index,
@@ -399,7 +414,7 @@ TRACE_EVENT(btrfs_sync_file,
TP_ARGS(file, datasync),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( ino_t, ino )
__field( ino_t, parent )
__field( int, datasync )
@@ -410,6 +425,7 @@ TRACE_EVENT(btrfs_sync_file,
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = d_inode(dentry);
+ TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb));
__entry->ino = inode->i_ino;
__entry->parent = d_inode(dentry->d_parent)->i_ino;
__entry->datasync = datasync;
@@ -417,7 +433,7 @@ TRACE_EVENT(btrfs_sync_file,
BTRFS_I(inode)->root->root_key.objectid;
),
- TP_printk("root = %llu(%s), ino = %ld, parent = %ld, datasync = %d",
+ TP_printk_btrfs("root = %llu(%s), ino = %ld, parent = %ld, datasync = %d",
show_root_type(__entry->root_objectid),
(unsigned long)__entry->ino, (unsigned long)__entry->parent,
__entry->datasync)
@@ -425,19 +441,19 @@ TRACE_EVENT(btrfs_sync_file,
TRACE_EVENT(btrfs_sync_fs,
- TP_PROTO(int wait),
+ TP_PROTO(struct btrfs_fs_info *fs_info, int wait),
- TP_ARGS(wait),
+ TP_ARGS(fs_info, wait),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( int, wait )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->wait = wait;
),
- TP_printk("wait = %d", __entry->wait)
+ TP_printk_btrfs("wait = %d", __entry->wait)
);
TRACE_EVENT(btrfs_add_block_group,
@@ -490,13 +506,14 @@ TRACE_EVENT(btrfs_add_block_group,
DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action),
+ TP_ARGS(fs_info, ref, full_ref, action),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bytenr )
__field( u64, num_bytes )
__field( int, action )
@@ -507,7 +524,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
__field( u64, seq )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->bytenr = ref->bytenr;
__entry->num_bytes = ref->num_bytes;
__entry->action = action;
@@ -518,7 +535,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
__entry->seq = ref->seq;
),
- TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
+ TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, "
"parent = %llu(%s), ref_root = %llu(%s), level = %d, "
"type = %s, seq = %llu",
(unsigned long long)__entry->bytenr,
@@ -532,31 +549,34 @@ DECLARE_EVENT_CLASS(btrfs_delayed_tree_ref,
DEFINE_EVENT(btrfs_delayed_tree_ref, add_delayed_tree_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action)
+ TP_ARGS(fs_info, ref, full_ref, action)
);
DEFINE_EVENT(btrfs_delayed_tree_ref, run_delayed_tree_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_tree_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action)
+ TP_ARGS(fs_info, ref, full_ref, action)
);
DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action),
+ TP_ARGS(fs_info, ref, full_ref, action),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bytenr )
__field( u64, num_bytes )
__field( int, action )
@@ -568,7 +588,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
__field( u64, seq )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->bytenr = ref->bytenr;
__entry->num_bytes = ref->num_bytes;
__entry->action = action;
@@ -580,7 +600,7 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
__entry->seq = ref->seq;
),
- TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, "
+ TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, "
"parent = %llu(%s), ref_root = %llu(%s), owner = %llu, "
"offset = %llu, type = %s, seq = %llu",
(unsigned long long)__entry->bytenr,
@@ -596,45 +616,48 @@ DECLARE_EVENT_CLASS(btrfs_delayed_data_ref,
DEFINE_EVENT(btrfs_delayed_data_ref, add_delayed_data_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action)
+ TP_ARGS(fs_info, ref, full_ref, action)
);
DEFINE_EVENT(btrfs_delayed_data_ref, run_delayed_data_ref,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_data_ref *full_ref,
int action),
- TP_ARGS(ref, full_ref, action)
+ TP_ARGS(fs_info, ref, full_ref, action)
);
DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref,
int action),
- TP_ARGS(ref, head_ref, action),
+ TP_ARGS(fs_info, ref, head_ref, action),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bytenr )
__field( u64, num_bytes )
__field( int, action )
__field( int, is_data )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->bytenr = ref->bytenr;
__entry->num_bytes = ref->num_bytes;
__entry->action = action;
__entry->is_data = head_ref->is_data;
),
- TP_printk("bytenr = %llu, num_bytes = %llu, action = %s, is_data = %d",
+ TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, action = %s, is_data = %d",
(unsigned long long)__entry->bytenr,
(unsigned long long)__entry->num_bytes,
show_ref_action(__entry->action),
@@ -643,20 +666,22 @@ DECLARE_EVENT_CLASS(btrfs_delayed_ref_head,
DEFINE_EVENT(btrfs_delayed_ref_head, add_delayed_ref_head,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref,
int action),
- TP_ARGS(ref, head_ref, action)
+ TP_ARGS(fs_info, ref, head_ref, action)
);
DEFINE_EVENT(btrfs_delayed_ref_head, run_delayed_ref_head,
- TP_PROTO(struct btrfs_delayed_ref_node *ref,
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_delayed_ref_node *ref,
struct btrfs_delayed_ref_head *head_ref,
int action),
- TP_ARGS(ref, head_ref, action)
+ TP_ARGS(fs_info, ref, head_ref, action)
);
#define show_chunk_type(type) \
@@ -678,7 +703,7 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
TP_ARGS(root, map, offset, size),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( int, num_stripes )
__field( u64, type )
__field( int, sub_stripes )
@@ -687,7 +712,7 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
__field( u64, root_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(root->fs_info,
__entry->num_stripes = map->num_stripes;
__entry->type = map->type;
__entry->sub_stripes = map->sub_stripes;
@@ -696,7 +721,7 @@ DECLARE_EVENT_CLASS(btrfs__chunk,
__entry->root_objectid = root->root_key.objectid;
),
- TP_printk("root = %llu(%s), offset = %llu, size = %llu, "
+ TP_printk_btrfs("root = %llu(%s), offset = %llu, size = %llu, "
"num_stripes = %d, sub_stripes = %d, type = %s",
show_root_type(__entry->root_objectid),
(unsigned long long)__entry->offset,
@@ -728,7 +753,7 @@ TRACE_EVENT(btrfs_cow_block,
TP_ARGS(root, buf, cow),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, root_objectid )
__field( u64, buf_start )
__field( int, refs )
@@ -737,7 +762,7 @@ TRACE_EVENT(btrfs_cow_block,
__field( int, cow_level )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(root->fs_info,
__entry->root_objectid = root->root_key.objectid;
__entry->buf_start = buf->start;
__entry->refs = atomic_read(&buf->refs);
@@ -746,7 +771,7 @@ TRACE_EVENT(btrfs_cow_block,
__entry->cow_level = btrfs_header_level(cow);
),
- TP_printk("root = %llu(%s), refs = %d, orig_buf = %llu "
+ TP_printk_btrfs("root = %llu(%s), refs = %d, orig_buf = %llu "
"(orig_level = %d), cow_buf = %llu (cow_level = %d)",
show_root_type(__entry->root_objectid),
__entry->refs,
@@ -763,25 +788,23 @@ TRACE_EVENT(btrfs_space_reservation,
TP_ARGS(fs_info, type, val, bytes, reserve),
- TP_STRUCT__entry(
- __array( u8, fsid, BTRFS_UUID_SIZE )
+ TP_STRUCT__entry_btrfs(
__string( type, type )
__field( u64, val )
__field( u64, bytes )
__field( int, reserve )
),
- TP_fast_assign(
- memcpy(__entry->fsid, fs_info->fsid, BTRFS_UUID_SIZE);
+ TP_fast_assign_btrfs(fs_info,
__assign_str(type, type);
__entry->val = val;
__entry->bytes = bytes;
__entry->reserve = reserve;
),
- TP_printk("%pU: %s: %Lu %s %Lu", __entry->fsid, __get_str(type),
- __entry->val, __entry->reserve ? "reserve" : "release",
- __entry->bytes)
+ TP_printk_btrfs("%s: %Lu %s %Lu", __get_str(type), __entry->val,
+ __entry->reserve ? "reserve" : "release",
+ __entry->bytes)
);
#define show_flush_action(action) \
@@ -872,22 +895,19 @@ DECLARE_EVENT_CLASS(btrfs__reserved_extent,
TP_ARGS(root, start, len),
- TP_STRUCT__entry(
- __array( u8, fsid, BTRFS_UUID_SIZE )
- __field( u64, root_objectid )
- __field( u64, start )
- __field( u64, len )
+ TP_STRUCT__entry_btrfs(
+ __field( u64, root_objectid )
+ __field( u64, start )
+ __field( u64, len )
),
- TP_fast_assign(
- memcpy(__entry->fsid, root->fs_info->fsid, BTRFS_UUID_SIZE);
+ TP_fast_assign_btrfs(root->fs_info,
__entry->root_objectid = root->root_key.objectid;
__entry->start = start;
__entry->len = len;
),
- TP_printk("%pU: root = %llu(%s), start = %llu, len = %llu",
- __entry->fsid,
+ TP_printk_btrfs("root = %llu(%s), start = %llu, len = %llu",
show_root_type(__entry->root_objectid),
(unsigned long long)__entry->start,
(unsigned long long)__entry->len)
@@ -914,21 +934,21 @@ TRACE_EVENT(find_free_extent,
TP_ARGS(root, num_bytes, empty_size, data),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, root_objectid )
__field( u64, num_bytes )
__field( u64, empty_size )
__field( u64, data )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(root->fs_info,
__entry->root_objectid = root->root_key.objectid;
__entry->num_bytes = num_bytes;
__entry->empty_size = empty_size;
__entry->data = data;
),
- TP_printk("root = %Lu(%s), len = %Lu, empty_size = %Lu, "
+ TP_printk_btrfs("root = %Lu(%s), len = %Lu, empty_size = %Lu, "
"flags = %Lu(%s)", show_root_type(__entry->root_objectid),
__entry->num_bytes, __entry->empty_size, __entry->data,
__print_flags((unsigned long)__entry->data, "|",
@@ -943,8 +963,7 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
TP_ARGS(root, block_group, start, len),
- TP_STRUCT__entry(
- __array( u8, fsid, BTRFS_UUID_SIZE )
+ TP_STRUCT__entry_btrfs(
__field( u64, root_objectid )
__field( u64, bg_objectid )
__field( u64, flags )
@@ -952,8 +971,7 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
__field( u64, len )
),
- TP_fast_assign(
- memcpy(__entry->fsid, root->fs_info->fsid, BTRFS_UUID_SIZE);
+ TP_fast_assign_btrfs(root->fs_info,
__entry->root_objectid = root->root_key.objectid;
__entry->bg_objectid = block_group->key.objectid;
__entry->flags = block_group->flags;
@@ -961,8 +979,8 @@ DECLARE_EVENT_CLASS(btrfs__reserve_extent,
__entry->len = len;
),
- TP_printk("%pU: root = %Lu(%s), block_group = %Lu, flags = %Lu(%s), "
- "start = %Lu, len = %Lu", __entry->fsid,
+ TP_printk_btrfs("root = %Lu(%s), block_group = %Lu, flags = %Lu(%s), "
+ "start = %Lu, len = %Lu",
show_root_type(__entry->root_objectid), __entry->bg_objectid,
__entry->flags, __print_flags((unsigned long)__entry->flags,
"|", BTRFS_GROUP_FLAGS),
@@ -994,7 +1012,7 @@ TRACE_EVENT(btrfs_find_cluster,
TP_ARGS(block_group, start, bytes, empty_size, min_bytes),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bg_objectid )
__field( u64, flags )
__field( u64, start )
@@ -1003,7 +1021,7 @@ TRACE_EVENT(btrfs_find_cluster,
__field( u64, min_bytes )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(block_group->fs_info,
__entry->bg_objectid = block_group->key.objectid;
__entry->flags = block_group->flags;
__entry->start = start;
@@ -1012,7 +1030,7 @@ TRACE_EVENT(btrfs_find_cluster,
__entry->min_bytes = min_bytes;
),
- TP_printk("block_group = %Lu, flags = %Lu(%s), start = %Lu, len = %Lu,"
+ TP_printk_btrfs("block_group = %Lu, flags = %Lu(%s), start = %Lu, len = %Lu,"
" empty_size = %Lu, min_bytes = %Lu", __entry->bg_objectid,
__entry->flags,
__print_flags((unsigned long)__entry->flags, "|",
@@ -1026,15 +1044,15 @@ TRACE_EVENT(btrfs_failed_cluster_setup,
TP_ARGS(block_group),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bg_objectid )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(block_group->fs_info,
__entry->bg_objectid = block_group->key.objectid;
),
- TP_printk("block_group = %Lu", __entry->bg_objectid)
+ TP_printk_btrfs("block_group = %Lu", __entry->bg_objectid)
);
TRACE_EVENT(btrfs_setup_cluster,
@@ -1044,7 +1062,7 @@ TRACE_EVENT(btrfs_setup_cluster,
TP_ARGS(block_group, cluster, size, bitmap),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bg_objectid )
__field( u64, flags )
__field( u64, start )
@@ -1053,7 +1071,7 @@ TRACE_EVENT(btrfs_setup_cluster,
__field( int, bitmap )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(block_group->fs_info,
__entry->bg_objectid = block_group->key.objectid;
__entry->flags = block_group->flags;
__entry->start = cluster->window_start;
@@ -1062,7 +1080,7 @@ TRACE_EVENT(btrfs_setup_cluster,
__entry->bitmap = bitmap;
),
- TP_printk("block_group = %Lu, flags = %Lu(%s), window_start = %Lu, "
+ TP_printk_btrfs("block_group = %Lu, flags = %Lu(%s), window_start = %Lu, "
"size = %Lu, max_size = %Lu, bitmap = %d",
__entry->bg_objectid,
__entry->flags,
@@ -1120,7 +1138,7 @@ DECLARE_EVENT_CLASS(btrfs__work,
TP_ARGS(work),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( void *, work )
__field( void *, wq )
__field( void *, func )
@@ -1129,7 +1147,7 @@ DECLARE_EVENT_CLASS(btrfs__work,
__field( void *, normal_work )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_work_owner(work),
__entry->work = work;
__entry->wq = work->wq;
__entry->func = work->func;
@@ -1138,7 +1156,7 @@ DECLARE_EVENT_CLASS(btrfs__work,
__entry->normal_work = &work->normal_work;
),
- TP_printk("work=%p (normal_work=%p), wq=%p, func=%pf, ordered_func=%p,"
+ TP_printk_btrfs("work=%p (normal_work=%p), wq=%p, func=%pf, ordered_func=%p,"
" ordered_free=%p",
__entry->work, __entry->normal_work, __entry->wq,
__entry->func, __entry->ordered_func, __entry->ordered_free)
@@ -1151,15 +1169,15 @@ DECLARE_EVENT_CLASS(btrfs__work__done,
TP_ARGS(work),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( void *, work )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_work_owner(work),
__entry->work = work;
),
- TP_printk("work->%p", __entry->work)
+ TP_printk_btrfs("work->%p", __entry->work)
);
DEFINE_EVENT(btrfs__work, btrfs_work_queued,
@@ -1196,19 +1214,19 @@ DECLARE_EVENT_CLASS(btrfs__workqueue,
TP_ARGS(wq, name, high),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( void *, wq )
__string( name, name )
__field( int , high )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_workqueue_owner(wq),
__entry->wq = wq;
__assign_str(name, name);
__entry->high = high;
),
- TP_printk("name=%s%s, wq=%p", __get_str(name),
+ TP_printk_btrfs("name=%s%s, wq=%p", __get_str(name),
__print_flags(__entry->high, "",
{(WQ_HIGHPRI), "-high"}),
__entry->wq)
@@ -1227,15 +1245,15 @@ DECLARE_EVENT_CLASS(btrfs__workqueue_done,
TP_ARGS(wq),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( void *, wq )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_workqueue_owner(wq),
__entry->wq = wq;
),
- TP_printk("wq=%p", __entry->wq)
+ TP_printk_btrfs("wq=%p", __entry->wq)
);
DEFINE_EVENT(btrfs__workqueue_done, btrfs_workqueue_destroy,
@@ -1251,19 +1269,19 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_data_map,
TP_ARGS(inode, free_reserved),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, rootid )
__field( unsigned long, ino )
__field( u64, free_reserved )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
__entry->rootid = BTRFS_I(inode)->root->objectid;
__entry->ino = inode->i_ino;
__entry->free_reserved = free_reserved;
),
- TP_printk("rootid=%llu, ino=%lu, free_reserved=%llu",
+ TP_printk_btrfs("rootid=%llu, ino=%lu, free_reserved=%llu",
__entry->rootid, __entry->ino, __entry->free_reserved)
);
@@ -1292,7 +1310,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
TP_ARGS(inode, start, len, reserved, op),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, rootid )
__field( unsigned long, ino )
__field( u64, start )
@@ -1301,7 +1319,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
__field( int, op )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(btrfs_sb(inode->i_sb),
__entry->rootid = BTRFS_I(inode)->root->objectid;
__entry->ino = inode->i_ino;
__entry->start = start;
@@ -1310,7 +1328,7 @@ DECLARE_EVENT_CLASS(btrfs__qgroup_rsv_data,
__entry->op = op;
),
- TP_printk("root=%llu, ino=%lu, start=%llu, len=%llu, reserved=%llu, op=%s",
+ TP_printk_btrfs("root=%llu, ino=%lu, start=%llu, len=%llu, reserved=%llu, op=%s",
__entry->rootid, __entry->ino, __entry->start, __entry->len,
__entry->reserved,
__print_flags((unsigned long)__entry->op, "",
@@ -1334,86 +1352,90 @@ DEFINE_EVENT(btrfs__qgroup_rsv_data, btrfs_qgroup_release_data,
DECLARE_EVENT_CLASS(btrfs__qgroup_delayed_ref,
- TP_PROTO(u64 ref_root, u64 reserved),
+ TP_PROTO(struct btrfs_fs_info *fs_info, u64 ref_root, u64 reserved),
- TP_ARGS(ref_root, reserved),
+ TP_ARGS(fs_info, ref_root, reserved),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, ref_root )
__field( u64, reserved )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->ref_root = ref_root;
__entry->reserved = reserved;
),
- TP_printk("root=%llu, reserved=%llu, op=free",
+ TP_printk_btrfs("root=%llu, reserved=%llu, op=free",
__entry->ref_root, __entry->reserved)
);
DEFINE_EVENT(btrfs__qgroup_delayed_ref, btrfs_qgroup_free_delayed_ref,
- TP_PROTO(u64 ref_root, u64 reserved),
+ TP_PROTO(struct btrfs_fs_info *fs_info, u64 ref_root, u64 reserved),
- TP_ARGS(ref_root, reserved)
+ TP_ARGS(fs_info, ref_root, reserved)
);
DECLARE_EVENT_CLASS(btrfs_qgroup_extent,
- TP_PROTO(struct btrfs_qgroup_extent_record *rec),
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_qgroup_extent_record *rec),
- TP_ARGS(rec),
+ TP_ARGS(fs_info, rec),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bytenr )
__field( u64, num_bytes )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->bytenr = rec->bytenr,
__entry->num_bytes = rec->num_bytes;
),
- TP_printk("bytenr = %llu, num_bytes = %llu",
+ TP_printk_btrfs("bytenr = %llu, num_bytes = %llu",
(unsigned long long)__entry->bytenr,
(unsigned long long)__entry->num_bytes)
);
DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_account_extents,
- TP_PROTO(struct btrfs_qgroup_extent_record *rec),
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_qgroup_extent_record *rec),
- TP_ARGS(rec)
+ TP_ARGS(fs_info, rec)
);
DEFINE_EVENT(btrfs_qgroup_extent, btrfs_qgroup_insert_dirty_extent,
- TP_PROTO(struct btrfs_qgroup_extent_record *rec),
+ TP_PROTO(struct btrfs_fs_info *fs_info,
+ struct btrfs_qgroup_extent_record *rec),
- TP_ARGS(rec)
+ TP_ARGS(fs_info, rec)
);
TRACE_EVENT(btrfs_qgroup_account_extent,
- TP_PROTO(u64 bytenr, u64 num_bytes, u64 nr_old_roots, u64 nr_new_roots),
+ TP_PROTO(struct btrfs_fs_info *fs_info, u64 bytenr,
+ u64 num_bytes, u64 nr_old_roots, u64 nr_new_roots),
- TP_ARGS(bytenr, num_bytes, nr_old_roots, nr_new_roots),
+ TP_ARGS(fs_info, bytenr, num_bytes, nr_old_roots, nr_new_roots),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, bytenr )
__field( u64, num_bytes )
__field( u64, nr_old_roots )
__field( u64, nr_new_roots )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->bytenr = bytenr;
__entry->num_bytes = num_bytes;
__entry->nr_old_roots = nr_old_roots;
__entry->nr_new_roots = nr_new_roots;
),
- TP_printk("bytenr = %llu, num_bytes = %llu, nr_old_roots = %llu, "
+ TP_printk_btrfs("bytenr = %llu, num_bytes = %llu, nr_old_roots = %llu, "
"nr_new_roots = %llu",
__entry->bytenr,
__entry->num_bytes,
@@ -1423,23 +1445,24 @@ TRACE_EVENT(btrfs_qgroup_account_extent,
TRACE_EVENT(qgroup_update_counters,
- TP_PROTO(u64 qgid, u64 cur_old_count, u64 cur_new_count),
+ TP_PROTO(struct btrfs_fs_info *fs_info, u64 qgid,
+ u64 cur_old_count, u64 cur_new_count),
- TP_ARGS(qgid, cur_old_count, cur_new_count),
+ TP_ARGS(fs_info, qgid, cur_old_count, cur_new_count),
- TP_STRUCT__entry(
+ TP_STRUCT__entry_btrfs(
__field( u64, qgid )
__field( u64, cur_old_count )
__field( u64, cur_new_count )
),
- TP_fast_assign(
+ TP_fast_assign_btrfs(fs_info,
__entry->qgid = qgid;
__entry->cur_old_count = cur_old_count;
__entry->cur_new_count = cur_new_count;
),
- TP_printk("qgid = %llu, cur_old_count = %llu, cur_new_count = %llu",
+ TP_printk_btrfs("qgid = %llu, cur_old_count = %llu, cur_new_count = %llu",
__entry->qgid,
__entry->cur_old_count,
__entry->cur_new_count)
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index 003dca933803..8a707f8a41c3 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -473,6 +473,39 @@ TRACE_EVENT(svc_recv,
show_rqstp_flags(__entry->flags))
);
+DECLARE_EVENT_CLASS(svc_rqst_event,
+
+ TP_PROTO(struct svc_rqst *rqst),
+
+ TP_ARGS(rqst),
+
+ TP_STRUCT__entry(
+ __field(__be32, xid)
+ __field(unsigned long, flags)
+ __dynamic_array(unsigned char, addr, rqst->rq_addrlen)
+ ),
+
+ TP_fast_assign(
+ __entry->xid = rqst->rq_xid;
+ __entry->flags = rqst->rq_flags;
+ memcpy(__get_dynamic_array(addr),
+ &rqst->rq_addr, rqst->rq_addrlen);
+ ),
+
+ TP_printk("addr=%pIScp rq_xid=0x%x flags=%s",
+ (struct sockaddr *)__get_dynamic_array(addr),
+ be32_to_cpu(__entry->xid),
+ show_rqstp_flags(__entry->flags))
+);
+
+DEFINE_EVENT(svc_rqst_event, svc_defer,
+ TP_PROTO(struct svc_rqst *rqst),
+ TP_ARGS(rqst));
+
+DEFINE_EVENT(svc_rqst_event, svc_drop,
+ TP_PROTO(struct svc_rqst *rqst),
+ TP_ARGS(rqst));
+
DECLARE_EVENT_CLASS(svc_rqst_status,
TP_PROTO(struct svc_rqst *rqst, int status),
@@ -529,45 +562,67 @@ TRACE_EVENT(svc_xprt_do_enqueue,
TP_STRUCT__entry(
__field(struct svc_xprt *, xprt)
- __field_struct(struct sockaddr_storage, ss)
__field(int, pid)
__field(unsigned long, flags)
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
+ xprt->xpt_remotelen : 0)
),
TP_fast_assign(
__entry->xprt = xprt;
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
__entry->pid = rqst? rqst->rq_task->pid : 0;
- __entry->flags = xprt ? xprt->xpt_flags : 0;
+ if (xprt) {
+ memcpy(__get_dynamic_array(addr),
+ &xprt->xpt_remote,
+ xprt->xpt_remotelen);
+ __entry->flags = xprt->xpt_flags;
+ } else
+ __entry->flags = 0;
),
TP_printk("xprt=0x%p addr=%pIScp pid=%d flags=%s", __entry->xprt,
- (struct sockaddr *)&__entry->ss,
+ __get_dynamic_array_len(addr) != 0 ?
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
__entry->pid, show_svc_xprt_flags(__entry->flags))
);
-TRACE_EVENT(svc_xprt_dequeue,
+DECLARE_EVENT_CLASS(svc_xprt_event,
TP_PROTO(struct svc_xprt *xprt),
TP_ARGS(xprt),
TP_STRUCT__entry(
__field(struct svc_xprt *, xprt)
- __field_struct(struct sockaddr_storage, ss)
__field(unsigned long, flags)
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
+ xprt->xpt_remotelen : 0)
),
TP_fast_assign(
- __entry->xprt = xprt,
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
- __entry->flags = xprt ? xprt->xpt_flags : 0;
+ __entry->xprt = xprt;
+ if (xprt) {
+ memcpy(__get_dynamic_array(addr),
+ &xprt->xpt_remote,
+ xprt->xpt_remotelen);
+ __entry->flags = xprt->xpt_flags;
+ } else
+ __entry->flags = 0;
),
TP_printk("xprt=0x%p addr=%pIScp flags=%s", __entry->xprt,
- (struct sockaddr *)&__entry->ss,
+ __get_dynamic_array_len(addr) != 0 ?
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
show_svc_xprt_flags(__entry->flags))
);
+DEFINE_EVENT(svc_xprt_event, svc_xprt_dequeue,
+ TP_PROTO(struct svc_xprt *xprt),
+ TP_ARGS(xprt));
+
+DEFINE_EVENT(svc_xprt_event, svc_xprt_no_write_space,
+ TP_PROTO(struct svc_xprt *xprt),
+ TP_ARGS(xprt));
+
TRACE_EVENT(svc_wake_up,
TP_PROTO(int pid),
@@ -592,21 +647,56 @@ TRACE_EVENT(svc_handle_xprt,
TP_STRUCT__entry(
__field(struct svc_xprt *, xprt)
__field(int, len)
- __field_struct(struct sockaddr_storage, ss)
__field(unsigned long, flags)
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
+ xprt->xpt_remotelen : 0)
),
TP_fast_assign(
__entry->xprt = xprt;
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
__entry->len = len;
- __entry->flags = xprt ? xprt->xpt_flags : 0;
+ if (xprt) {
+ memcpy(__get_dynamic_array(addr),
+ &xprt->xpt_remote,
+ xprt->xpt_remotelen);
+ __entry->flags = xprt->xpt_flags;
+ } else
+ __entry->flags = 0;
),
TP_printk("xprt=0x%p addr=%pIScp len=%d flags=%s", __entry->xprt,
- (struct sockaddr *)&__entry->ss,
+ __get_dynamic_array_len(addr) != 0 ?
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
__entry->len, show_svc_xprt_flags(__entry->flags))
);
+
+
+DECLARE_EVENT_CLASS(svc_deferred_event,
+ TP_PROTO(struct svc_deferred_req *dr),
+
+ TP_ARGS(dr),
+
+ TP_STRUCT__entry(
+ __field(__be32, xid)
+ __dynamic_array(unsigned char, addr, dr->addrlen)
+ ),
+
+ TP_fast_assign(
+ __entry->xid = *(__be32 *)(dr->args + (dr->xprt_hlen>>2));
+ memcpy(__get_dynamic_array(addr), &dr->addr, dr->addrlen);
+ ),
+
+ TP_printk("addr=%pIScp xid=0x%x",
+ (struct sockaddr *)__get_dynamic_array(addr),
+ be32_to_cpu(__entry->xid))
+);
+
+DEFINE_EVENT(svc_deferred_event, svc_drop_deferred,
+ TP_PROTO(struct svc_deferred_req *dr),
+ TP_ARGS(dr));
+DEFINE_EVENT(svc_deferred_event, svc_revisit_deferred,
+ TP_PROTO(struct svc_deferred_req *dr),
+ TP_ARGS(dr));
#endif /* _TRACE_SUNRPC_H */
#include <trace/define_trace.h>
diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h
index 51440131d337..28c5da6fdfac 100644
--- a/include/trace/events/timer.h
+++ b/include/trace/events/timer.h
@@ -330,24 +330,32 @@ TRACE_EVENT(itimer_expire,
#ifdef CONFIG_NO_HZ_COMMON
#define TICK_DEP_NAMES \
- tick_dep_name(NONE) \
+ tick_dep_mask_name(NONE) \
tick_dep_name(POSIX_TIMER) \
tick_dep_name(PERF_EVENTS) \
tick_dep_name(SCHED) \
tick_dep_name_end(CLOCK_UNSTABLE)
#undef tick_dep_name
+#undef tick_dep_mask_name
#undef tick_dep_name_end
-#define tick_dep_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
-#define tick_dep_name_end(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
+/* The MASK will convert to their bits and they need to be processed too */
+#define tick_dep_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \
+ TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
+#define tick_dep_name_end(sdep) TRACE_DEFINE_ENUM(TICK_DEP_BIT_##sdep); \
+ TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
+/* NONE only has a mask defined for it */
+#define tick_dep_mask_name(sdep) TRACE_DEFINE_ENUM(TICK_DEP_MASK_##sdep);
TICK_DEP_NAMES
#undef tick_dep_name
+#undef tick_dep_mask_name
#undef tick_dep_name_end
#define tick_dep_name(sdep) { TICK_DEP_MASK_##sdep, #sdep },
+#define tick_dep_mask_name(sdep) { TICK_DEP_MASK_##sdep, #sdep },
#define tick_dep_name_end(sdep) { TICK_DEP_MASK_##sdep, #sdep }
#define show_tick_dep_name(val) \
diff --git a/include/trace/events/vsock_virtio_transport_common.h b/include/trace/events/vsock_virtio_transport_common.h
new file mode 100644
index 000000000000..b7f1d6278280
--- /dev/null
+++ b/include/trace/events/vsock_virtio_transport_common.h
@@ -0,0 +1,144 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM vsock
+
+#if !defined(_TRACE_VSOCK_VIRTIO_TRANSPORT_COMMON_H) || \
+ defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_VSOCK_VIRTIO_TRANSPORT_COMMON_H
+
+#include <linux/tracepoint.h>
+
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_TYPE_STREAM);
+
+#define show_type(val) \
+ __print_symbolic(val, { VIRTIO_VSOCK_TYPE_STREAM, "STREAM" })
+
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_INVALID);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_REQUEST);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_RESPONSE);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_RST);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_SHUTDOWN);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_RW);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_CREDIT_UPDATE);
+TRACE_DEFINE_ENUM(VIRTIO_VSOCK_OP_CREDIT_REQUEST);
+
+#define show_op(val) \
+ __print_symbolic(val, \
+ { VIRTIO_VSOCK_OP_INVALID, "INVALID" }, \
+ { VIRTIO_VSOCK_OP_REQUEST, "REQUEST" }, \
+ { VIRTIO_VSOCK_OP_RESPONSE, "RESPONSE" }, \
+ { VIRTIO_VSOCK_OP_RST, "RST" }, \
+ { VIRTIO_VSOCK_OP_SHUTDOWN, "SHUTDOWN" }, \
+ { VIRTIO_VSOCK_OP_RW, "RW" }, \
+ { VIRTIO_VSOCK_OP_CREDIT_UPDATE, "CREDIT_UPDATE" }, \
+ { VIRTIO_VSOCK_OP_CREDIT_REQUEST, "CREDIT_REQUEST" })
+
+TRACE_EVENT(virtio_transport_alloc_pkt,
+ TP_PROTO(
+ __u32 src_cid, __u32 src_port,
+ __u32 dst_cid, __u32 dst_port,
+ __u32 len,
+ __u16 type,
+ __u16 op,
+ __u32 flags
+ ),
+ TP_ARGS(
+ src_cid, src_port,
+ dst_cid, dst_port,
+ len,
+ type,
+ op,
+ flags
+ ),
+ TP_STRUCT__entry(
+ __field(__u32, src_cid)
+ __field(__u32, src_port)
+ __field(__u32, dst_cid)
+ __field(__u32, dst_port)
+ __field(__u32, len)
+ __field(__u16, type)
+ __field(__u16, op)
+ __field(__u32, flags)
+ ),
+ TP_fast_assign(
+ __entry->src_cid = src_cid;
+ __entry->src_port = src_port;
+ __entry->dst_cid = dst_cid;
+ __entry->dst_port = dst_port;
+ __entry->len = len;
+ __entry->type = type;
+ __entry->op = op;
+ __entry->flags = flags;
+ ),
+ TP_printk("%u:%u -> %u:%u len=%u type=%s op=%s flags=%#x",
+ __entry->src_cid, __entry->src_port,
+ __entry->dst_cid, __entry->dst_port,
+ __entry->len,
+ show_type(__entry->type),
+ show_op(__entry->op),
+ __entry->flags)
+);
+
+TRACE_EVENT(virtio_transport_recv_pkt,
+ TP_PROTO(
+ __u32 src_cid, __u32 src_port,
+ __u32 dst_cid, __u32 dst_port,
+ __u32 len,
+ __u16 type,
+ __u16 op,
+ __u32 flags,
+ __u32 buf_alloc,
+ __u32 fwd_cnt
+ ),
+ TP_ARGS(
+ src_cid, src_port,
+ dst_cid, dst_port,
+ len,
+ type,
+ op,
+ flags,
+ buf_alloc,
+ fwd_cnt
+ ),
+ TP_STRUCT__entry(
+ __field(__u32, src_cid)
+ __field(__u32, src_port)
+ __field(__u32, dst_cid)
+ __field(__u32, dst_port)
+ __field(__u32, len)
+ __field(__u16, type)
+ __field(__u16, op)
+ __field(__u32, flags)
+ __field(__u32, buf_alloc)
+ __field(__u32, fwd_cnt)
+ ),
+ TP_fast_assign(
+ __entry->src_cid = src_cid;
+ __entry->src_port = src_port;
+ __entry->dst_cid = dst_cid;
+ __entry->dst_port = dst_port;
+ __entry->len = len;
+ __entry->type = type;
+ __entry->op = op;
+ __entry->flags = flags;
+ __entry->buf_alloc = buf_alloc;
+ __entry->fwd_cnt = fwd_cnt;
+ ),
+ TP_printk("%u:%u -> %u:%u len=%u type=%s op=%s flags=%#x "
+ "buf_alloc=%u fwd_cnt=%u",
+ __entry->src_cid, __entry->src_port,
+ __entry->dst_cid, __entry->dst_port,
+ __entry->len,
+ show_type(__entry->type),
+ show_op(__entry->op),
+ __entry->flags,
+ __entry->buf_alloc,
+ __entry->fwd_cnt)
+);
+
+#endif /* _TRACE_VSOCK_VIRTIO_TRANSPORT_COMMON_H */
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE vsock_virtio_transport_common
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index c44747c0796a..185f8ea2702f 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -454,6 +454,7 @@ header-y += virtio_ring.h
header-y += virtio_rng.h
header-y += virtio_scsi.h
header-y += virtio_types.h
+header-y += virtio_vsock.h
header-y += vm_sockets.h
header-y += vt.h
header-y += vtpm_proxy.h
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index 2bdd1e3e7007..ac5eacd3055b 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -798,7 +798,7 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code)
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
struct btrfs_ioctl_ino_path_args)
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
- struct btrfs_ioctl_ino_path_args)
+ struct btrfs_ioctl_logical_ino_args)
#define BTRFS_IOC_SET_RECEIVED_SUBVOL _IOWR(BTRFS_IOCTL_MAGIC, 37, \
struct btrfs_ioctl_received_subvol_args)
#define BTRFS_IOC_SEND _IOW(BTRFS_IOCTL_MAGIC, 38, struct btrfs_ioctl_send_args)
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index cb4a72f888d5..b59ee077a596 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -286,6 +286,7 @@ typedef struct elf64_phdr {
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_RELA_LIVEPATCH 0x00100000
+#define SHF_RO_AFTER_INIT 0x00200000
#define SHF_MASKPROC 0xf0000000
/* special section indexes */
@@ -381,6 +382,19 @@ typedef struct elf64_shdr {
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
+#define NT_PPC_TAR 0x103 /* Target Address Register */
+#define NT_PPC_PPR 0x104 /* Program Priority Register */
+#define NT_PPC_DSCR 0x105 /* Data Stream Control Register */
+#define NT_PPC_EBB 0x106 /* Event Based Branch Registers */
+#define NT_PPC_PMU 0x107 /* Performance Monitor Registers */
+#define NT_PPC_TM_CGPR 0x108 /* TM checkpointed GPR Registers */
+#define NT_PPC_TM_CFPR 0x109 /* TM checkpointed FPR Registers */
+#define NT_PPC_TM_CVMX 0x10a /* TM checkpointed VMX Registers */
+#define NT_PPC_TM_CVSX 0x10b /* TM checkpointed VSX Registers */
+#define NT_PPC_TM_SPR 0x10c /* TM Special Purpose Registers */
+#define NT_PPC_TM_CTAR 0x10d /* TM checkpointed Target Address Register */
+#define NT_PPC_TM_CPPR 0x10e /* TM checkpointed Program Priority Register */
+#define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control Register */
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index e98bb4cce639..300ef255d1e0 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -882,7 +882,10 @@ struct kvm_irq_routing_msi {
__u32 address_lo;
__u32 address_hi;
__u32 data;
- __u32 pad;
+ union {
+ __u32 pad;
+ __u32 devid;
+ };
};
struct kvm_irq_routing_s390_adapter {
diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
index 61a8777178c6..56b7ab584cc0 100644
--- a/include/uapi/linux/vhost.h
+++ b/include/uapi/linux/vhost.h
@@ -47,6 +47,32 @@ struct vhost_vring_addr {
__u64 log_guest_addr;
};
+/* no alignment requirement */
+struct vhost_iotlb_msg {
+ __u64 iova;
+ __u64 size;
+ __u64 uaddr;
+#define VHOST_ACCESS_RO 0x1
+#define VHOST_ACCESS_WO 0x2
+#define VHOST_ACCESS_RW 0x3
+ __u8 perm;
+#define VHOST_IOTLB_MISS 1
+#define VHOST_IOTLB_UPDATE 2
+#define VHOST_IOTLB_INVALIDATE 3
+#define VHOST_IOTLB_ACCESS_FAIL 4
+ __u8 type;
+};
+
+#define VHOST_IOTLB_MSG 0x1
+
+struct vhost_msg {
+ int type;
+ union {
+ struct vhost_iotlb_msg iotlb;
+ __u8 padding[64];
+ };
+};
+
struct vhost_memory_region {
__u64 guest_phys_addr;
__u64 memory_size; /* bytes */
@@ -146,6 +172,8 @@ struct vhost_memory {
#define VHOST_F_LOG_ALL 26
/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
#define VHOST_NET_F_VIRTIO_NET_HDR 27
+/* Vhost have device IOTLB */
+#define VHOST_F_DEVICE_IOTLB 63
/* VHOST_SCSI specific definitions */
@@ -175,4 +203,9 @@ struct vhost_scsi_target {
#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
+/* VHOST_VSOCK specific defines */
+
+#define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64)
+#define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int)
+
#endif
diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
index 4cb65bbfa654..308e2096291f 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -49,7 +49,7 @@
* transport being used (eg. virtio_ring), the rest are per-device feature
* bits. */
#define VIRTIO_TRANSPORT_F_START 28
-#define VIRTIO_TRANSPORT_F_END 33
+#define VIRTIO_TRANSPORT_F_END 34
#ifndef VIRTIO_CONFIG_NO_LEGACY
/* Do we get callbacks when the ring is completely used, even if we've
@@ -63,4 +63,12 @@
/* v1.0 compliant. */
#define VIRTIO_F_VERSION_1 32
+/*
+ * If clear - device has the IOMMU bypass quirk feature.
+ * If set - use platform tools to detect the IOMMU.
+ *
+ * Note the reverse polarity (compared to most other features),
+ * this is for compatibility with legacy systems.
+ */
+#define VIRTIO_F_IOMMU_PLATFORM 33
#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
diff --git a/include/uapi/linux/virtio_ids.h b/include/uapi/linux/virtio_ids.h
index 77925f587b15..3228d582234a 100644
--- a/include/uapi/linux/virtio_ids.h
+++ b/include/uapi/linux/virtio_ids.h
@@ -41,5 +41,6 @@
#define VIRTIO_ID_CAIF 12 /* Virtio caif */
#define VIRTIO_ID_GPU 16 /* virtio GPU */
#define VIRTIO_ID_INPUT 18 /* virtio input */
+#define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
#endif /* _LINUX_VIRTIO_IDS_H */
diff --git a/include/uapi/linux/virtio_vsock.h b/include/uapi/linux/virtio_vsock.h
new file mode 100644
index 000000000000..1d57ed3d84d2
--- /dev/null
+++ b/include/uapi/linux/virtio_vsock.h
@@ -0,0 +1,94 @@
+/*
+ * This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so
+ * anyone can use the definitions to implement compatible drivers/servers:
+ *
+ *
+ * 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 IBM 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 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 IBM 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.
+ *
+ * Copyright (C) Red Hat, Inc., 2013-2015
+ * Copyright (C) Asias He <asias@redhat.com>, 2013
+ * Copyright (C) Stefan Hajnoczi <stefanha@redhat.com>, 2015
+ */
+
+#ifndef _UAPI_LINUX_VIRTIO_VSOCK_H
+#define _UAPI_LINUX_VIRTIO_VSOCK_H
+
+#include <linux/types.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+
+struct virtio_vsock_config {
+ __le64 guest_cid;
+} __attribute__((packed));
+
+enum virtio_vsock_event_id {
+ VIRTIO_VSOCK_EVENT_TRANSPORT_RESET = 0,
+};
+
+struct virtio_vsock_event {
+ __le32 id;
+} __attribute__((packed));
+
+struct virtio_vsock_hdr {
+ __le64 src_cid;
+ __le64 dst_cid;
+ __le32 src_port;
+ __le32 dst_port;
+ __le32 len;
+ __le16 type; /* enum virtio_vsock_type */
+ __le16 op; /* enum virtio_vsock_op */
+ __le32 flags;
+ __le32 buf_alloc;
+ __le32 fwd_cnt;
+} __attribute__((packed));
+
+enum virtio_vsock_type {
+ VIRTIO_VSOCK_TYPE_STREAM = 1,
+};
+
+enum virtio_vsock_op {
+ VIRTIO_VSOCK_OP_INVALID = 0,
+
+ /* Connect operations */
+ VIRTIO_VSOCK_OP_REQUEST = 1,
+ VIRTIO_VSOCK_OP_RESPONSE = 2,
+ VIRTIO_VSOCK_OP_RST = 3,
+ VIRTIO_VSOCK_OP_SHUTDOWN = 4,
+
+ /* To send payload */
+ VIRTIO_VSOCK_OP_RW = 5,
+
+ /* Tell the peer our credit info */
+ VIRTIO_VSOCK_OP_CREDIT_UPDATE = 6,
+ /* Request the peer to send the credit info to us */
+ VIRTIO_VSOCK_OP_CREDIT_REQUEST = 7,
+};
+
+/* VIRTIO_VSOCK_OP_SHUTDOWN flags values */
+enum virtio_vsock_shutdown {
+ VIRTIO_VSOCK_SHUTDOWN_RCV = 1,
+ VIRTIO_VSOCK_SHUTDOWN_SEND = 2,
+};
+
+#endif /* _UAPI_LINUX_VIRTIO_VSOCK_H */
diff --git a/include/uapi/misc/cxl.h b/include/uapi/misc/cxl.h
index cbae529b7ce0..180d526a55c3 100644
--- a/include/uapi/misc/cxl.h
+++ b/include/uapi/misc/cxl.h
@@ -136,8 +136,8 @@ struct cxl_event_afu_driver_reserved {
*
* Of course the contents will be ABI, but that's up the AFU driver.
*/
- size_t data_size;
- u8 data[];
+ __u32 data_size;
+ __u8 data[];
};
struct cxl_event {
diff --git a/include/uapi/rdma/Kbuild b/include/uapi/rdma/Kbuild
index 231901b08f6c..4edb0f2b4f9f 100644
--- a/include/uapi/rdma/Kbuild
+++ b/include/uapi/rdma/Kbuild
@@ -6,3 +6,4 @@ header-y += ib_user_verbs.h
header-y += rdma_netlink.h
header-y += rdma_user_cm.h
header-y += hfi/
+header-y += rdma_user_rxe.h
diff --git a/include/uapi/rdma/hfi/hfi1_user.h b/include/uapi/rdma/hfi/hfi1_user.h
index 98bebf8bef55..d15e7289d835 100644
--- a/include/uapi/rdma/hfi/hfi1_user.h
+++ b/include/uapi/rdma/hfi/hfi1_user.h
@@ -75,7 +75,7 @@
* may not be implemented; the user code must deal with this if it
* cares, or it must abort after initialization reports the difference.
*/
-#define HFI1_USER_SWMINOR 1
+#define HFI1_USER_SWMINOR 2
/*
* We will encode the major/minor inside a single 32bit version number.
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
index b6543d73d20a..7f035f4b53b0 100644
--- a/include/uapi/rdma/ib_user_verbs.h
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -95,6 +95,11 @@ enum {
IB_USER_VERBS_EX_CMD_CREATE_QP = IB_USER_VERBS_CMD_CREATE_QP,
IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
+ IB_USER_VERBS_EX_CMD_CREATE_WQ,
+ IB_USER_VERBS_EX_CMD_MODIFY_WQ,
+ IB_USER_VERBS_EX_CMD_DESTROY_WQ,
+ IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL,
+ IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL
};
/*
@@ -518,6 +523,14 @@ struct ib_uverbs_create_qp {
__u64 driver_data[0];
};
+enum ib_uverbs_create_qp_mask {
+ IB_UVERBS_CREATE_QP_MASK_IND_TABLE = 1UL << 0,
+};
+
+enum {
+ IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE,
+};
+
struct ib_uverbs_ex_create_qp {
__u64 user_handle;
__u32 pd_handle;
@@ -535,6 +548,8 @@ struct ib_uverbs_ex_create_qp {
__u8 reserved;
__u32 comp_mask;
__u32 create_flags;
+ __u32 rwq_ind_tbl_handle;
+ __u32 reserved1;
};
struct ib_uverbs_open_qp {
@@ -852,6 +867,24 @@ struct ib_uverbs_flow_spec_tcp_udp {
struct ib_uverbs_flow_tcp_udp_filter mask;
};
+struct ib_uverbs_flow_ipv6_filter {
+ __u8 src_ip[16];
+ __u8 dst_ip[16];
+};
+
+struct ib_uverbs_flow_spec_ipv6 {
+ union {
+ struct ib_uverbs_flow_spec_hdr hdr;
+ struct {
+ __u32 type;
+ __u16 size;
+ __u16 reserved;
+ };
+ };
+ struct ib_uverbs_flow_ipv6_filter val;
+ struct ib_uverbs_flow_ipv6_filter mask;
+};
+
struct ib_uverbs_flow_attr {
__u32 type;
__u16 size;
@@ -946,4 +979,66 @@ struct ib_uverbs_destroy_srq_resp {
__u32 events_reported;
};
+struct ib_uverbs_ex_create_wq {
+ __u32 comp_mask;
+ __u32 wq_type;
+ __u64 user_handle;
+ __u32 pd_handle;
+ __u32 cq_handle;
+ __u32 max_wr;
+ __u32 max_sge;
+};
+
+struct ib_uverbs_ex_create_wq_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+ __u32 wq_handle;
+ __u32 max_wr;
+ __u32 max_sge;
+ __u32 wqn;
+};
+
+struct ib_uverbs_ex_destroy_wq {
+ __u32 comp_mask;
+ __u32 wq_handle;
+};
+
+struct ib_uverbs_ex_destroy_wq_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+ __u32 events_reported;
+ __u32 reserved;
+};
+
+struct ib_uverbs_ex_modify_wq {
+ __u32 attr_mask;
+ __u32 wq_handle;
+ __u32 wq_state;
+ __u32 curr_wq_state;
+};
+
+/* Prevent memory allocation rather than max expected size */
+#define IB_USER_VERBS_MAX_LOG_IND_TBL_SIZE 0x0d
+struct ib_uverbs_ex_create_rwq_ind_table {
+ __u32 comp_mask;
+ __u32 log_ind_tbl_size;
+ /* Following are the wq handles according to log_ind_tbl_size
+ * wq_handle1
+ * wq_handle2
+ */
+ __u32 wq_handles[0];
+};
+
+struct ib_uverbs_ex_create_rwq_ind_table_resp {
+ __u32 comp_mask;
+ __u32 response_length;
+ __u32 ind_tbl_handle;
+ __u32 ind_tbl_num;
+};
+
+struct ib_uverbs_ex_destroy_rwq_ind_table {
+ __u32 comp_mask;
+ __u32 ind_tbl_handle;
+};
+
#endif /* IB_USER_VERBS_H */
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
index 3066718eb120..01923d463673 100644
--- a/include/uapi/rdma/rdma_user_cm.h
+++ b/include/uapi/rdma/rdma_user_cm.h
@@ -244,12 +244,19 @@ struct rdma_ucm_join_ip_mcast {
__u32 id;
};
+/* Multicast join flags */
+enum {
+ RDMA_MC_JOIN_FLAG_FULLMEMBER,
+ RDMA_MC_JOIN_FLAG_SENDONLY_FULLMEMBER,
+ RDMA_MC_JOIN_FLAG_RESERVED,
+};
+
struct rdma_ucm_join_mcast {
__u64 response; /* rdma_ucma_create_id_resp */
__u64 uid;
__u32 id;
__u16 addr_size;
- __u16 reserved;
+ __u16 join_flags;
struct sockaddr_storage addr;
};
diff --git a/include/uapi/rdma/rdma_user_rxe.h b/include/uapi/rdma/rdma_user_rxe.h
new file mode 100644
index 000000000000..1de99cfdaf7d
--- /dev/null
+++ b/include/uapi/rdma/rdma_user_rxe.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef RDMA_USER_RXE_H
+#define RDMA_USER_RXE_H
+
+#include <linux/types.h>
+
+union rxe_gid {
+ __u8 raw[16];
+ struct {
+ __be64 subnet_prefix;
+ __be64 interface_id;
+ } global;
+};
+
+struct rxe_global_route {
+ union rxe_gid dgid;
+ __u32 flow_label;
+ __u8 sgid_index;
+ __u8 hop_limit;
+ __u8 traffic_class;
+};
+
+struct rxe_av {
+ __u8 port_num;
+ __u8 network_type;
+ struct rxe_global_route grh;
+ union {
+ struct sockaddr _sockaddr;
+ struct sockaddr_in _sockaddr_in;
+ struct sockaddr_in6 _sockaddr_in6;
+ } sgid_addr, dgid_addr;
+};
+
+struct rxe_send_wr {
+ __u64 wr_id;
+ __u32 num_sge;
+ __u32 opcode;
+ __u32 send_flags;
+ union {
+ __be32 imm_data;
+ __u32 invalidate_rkey;
+ } ex;
+ union {
+ struct {
+ __u64 remote_addr;
+ __u32 rkey;
+ } rdma;
+ struct {
+ __u64 remote_addr;
+ __u64 compare_add;
+ __u64 swap;
+ __u32 rkey;
+ } atomic;
+ struct {
+ __u32 remote_qpn;
+ __u32 remote_qkey;
+ __u16 pkey_index;
+ } ud;
+ struct {
+ struct ib_mr *mr;
+ __u32 key;
+ int access;
+ } reg;
+ } wr;
+};
+
+struct rxe_sge {
+ __u64 addr;
+ __u32 length;
+ __u32 lkey;
+};
+
+struct mminfo {
+ __u64 offset;
+ __u32 size;
+ __u32 pad;
+};
+
+struct rxe_dma_info {
+ __u32 length;
+ __u32 resid;
+ __u32 cur_sge;
+ __u32 num_sge;
+ __u32 sge_offset;
+ union {
+ __u8 inline_data[0];
+ struct rxe_sge sge[0];
+ };
+};
+
+struct rxe_send_wqe {
+ struct rxe_send_wr wr;
+ struct rxe_av av;
+ __u32 status;
+ __u32 state;
+ __u64 iova;
+ __u32 mask;
+ __u32 first_psn;
+ __u32 last_psn;
+ __u32 ack_length;
+ __u32 ssn;
+ __u32 has_rd_atomic;
+ struct rxe_dma_info dma;
+};
+
+struct rxe_recv_wqe {
+ __u64 wr_id;
+ __u32 num_sge;
+ __u32 padding;
+ struct rxe_dma_info dma;
+};
+
+#endif /* RDMA_USER_RXE_H */
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
index 8b2eb93ae8ba..7c35e279d1e3 100644
--- a/include/xen/swiotlb-xen.h
+++ b/include/xen/swiotlb-xen.h
@@ -9,30 +9,30 @@ extern int xen_swiotlb_init(int verbose, bool early);
extern void
*xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void
xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void xen_swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern int
xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void
xen_swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
int nelems, enum dma_data_direction dir,
- struct dma_attrs *attrs);
+ unsigned long attrs);
extern void
xen_swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
diff --git a/init/Kconfig b/init/Kconfig
index 69886493ff1e..cac3f096050d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1761,6 +1761,7 @@ choice
config SLAB
bool "SLAB"
+ select HAVE_HARDENED_USERCOPY_ALLOCATOR
help
The regular slab allocator that is established and known to work
well in all environments. It organizes cache hot objects in
@@ -1768,6 +1769,7 @@ config SLAB
config SLUB
bool "SLUB (Unqueued Allocator)"
+ select HAVE_HARDENED_USERCOPY_ALLOCATOR
help
SLUB is a slab allocator that minimizes cache line usage
instead of managing queues of cached objects (SLAB approach).
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 356a6c7cb52a..1903b8f3a705 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -448,7 +448,7 @@ static u64 __report_allowed;
static void perf_duration_warn(struct irq_work *w)
{
- printk_ratelimited(KERN_WARNING
+ printk_ratelimited(KERN_INFO
"perf: interrupt took too long (%lld > %lld), lowering "
"kernel.perf_event_max_sample_rate to %d\n",
__report_avg, __report_allowed,
@@ -843,6 +843,32 @@ perf_cgroup_mark_enabled(struct perf_event *event,
}
}
}
+
+/*
+ * Update cpuctx->cgrp so that it is set when first cgroup event is added and
+ * cleared when last cgroup event is removed.
+ */
+static inline void
+list_update_cgroup_event(struct perf_event *event,
+ struct perf_event_context *ctx, bool add)
+{
+ struct perf_cpu_context *cpuctx;
+
+ if (!is_cgroup_event(event))
+ return;
+
+ if (add && ctx->nr_cgroups++)
+ return;
+ else if (!add && --ctx->nr_cgroups)
+ return;
+ /*
+ * Because cgroup events are always per-cpu events,
+ * this will always be called from the right CPU.
+ */
+ cpuctx = __get_cpu_context(ctx);
+ cpuctx->cgrp = add ? event->cgrp : NULL;
+}
+
#else /* !CONFIG_CGROUP_PERF */
static inline bool
@@ -920,6 +946,13 @@ perf_cgroup_mark_enabled(struct perf_event *event,
struct perf_event_context *ctx)
{
}
+
+static inline void
+list_update_cgroup_event(struct perf_event *event,
+ struct perf_event_context *ctx, bool add)
+{
+}
+
#endif
/*
@@ -1392,6 +1425,7 @@ ctx_group_list(struct perf_event *event, struct perf_event_context *ctx)
static void
list_add_event(struct perf_event *event, struct perf_event_context *ctx)
{
+
lockdep_assert_held(&ctx->lock);
WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT);
@@ -1412,8 +1446,7 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
list_add_tail(&event->group_entry, list);
}
- if (is_cgroup_event(event))
- ctx->nr_cgroups++;
+ list_update_cgroup_event(event, ctx, true);
list_add_rcu(&event->event_entry, &ctx->event_list);
ctx->nr_events++;
@@ -1581,8 +1614,6 @@ static void perf_group_attach(struct perf_event *event)
static void
list_del_event(struct perf_event *event, struct perf_event_context *ctx)
{
- struct perf_cpu_context *cpuctx;
-
WARN_ON_ONCE(event->ctx != ctx);
lockdep_assert_held(&ctx->lock);
@@ -1594,20 +1625,7 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
event->attach_state &= ~PERF_ATTACH_CONTEXT;
- if (is_cgroup_event(event)) {
- ctx->nr_cgroups--;
- /*
- * Because cgroup events are always per-cpu events, this will
- * always be called from the right CPU.
- */
- cpuctx = __get_cpu_context(ctx);
- /*
- * If there are no more cgroup events then clear cgrp to avoid
- * stale pointer in update_cgrp_time_from_cpuctx().
- */
- if (!ctx->nr_cgroups)
- cpuctx->cgrp = NULL;
- }
+ list_update_cgroup_event(event, ctx, false);
ctx->nr_events--;
if (event->attr.inherit_stat)
@@ -1716,8 +1734,8 @@ static inline int pmu_filter_match(struct perf_event *event)
static inline int
event_filter_match(struct perf_event *event)
{
- return (event->cpu == -1 || event->cpu == smp_processor_id())
- && perf_cgroup_match(event) && pmu_filter_match(event);
+ return (event->cpu == -1 || event->cpu == smp_processor_id()) &&
+ perf_cgroup_match(event) && pmu_filter_match(event);
}
static void
@@ -1737,8 +1755,8 @@ event_sched_out(struct perf_event *event,
* maintained, otherwise bogus information is return
* via read() for time_enabled, time_running:
*/
- if (event->state == PERF_EVENT_STATE_INACTIVE
- && !event_filter_match(event)) {
+ if (event->state == PERF_EVENT_STATE_INACTIVE &&
+ !event_filter_match(event)) {
delta = tstamp - event->tstamp_stopped;
event->tstamp_running += delta;
event->tstamp_stopped = tstamp;
@@ -2236,10 +2254,15 @@ perf_install_in_context(struct perf_event_context *ctx,
lockdep_assert_held(&ctx->mutex);
- event->ctx = ctx;
if (event->cpu != -1)
event->cpu = cpu;
+ /*
+ * Ensures that if we can observe event->ctx, both the event and ctx
+ * will be 'complete'. See perf_iterate_sb_cpu().
+ */
+ smp_store_release(&event->ctx, ctx);
+
if (!task) {
cpu_function_call(cpu, __perf_install_in_context, event);
return;
@@ -5969,6 +5992,14 @@ static void perf_iterate_sb_cpu(perf_iterate_f output, void *data)
struct perf_event *event;
list_for_each_entry_rcu(event, &pel->list, sb_list) {
+ /*
+ * Skip events that are not fully formed yet; ensure that
+ * if we observe event->ctx, both event and ctx will be
+ * complete enough. See perf_install_in_context().
+ */
+ if (!smp_load_acquire(&event->ctx))
+ continue;
+
if (event->state < PERF_EVENT_STATE_INACTIVE)
continue;
if (!event_filter_match(event))
diff --git a/kernel/futex.c b/kernel/futex.c
index 33664f70e2d2..46cb3a301bc1 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -179,7 +179,15 @@ int __read_mostly futex_cmpxchg_enabled;
* Futex flags used to encode options to functions and preserve them across
* restarts.
*/
-#define FLAGS_SHARED 0x01
+#ifdef CONFIG_MMU
+# define FLAGS_SHARED 0x01
+#else
+/*
+ * NOMMU does not have per process address space. Let the compiler optimize
+ * code away.
+ */
+# define FLAGS_SHARED 0x00
+#endif
#define FLAGS_CLOCKRT 0x02
#define FLAGS_HAS_TIMEOUT 0x04
@@ -405,6 +413,16 @@ static void get_futex_key_refs(union futex_key *key)
if (!key->both.ptr)
return;
+ /*
+ * On MMU less systems futexes are always "private" as there is no per
+ * process address space. We need the smp wmb nevertheless - yes,
+ * arch/blackfin has MMU less SMP ...
+ */
+ if (!IS_ENABLED(CONFIG_MMU)) {
+ smp_mb(); /* explicit smp_mb(); (B) */
+ return;
+ }
+
switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
case FUT_OFF_INODE:
ihold(key->shared.inode); /* implies smp_mb(); (B) */
@@ -436,6 +454,9 @@ static void drop_futex_key_refs(union futex_key *key)
return;
}
+ if (!IS_ENABLED(CONFIG_MMU))
+ return;
+
switch (key->both.offset & (FUT_OFF_INODE|FUT_OFF_MMSHARED)) {
case FUT_OFF_INODE:
iput(key->shared.inode);
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 54999350162c..19e9dfbe97fa 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -359,6 +359,17 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
else
dev_dbg(dev, "irq [%d-%d] for MSI\n",
virq, virq + desc->nvec_used - 1);
+ /*
+ * This flag is set by the PCI layer as we need to activate
+ * the MSI entries before the PCI layer enables MSI in the
+ * card. Otherwise the card latches a random msi message.
+ */
+ if (info->flags & MSI_FLAG_ACTIVATE_EARLY) {
+ struct irq_data *irq_data;
+
+ irq_data = irq_domain_get_irq_data(domain, desc->irq);
+ irq_domain_activate_irq(irq_data);
+ }
}
return 0;
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 0dbea887d625..93ad6c1fb9b6 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/static_key.h>
#include <linux/jump_label_ratelimit.h>
+#include <linux/bug.h>
#ifdef HAVE_JUMP_LABEL
@@ -56,6 +57,49 @@ jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop)
static void jump_label_update(struct static_key *key);
+/*
+ * There are similar definitions for the !HAVE_JUMP_LABEL case in jump_label.h.
+ * The use of 'atomic_read()' requires atomic.h and its problematic for some
+ * kernel headers such as kernel.h and others. Since static_key_count() is not
+ * used in the branch statements as it is for the !HAVE_JUMP_LABEL case its ok
+ * to have it be a function here. Similarly, for 'static_key_enable()' and
+ * 'static_key_disable()', which require bug.h. This should allow jump_label.h
+ * to be included from most/all places for HAVE_JUMP_LABEL.
+ */
+int static_key_count(struct static_key *key)
+{
+ /*
+ * -1 means the first static_key_slow_inc() is in progress.
+ * static_key_enabled() must return true, so return 1 here.
+ */
+ int n = atomic_read(&key->enabled);
+
+ return n >= 0 ? n : 1;
+}
+EXPORT_SYMBOL_GPL(static_key_count);
+
+void static_key_enable(struct static_key *key)
+{
+ int count = static_key_count(key);
+
+ WARN_ON_ONCE(count < 0 || count > 1);
+
+ if (!count)
+ static_key_slow_inc(key);
+}
+EXPORT_SYMBOL_GPL(static_key_enable);
+
+void static_key_disable(struct static_key *key)
+{
+ int count = static_key_count(key);
+
+ WARN_ON_ONCE(count < 0 || count > 1);
+
+ if (count)
+ static_key_slow_dec(key);
+}
+EXPORT_SYMBOL_GPL(static_key_disable);
+
void static_key_slow_inc(struct static_key *key)
{
int v, v1;
@@ -235,6 +279,18 @@ void __init jump_label_init(void)
struct static_key *key = NULL;
struct jump_entry *iter;
+ /*
+ * Since we are initializing the static_key.enabled field with
+ * with the 'raw' int values (to avoid pulling in atomic.h) in
+ * jump_label.h, let's make sure that is safe. There are only two
+ * cases to check since we initialize to 0 or 1.
+ */
+ BUILD_BUG_ON((int)ATOMIC_INIT(0) != 0);
+ BUILD_BUG_ON((int)ATOMIC_INIT(1) != 1);
+
+ if (static_key_initialized)
+ return;
+
jump_label_lock();
jump_label_sort_entries(iter_start, iter_stop);
@@ -284,11 +340,14 @@ static int __jump_label_mod_text_reserved(void *start, void *end)
{
struct module *mod;
+ preempt_disable();
mod = __module_text_address((unsigned long)start);
+ WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
+ preempt_enable();
+
if (!mod)
return 0;
- WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
return __jump_label_text_reserved(mod->jump_entries,
mod->jump_entries + mod->num_jump_entries,
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 5c2bc1052691..8bbe50704621 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -309,7 +309,7 @@ static int klp_write_object_relocations(struct module *pmod,
break;
}
- module_enable_ro(pmod);
+ module_enable_ro(pmod, true);
return ret;
}
diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h
index 37649e69056c..8a99abf58080 100644
--- a/kernel/locking/qspinlock_paravirt.h
+++ b/kernel/locking/qspinlock_paravirt.h
@@ -450,7 +450,7 @@ pv_wait_head_or_lock(struct qspinlock *lock, struct mcs_spinlock *node)
goto gotlock;
}
}
- WRITE_ONCE(pn->state, vcpu_halted);
+ WRITE_ONCE(pn->state, vcpu_hashed);
qstat_inc(qstat_pv_wait_head, true);
qstat_inc(qstat_pv_wait_again, waitcnt);
pv_wait(&l->locked, _Q_SLOW_VAL);
diff --git a/kernel/locking/qspinlock_stat.h b/kernel/locking/qspinlock_stat.h
index 22e025309845..b9d031516254 100644
--- a/kernel/locking/qspinlock_stat.h
+++ b/kernel/locking/qspinlock_stat.h
@@ -153,7 +153,6 @@ static ssize_t qstat_read(struct file *file, char __user *user_buf,
*/
if ((counter == qstat_pv_latency_kick) ||
(counter == qstat_pv_latency_wake)) {
- stat = 0;
if (kicks)
stat = DIV_ROUND_CLOSEST_ULL(stat, kicks);
}
diff --git a/kernel/module.c b/kernel/module.c
index a0f48b8b00da..529efae9f481 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -265,7 +265,7 @@ static void module_assert_mutex_or_preempt(void)
if (unlikely(!debug_locks))
return;
- WARN_ON(!rcu_read_lock_sched_held() &&
+ WARN_ON_ONCE(!rcu_read_lock_sched_held() &&
!lockdep_is_held(&module_mutex));
#endif
}
@@ -337,7 +337,7 @@ static inline void add_taint_module(struct module *mod, unsigned flag,
* A thread that wants to hold a reference to a module only while it
* is running can call this to safely exit. nfsd and lockd use this.
*/
-void __module_put_and_exit(struct module *mod, long code)
+void __noreturn __module_put_and_exit(struct module *mod, long code)
{
module_put(mod);
do_exit(code);
@@ -1694,8 +1694,7 @@ static int module_add_modinfo_attrs(struct module *mod)
temp_attr = mod->modinfo_attrs;
for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
- if (!attr->test ||
- (attr->test && attr->test(mod))) {
+ if (!attr->test || attr->test(mod)) {
memcpy(temp_attr, attr, sizeof(*temp_attr));
sysfs_attr_init(&temp_attr->attr);
error = sysfs_create_file(&mod->mkobj.kobj,
@@ -1859,10 +1858,11 @@ static void mod_sysfs_teardown(struct module *mod)
* from modification and any data from execution.
*
* General layout of module is:
- * [text] [read-only-data] [writable data]
- * text_size -----^ ^ ^
- * ro_size ------------------------| |
- * size -------------------------------------------|
+ * [text] [read-only-data] [ro-after-init] [writable data]
+ * text_size -----^ ^ ^ ^
+ * ro_size ------------------------| | |
+ * ro_after_init_size -----------------------------| |
+ * size -----------------------------------------------------------|
*
* These values are always page-aligned (as is base)
*/
@@ -1885,14 +1885,24 @@ static void frob_rodata(const struct module_layout *layout,
(layout->ro_size - layout->text_size) >> PAGE_SHIFT);
}
+static void frob_ro_after_init(const struct module_layout *layout,
+ int (*set_memory)(unsigned long start, int num_pages))
+{
+ BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
+ BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
+ BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
+ set_memory((unsigned long)layout->base + layout->ro_size,
+ (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
+}
+
static void frob_writable_data(const struct module_layout *layout,
int (*set_memory)(unsigned long start, int num_pages))
{
BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
- BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
+ BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));
- set_memory((unsigned long)layout->base + layout->ro_size,
- (layout->size - layout->ro_size) >> PAGE_SHIFT);
+ set_memory((unsigned long)layout->base + layout->ro_after_init_size,
+ (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
}
/* livepatching wants to disable read-only so it can frob module. */
@@ -1900,21 +1910,26 @@ void module_disable_ro(const struct module *mod)
{
frob_text(&mod->core_layout, set_memory_rw);
frob_rodata(&mod->core_layout, set_memory_rw);
+ frob_ro_after_init(&mod->core_layout, set_memory_rw);
frob_text(&mod->init_layout, set_memory_rw);
frob_rodata(&mod->init_layout, set_memory_rw);
}
-void module_enable_ro(const struct module *mod)
+void module_enable_ro(const struct module *mod, bool after_init)
{
frob_text(&mod->core_layout, set_memory_ro);
frob_rodata(&mod->core_layout, set_memory_ro);
frob_text(&mod->init_layout, set_memory_ro);
frob_rodata(&mod->init_layout, set_memory_ro);
+
+ if (after_init)
+ frob_ro_after_init(&mod->core_layout, set_memory_ro);
}
static void module_enable_nx(const struct module *mod)
{
frob_rodata(&mod->core_layout, set_memory_nx);
+ frob_ro_after_init(&mod->core_layout, set_memory_nx);
frob_writable_data(&mod->core_layout, set_memory_nx);
frob_rodata(&mod->init_layout, set_memory_nx);
frob_writable_data(&mod->init_layout, set_memory_nx);
@@ -1923,6 +1938,7 @@ static void module_enable_nx(const struct module *mod)
static void module_disable_nx(const struct module *mod)
{
frob_rodata(&mod->core_layout, set_memory_x);
+ frob_ro_after_init(&mod->core_layout, set_memory_x);
frob_writable_data(&mod->core_layout, set_memory_x);
frob_rodata(&mod->init_layout, set_memory_x);
frob_writable_data(&mod->init_layout, set_memory_x);
@@ -1965,6 +1981,8 @@ static void disable_ro_nx(const struct module_layout *layout)
frob_text(layout, set_memory_rw);
frob_rodata(layout, set_memory_rw);
frob_rodata(layout, set_memory_x);
+ frob_ro_after_init(layout, set_memory_rw);
+ frob_ro_after_init(layout, set_memory_x);
frob_writable_data(layout, set_memory_x);
}
@@ -2307,6 +2325,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
* finder in the two loops below */
{ SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
{ SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
+ { SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL },
{ SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
{ ARCH_SHF_SMALL | SHF_ALLOC, 0 }
};
@@ -2338,7 +2357,11 @@ static void layout_sections(struct module *mod, struct load_info *info)
mod->core_layout.size = debug_align(mod->core_layout.size);
mod->core_layout.ro_size = mod->core_layout.size;
break;
- case 3: /* whole core */
+ case 2: /* RO after init */
+ mod->core_layout.size = debug_align(mod->core_layout.size);
+ mod->core_layout.ro_after_init_size = mod->core_layout.size;
+ break;
+ case 4: /* whole core */
mod->core_layout.size = debug_align(mod->core_layout.size);
break;
}
@@ -2368,7 +2391,14 @@ static void layout_sections(struct module *mod, struct load_info *info)
mod->init_layout.size = debug_align(mod->init_layout.size);
mod->init_layout.ro_size = mod->init_layout.size;
break;
- case 3: /* whole init */
+ case 2:
+ /*
+ * RO after init doesn't apply to init_layout (only
+ * core_layout), so it just takes the value of ro_size.
+ */
+ mod->init_layout.ro_after_init_size = mod->init_layout.ro_size;
+ break;
+ case 4: /* whole init */
mod->init_layout.size = debug_align(mod->init_layout.size);
break;
}
@@ -2688,13 +2718,18 @@ static inline void kmemleak_load_module(const struct module *mod,
#endif
#ifdef CONFIG_MODULE_SIG
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
{
int err = -ENOKEY;
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
const void *mod = info->hdr;
- if (info->len > markerlen &&
+ /*
+ * Require flags == 0, as a module with version information
+ * removed is no longer the module that was signed
+ */
+ if (flags == 0 &&
+ info->len > markerlen &&
memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
/* We truncate the module to discard the signature */
info->len -= markerlen;
@@ -2713,7 +2748,7 @@ static int module_sig_check(struct load_info *info)
return err;
}
#else /* !CONFIG_MODULE_SIG */
-static int module_sig_check(struct load_info *info)
+static int module_sig_check(struct load_info *info, int flags)
{
return 0;
}
@@ -2921,8 +2956,12 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
return -ENOEXEC;
}
- if (!get_modinfo(info, "intree"))
+ if (!get_modinfo(info, "intree")) {
+ if (!test_taint(TAINT_OOT_MODULE))
+ pr_warn("%s: loading out-of-tree module taints kernel.\n",
+ mod->name);
add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
+ }
if (get_modinfo(info, "staging")) {
add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
@@ -3091,6 +3130,8 @@ static int move_module(struct module *mod, struct load_info *info)
static int check_module_license_and_versions(struct module *mod)
{
+ int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
+
/*
* ndiswrapper is under GPL by itself, but loads proprietary modules.
* Don't use add_taint_module(), as it would prevent ndiswrapper from
@@ -3109,6 +3150,9 @@ static int check_module_license_and_versions(struct module *mod)
add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
LOCKDEP_NOW_UNRELIABLE);
+ if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
+ pr_warn("%s: module license taints kernel.\n", mod->name);
+
#ifdef CONFIG_MODVERSIONS
if ((mod->num_syms && !mod->crcs)
|| (mod->num_gpl_syms && !mod->gpl_crcs)
@@ -3156,16 +3200,41 @@ int __weak module_frob_arch_sections(Elf_Ehdr *hdr,
return 0;
}
+/* module_blacklist is a comma-separated list of module names */
+static char *module_blacklist;
+static bool blacklisted(char *module_name)
+{
+ const char *p;
+ size_t len;
+
+ if (!module_blacklist)
+ return false;
+
+ for (p = module_blacklist; *p; p += len) {
+ len = strcspn(p, ",");
+ if (strlen(module_name) == len && !memcmp(module_name, p, len))
+ return true;
+ if (p[len] == ',')
+ len++;
+ }
+ return false;
+}
+core_param(module_blacklist, module_blacklist, charp, 0400);
+
static struct module *layout_and_allocate(struct load_info *info, int flags)
{
/* Module within temporary copy. */
struct module *mod;
+ unsigned int ndx;
int err;
mod = setup_load_info(info, flags);
if (IS_ERR(mod))
return mod;
+ if (blacklisted(mod->name))
+ return ERR_PTR(-EPERM);
+
err = check_modinfo(mod, info, flags);
if (err)
return ERR_PTR(err);
@@ -3179,6 +3248,15 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
/* We will do a special allocation for per-cpu sections later. */
info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ /*
+ * Mark ro_after_init section with SHF_RO_AFTER_INIT so that
+ * layout_sections() can put it in the right place.
+ * Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set.
+ */
+ ndx = find_sec(info, ".data..ro_after_init");
+ if (ndx)
+ info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
+
/* Determine total sizes, and put offsets in sh_entsize. For now
this is done generically; there doesn't appear to be any
special cases for the architectures. */
@@ -3345,12 +3423,14 @@ static noinline int do_init_module(struct module *mod)
/* Switch to core kallsyms now init is done: kallsyms may be walking! */
rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
#endif
+ module_enable_ro(mod, true);
mod_tree_remove_init(mod);
disable_ro_nx(&mod->init_layout);
module_arch_freeing_init(mod);
mod->init_layout.base = NULL;
mod->init_layout.size = 0;
mod->init_layout.ro_size = 0;
+ mod->init_layout.ro_after_init_size = 0;
mod->init_layout.text_size = 0;
/*
* We want to free module_init, but be aware that kallsyms may be
@@ -3442,8 +3522,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
/* This relies on module_mutex for list integrity. */
module_bug_finalize(info->hdr, info->sechdrs, mod);
- /* Set RO and NX regions */
- module_enable_ro(mod);
+ module_enable_ro(mod, false);
module_enable_nx(mod);
/* Mark state as coming so strong_try_module_get() ignores us,
@@ -3499,7 +3578,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
long err;
char *after_dashes;
- err = module_sig_check(info);
+ err = module_sig_check(info, flags);
if (err)
goto free_copy;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index a881c6a7ba74..33c79b6105c5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -300,12 +300,12 @@ static int create_image(int platform_mode)
save_processor_state();
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, true);
error = swsusp_arch_suspend();
+ /* Restore control flow magically appears here */
+ restore_processor_state();
trace_suspend_resume(TPS("machine_suspend"), PM_EVENT_HIBERNATE, false);
if (error)
printk(KERN_ERR "PM: Error %d creating hibernation image\n",
error);
- /* Restore control flow magically appears here */
- restore_processor_state();
if (!in_suspend)
events_check_enabled = false;
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 5d4505f30083..7fd2838fa417 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -16,11 +16,9 @@
*/
#include <linux/percpu.h>
-typedef __printf(2, 0) int (*printk_func_t)(int level, const char *fmt,
- va_list args);
+typedef __printf(1, 0) int (*printk_func_t)(const char *fmt, va_list args);
-__printf(2, 0)
-int vprintk_default(int level, const char *fmt, va_list args);
+int __printf(1, 0) vprintk_default(const char *fmt, va_list args);
#ifdef CONFIG_PRINTK_NMI
@@ -33,10 +31,9 @@ extern raw_spinlock_t logbuf_lock;
* via per-CPU variable.
*/
DECLARE_PER_CPU(printk_func_t, printk_func);
-__printf(2, 0)
-static inline int vprintk_func(int level, const char *fmt, va_list args)
+static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
{
- return this_cpu_read(printk_func)(level, fmt, args);
+ return this_cpu_read(printk_func)(fmt, args);
}
extern atomic_t nmi_message_lost;
@@ -47,10 +44,9 @@ static inline int get_nmi_message_lost(void)
#else /* CONFIG_PRINTK_NMI */
-__printf(2, 0)
-static inline int vprintk_func(int level, const char *fmt, va_list args)
+static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
{
- return vprintk_default(level, fmt, args);
+ return vprintk_default(fmt, args);
}
static inline int get_nmi_message_lost(void)
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index bc3eeb1ae6da..b69eb8a2876f 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -58,7 +58,7 @@ static DEFINE_PER_CPU(struct nmi_seq_buf, nmi_print_seq);
* one writer running. But the buffer might get flushed from another
* CPU, so we need to be careful.
*/
-static int vprintk_nmi(int level, const char *fmt, va_list args)
+static int vprintk_nmi(const char *fmt, va_list args)
{
struct nmi_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
int add = 0;
@@ -79,16 +79,7 @@ again:
if (!len)
smp_rmb();
- if (level != LOGLEVEL_DEFAULT) {
- add = snprintf(s->buffer + len, sizeof(s->buffer) - len,
- KERN_SOH "%c", '0' + level);
- add += vsnprintf(s->buffer + len + add,
- sizeof(s->buffer) - len - add,
- fmt, args);
- } else {
- add = vsnprintf(s->buffer + len, sizeof(s->buffer) - len,
- fmt, args);
- }
+ add = vsnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args);
/*
* Do it once again if the buffer has been flushed in the meantime.
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a5ef95ca18c9..eea6dbc2d8cf 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1930,28 +1930,7 @@ asmlinkage int printk_emit(int facility, int level,
}
EXPORT_SYMBOL(printk_emit);
-#ifdef CONFIG_PRINTK
-#define define_pr_level(func, loglevel) \
-asmlinkage __visible void func(const char *fmt, ...) \
-{ \
- va_list args; \
- \
- va_start(args, fmt); \
- vprintk_default(loglevel, fmt, args); \
- va_end(args); \
-} \
-EXPORT_SYMBOL(func)
-
-define_pr_level(__pr_emerg, LOGLEVEL_EMERG);
-define_pr_level(__pr_alert, LOGLEVEL_ALERT);
-define_pr_level(__pr_crit, LOGLEVEL_CRIT);
-define_pr_level(__pr_err, LOGLEVEL_ERR);
-define_pr_level(__pr_warn, LOGLEVEL_WARNING);
-define_pr_level(__pr_notice, LOGLEVEL_NOTICE);
-define_pr_level(__pr_info, LOGLEVEL_INFO);
-#endif
-
-int vprintk_default(int level, const char *fmt, va_list args)
+int vprintk_default(const char *fmt, va_list args)
{
int r;
@@ -1961,7 +1940,7 @@ int vprintk_default(int level, const char *fmt, va_list args)
return r;
}
#endif
- r = vprintk_emit(0, level, NULL, 0, fmt, args);
+ r = vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args);
return r;
}
@@ -1994,7 +1973,7 @@ asmlinkage __visible int printk(const char *fmt, ...)
int r;
va_start(args, fmt);
- r = vprintk_func(LOGLEVEL_DEFAULT, fmt, args);
+ r = vprintk_func(fmt, args);
va_end(args);
return r;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index d49bfa1e53e6..1d3b7665d0be 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -585,8 +585,8 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
return -EINVAL;
if (unlikely(data & PTRACE_O_SUSPEND_SECCOMP)) {
- if (!config_enabled(CONFIG_CHECKPOINT_RESTORE) ||
- !config_enabled(CONFIG_SECCOMP))
+ if (!IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) ||
+ !IS_ENABLED(CONFIG_SECCOMP))
return -EINVAL;
if (!capable(CAP_SYS_ADMIN))
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5c883fe8e440..2a906f20fba7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -74,6 +74,7 @@
#include <linux/context_tracking.h>
#include <linux/compiler.h>
#include <linux/frame.h>
+#include <linux/prefetch.h>
#include <asm/switch_to.h>
#include <asm/tlb.h>
@@ -2972,6 +2973,23 @@ EXPORT_PER_CPU_SYMBOL(kstat);
EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
/*
+ * The function fair_sched_class.update_curr accesses the struct curr
+ * and its field curr->exec_start; when called from task_sched_runtime(),
+ * we observe a high rate of cache misses in practice.
+ * Prefetching this data results in improved performance.
+ */
+static inline void prefetch_curr_exec_start(struct task_struct *p)
+{
+#ifdef CONFIG_FAIR_GROUP_SCHED
+ struct sched_entity *curr = (&p->se)->cfs_rq->curr;
+#else
+ struct sched_entity *curr = (&task_rq(p)->cfs)->curr;
+#endif
+ prefetch(curr);
+ prefetch(&curr->exec_start);
+}
+
+/*
* Return accounted runtime for the task.
* In case the task is currently running, return the runtime plus current's
* pending runtime that have not been accounted yet.
@@ -3005,6 +3023,7 @@ unsigned long long task_sched_runtime(struct task_struct *p)
* thread, breaking clock_gettime().
*/
if (task_current(rq, p) && task_on_rq_queued(p)) {
+ prefetch_curr_exec_start(p);
update_rq_clock(rq);
p->sched_class->update_curr(rq);
}
diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
index 5be58820465c..d4184498c9f5 100644
--- a/kernel/sched/cpudeadline.c
+++ b/kernel/sched/cpudeadline.c
@@ -168,7 +168,7 @@ void cpudl_set(struct cpudl *cp, int cpu, u64 dl, int is_valid)
if (old_idx == IDX_INVALID) {
cp->size++;
- cp->elements[cp->size - 1].dl = 0;
+ cp->elements[cp->size - 1].dl = dl;
cp->elements[cp->size - 1].cpu = cpu;
cp->elements[cpu].idx = cp->size - 1;
cpudl_change_key(cp, cp->size - 1, dl);
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index 1934f658c036..9858266fb0b3 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -508,13 +508,21 @@ void account_process_tick(struct task_struct *p, int user_tick)
*/
void account_idle_ticks(unsigned long ticks)
{
+ cputime_t cputime, steal;
if (sched_clock_irqtime) {
irqtime_account_idle_ticks(ticks);
return;
}
- account_idle_time(jiffies_to_cputime(ticks));
+ cputime = jiffies_to_cputime(ticks);
+ steal = steal_account_process_time(cputime);
+
+ if (steal >= cputime)
+ return;
+
+ cputime -= steal;
+ account_idle_time(cputime);
}
/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index fcb7f0217ff4..1ce8867283dc 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -658,8 +658,11 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
*
* XXX figure out if select_task_rq_dl() deals with offline cpus.
*/
- if (unlikely(!rq->online))
+ if (unlikely(!rq->online)) {
+ lockdep_unpin_lock(&rq->lock, rf.cookie);
rq = dl_task_offline_migration(rq, p);
+ rf.cookie = lockdep_pin_lock(&rq->lock);
+ }
/*
* Queueing this task back might have overloaded rq, check if we need
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 4088eedea763..039de34f1521 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4269,7 +4269,7 @@ static void sync_throttle(struct task_group *tg, int cpu)
pcfs_rq = tg->parent->cfs_rq[cpu];
cfs_rq->throttle_count = pcfs_rq->throttle_count;
- pcfs_rq->throttled_clock_task = rq_clock_task(cpu_rq(cpu));
+ cfs_rq->throttled_clock_task = rq_clock_task(cpu_rq(cpu));
}
/* conditionally throttle active cfs_rq's from put_prev_entity() */
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 54d15eb2b701..ef6c6c3f9d8a 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -347,7 +347,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
{
struct seccomp_filter *sfilter;
int ret;
- const bool save_orig = config_enabled(CONFIG_CHECKPOINT_RESTORE);
+ const bool save_orig = IS_ENABLED(CONFIG_CHECKPOINT_RESTORE);
if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
return ERR_PTR(-EINVAL);
@@ -542,7 +542,7 @@ void secure_computing_strict(int this_syscall)
{
int mode = current->seccomp.mode;
- if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
+ if (IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) &&
unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
return;
@@ -655,7 +655,7 @@ int __secure_computing(const struct seccomp_data *sd)
int mode = current->seccomp.mode;
int this_syscall;
- if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
+ if (IS_ENABLED(CONFIG_CHECKPOINT_RESTORE) &&
unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
return 0;
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 555670a5143c..32bf6f75a8fe 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1496,6 +1496,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]);
u64 expires = KTIME_MAX;
unsigned long nextevt;
+ bool is_max_delta;
/*
* Pretend that there is no timer pending if the cpu is offline.
@@ -1506,6 +1507,7 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
spin_lock(&base->lock);
nextevt = __next_timer_interrupt(base);
+ is_max_delta = (nextevt == base->clk + NEXT_TIMER_MAX_DELTA);
base->next_expiry = nextevt;
/*
* We have a fresh next event. Check whether we can forward the base:
@@ -1519,7 +1521,8 @@ u64 get_next_timer_interrupt(unsigned long basej, u64 basem)
expires = basem;
base->is_idle = false;
} else {
- expires = basem + (nextevt - basej) * TICK_NSEC;
+ if (!is_max_delta)
+ expires = basem + (nextevt - basej) * TICK_NSEC;
/*
* If we expect to sleep more than a tick, mark the base idle:
*/
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index fb345cd11883..7598e6ca817a 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -776,7 +776,7 @@ static void blk_add_trace_bio(struct request_queue *q, struct bio *bio,
return;
__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
- bio_op(bio), bio->bi_rw, what, error, 0, NULL);
+ bio_op(bio), bio->bi_opf, what, error, 0, NULL);
}
static void blk_add_trace_bio_bounce(void *ignore,
@@ -881,7 +881,7 @@ static void blk_add_trace_split(void *ignore,
__be64 rpdu = cpu_to_be64(pdu);
__blk_add_trace(bt, bio->bi_iter.bi_sector,
- bio->bi_iter.bi_size, bio_op(bio), bio->bi_rw,
+ bio->bi_iter.bi_size, bio_op(bio), bio->bi_opf,
BLK_TA_SPLIT, bio->bi_error, sizeof(rpdu),
&rpdu);
}
@@ -915,7 +915,7 @@ static void blk_add_trace_bio_remap(void *ignore,
r.sector_from = cpu_to_be64(from);
__blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size,
- bio_op(bio), bio->bi_rw, BLK_TA_REMAP, bio->bi_error,
+ bio_op(bio), bio->bi_opf, BLK_TA_REMAP, bio->bi_error,
sizeof(r), &r);
}
diff --git a/lib/dma-noop.c b/lib/dma-noop.c
index 72145646857e..3d766e78fbe2 100644
--- a/lib/dma-noop.c
+++ b/lib/dma-noop.c
@@ -10,7 +10,7 @@
static void *dma_noop_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
void *ret;
@@ -22,7 +22,7 @@ static void *dma_noop_alloc(struct device *dev, size_t size,
static void dma_noop_free(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_addr,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
free_pages((unsigned long)cpu_addr, get_order(size));
}
@@ -30,13 +30,14 @@ static void dma_noop_free(struct device *dev, size_t size,
static dma_addr_t dma_noop_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
return page_to_phys(page) + offset;
}
static int dma_noop_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir,
+ unsigned long attrs)
{
int i;
struct scatterlist *sg;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index fe42b6ec3f0c..da796e2dc4f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -188,6 +188,13 @@ static int ddebug_change(const struct ddebug_query *query,
newflags = (dp->flags & mask) | flags;
if (newflags == dp->flags)
continue;
+#ifdef HAVE_JUMP_LABEL
+ if (dp->flags & _DPRINTK_FLAGS_PRINT) {
+ if (!(flags & _DPRINTK_FLAGS_PRINT))
+ static_branch_disable(&dp->key.dd_key_true);
+ } else if (flags & _DPRINTK_FLAGS_PRINT)
+ static_branch_enable(&dp->key.dd_key_true);
+#endif
dp->flags = newflags;
vpr_info("changed %s:%d [%s]%s =%s\n",
trim_prefix(dp->filename), dp->lineno,
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c
index 33f655ef48cd..9c5fe8110413 100644
--- a/lib/strncpy_from_user.c
+++ b/lib/strncpy_from_user.c
@@ -40,8 +40,8 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long
unsigned long c, data;
/* Fall back to byte-at-a-time if we get a page fault */
- if (unlikely(unsafe_get_user(c,(unsigned long __user *)(src+res))))
- break;
+ unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);
+
*(unsigned long *)(dst+res) = c;
if (has_zero(c, &data, &constants)) {
data = prep_zero_mask(c, data, &constants);
@@ -56,8 +56,7 @@ byte_at_a_time:
while (max) {
char c;
- if (unlikely(unsafe_get_user(c,src+res)))
- return -EFAULT;
+ unsafe_get_user(c,src+res, efault);
dst[res] = c;
if (!c)
return res;
@@ -76,6 +75,7 @@ byte_at_a_time:
* Nope: we hit the address space limit, and we still had more
* characters the caller would have wanted. That's an EFAULT.
*/
+efault:
return -EFAULT;
}
diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c
index 2625943625d7..8e105ed4df12 100644
--- a/lib/strnlen_user.c
+++ b/lib/strnlen_user.c
@@ -45,8 +45,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
src -= align;
max += align;
- if (unlikely(unsafe_get_user(c,(unsigned long __user *)src)))
- return 0;
+ unsafe_get_user(c, (unsigned long __user *)src, efault);
c |= aligned_byte_mask(align);
for (;;) {
@@ -61,8 +60,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
if (unlikely(max <= sizeof(unsigned long)))
break;
max -= sizeof(unsigned long);
- if (unlikely(unsafe_get_user(c,(unsigned long __user *)(src+res))))
- return 0;
+ unsafe_get_user(c, (unsigned long __user *)(src+res), efault);
}
res -= align;
@@ -77,6 +75,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
* Nope: we hit the address space limit, and we still had more
* characters the caller would have wanted. That's 0.
*/
+efault:
return 0;
}
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 76f29ecba8f4..22e13a0e19d7 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -738,7 +738,7 @@ swiotlb_full(struct device *dev, size_t size, enum dma_data_direction dir,
dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
phys_addr_t map, phys = page_to_phys(page) + offset;
dma_addr_t dev_addr = phys_to_dma(dev, phys);
@@ -807,7 +807,7 @@ static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
size_t size, enum dma_data_direction dir,
- struct dma_attrs *attrs)
+ unsigned long attrs)
{
unmap_single(hwdev, dev_addr, size, dir);
}
@@ -877,7 +877,7 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_device);
*/
int
swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
- enum dma_data_direction dir, struct dma_attrs *attrs)
+ enum dma_data_direction dir, unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -914,7 +914,7 @@ int
swiotlb_map_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
enum dma_data_direction dir)
{
- return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+ return swiotlb_map_sg_attrs(hwdev, sgl, nelems, dir, 0);
}
EXPORT_SYMBOL(swiotlb_map_sg);
@@ -924,7 +924,8 @@ EXPORT_SYMBOL(swiotlb_map_sg);
*/
void
swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
- int nelems, enum dma_data_direction dir, struct dma_attrs *attrs)
+ int nelems, enum dma_data_direction dir,
+ unsigned long attrs)
{
struct scatterlist *sg;
int i;
@@ -941,7 +942,7 @@ void
swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sgl, int nelems,
enum dma_data_direction dir)
{
- return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, NULL);
+ return swiotlb_unmap_sg_attrs(hwdev, sgl, nelems, dir, 0);
}
EXPORT_SYMBOL(swiotlb_unmap_sg);
diff --git a/mm/Kconfig b/mm/Kconfig
index c0837845c17c..78a23c5c302d 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -187,6 +187,7 @@ config MEMORY_HOTPLUG
bool "Allow for memory hot-add"
depends on SPARSEMEM || X86_64_ACPI_NUMA
depends on ARCH_ENABLE_MEMORY_HOTPLUG
+ depends on !KASAN
config MEMORY_HOTPLUG_SPARSE
def_bool y
diff --git a/mm/Makefile b/mm/Makefile
index fc059666c760..2ca1faf3fa09 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -21,6 +21,9 @@ KCOV_INSTRUMENT_memcontrol.o := n
KCOV_INSTRUMENT_mmzone.o := n
KCOV_INSTRUMENT_vmstat.o := n
+# Since __builtin_frame_address does work as used, disable the warning.
+CFLAGS_usercopy.o += $(call cc-disable-warning, frame-address)
+
mmu-y := nommu.o
mmu-$(CONFIG_MMU) := gup.o highmem.o memory.o mincore.o \
mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
@@ -99,3 +102,4 @@ obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
obj-$(CONFIG_IDLE_PAGE_TRACKING) += page_idle.o
obj-$(CONFIG_FRAME_VECTOR) += frame_vector.o
obj-$(CONFIG_DEBUG_PAGE_REF) += debug_page_ref.o
+obj-$(CONFIG_HARDENED_USERCOPY) += usercopy.o
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index efe237742074..8fde443f36d7 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -825,6 +825,20 @@ int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
}
EXPORT_SYMBOL(bdi_register_dev);
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
+{
+ int rc;
+
+ rc = bdi_register(bdi, NULL, "%u:%u", MAJOR(owner->devt),
+ MINOR(owner->devt));
+ if (rc)
+ return rc;
+ bdi->owner = owner;
+ get_device(owner);
+ return 0;
+}
+EXPORT_SYMBOL(bdi_register_owner);
+
/*
* Remove bdi from bdi_list, and ensure that it is no longer visible
*/
@@ -849,6 +863,11 @@ void bdi_unregister(struct backing_dev_info *bdi)
device_unregister(bdi->dev);
bdi->dev = NULL;
}
+
+ if (bdi->owner) {
+ put_device(bdi->owner);
+ bdi->owner = NULL;
+ }
}
void bdi_exit(struct backing_dev_info *bdi)
diff --git a/mm/filemap.c b/mm/filemap.c
index 3083ded98b15..8a287dfc5372 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -887,9 +887,9 @@ EXPORT_SYMBOL(end_page_writeback);
* After completing I/O on a page, call this routine to update the page
* flags appropriately
*/
-void page_endio(struct page *page, int rw, int err)
+void page_endio(struct page *page, bool is_write, int err)
{
- if (rw == READ) {
+ if (!is_write) {
if (!err) {
SetPageUptodate(page);
} else {
@@ -897,7 +897,7 @@ void page_endio(struct page *page, int rw, int err)
SetPageError(page);
}
unlock_page(page);
- } else { /* rw == WRITE */
+ } else {
if (err) {
SetPageError(page);
if (page->mapping)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ef968306fd5b..87e11d8ad536 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1448,6 +1448,7 @@ static void dissolve_free_huge_page(struct page *page)
list_del(&page->lru);
h->free_huge_pages--;
h->free_huge_pages_node[nid]--;
+ h->max_huge_pages--;
update_and_free_page(h, page);
}
spin_unlock(&hugetlb_lock);
@@ -3942,6 +3943,14 @@ same_page:
return i ? i : -EFAULT;
}
+#ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE
+/*
+ * ARCHes with special requirements for evicting HUGETLB backing TLB entries can
+ * implement this.
+ */
+#define flush_hugetlb_tlb_range(vma, addr, end) flush_tlb_range(vma, addr, end)
+#endif
+
unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
unsigned long address, unsigned long end, pgprot_t newprot)
{
@@ -4002,7 +4011,7 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
* once we release i_mmap_rwsem, another task can do the final put_page
* and that page table be reused and filled with junk.
*/
- flush_tlb_range(vma, start, end);
+ flush_hugetlb_tlb_range(vma, start, end);
mmu_notifier_invalidate_range(mm, start, end);
i_mmap_unlock_write(vma->vm_file->f_mapping);
mmu_notifier_invalidate_range_end(mm, start, end);
diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c
index b6728a33a4ac..baabaad4a4aa 100644
--- a/mm/kasan/quarantine.c
+++ b/mm/kasan/quarantine.c
@@ -217,11 +217,8 @@ void quarantine_reduce(void)
new_quarantine_size = (READ_ONCE(totalram_pages) << PAGE_SHIFT) /
QUARANTINE_FRACTION;
percpu_quarantines = QUARANTINE_PERCPU_SIZE * num_online_cpus();
- if (WARN_ONCE(new_quarantine_size < percpu_quarantines,
- "Too little memory, disabling global KASAN quarantine.\n"))
- new_quarantine_size = 0;
- else
- new_quarantine_size -= percpu_quarantines;
+ new_quarantine_size = (new_quarantine_size < percpu_quarantines) ?
+ 0 : new_quarantine_size - percpu_quarantines;
WRITE_ONCE(quarantine_size, new_quarantine_size);
last = global_quarantine.head;
diff --git a/mm/memblock.c b/mm/memblock.c
index ff5ff3b5f1ea..483197ef613f 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -482,7 +482,7 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type)
* @flags: flags of the new region
*
* Insert new memblock region [@base,@base+@size) into @type at @idx.
- * @type must already have extra room to accomodate the new region.
+ * @type must already have extra room to accommodate the new region.
*/
static void __init_memblock memblock_insert_region(struct memblock_type *type,
int idx, phys_addr_t base,
@@ -544,7 +544,7 @@ repeat:
/*
* The following is executed twice. Once with %false @insert and
* then with %true. The first counts the number of regions needed
- * to accomodate the new area. The second actually inserts them.
+ * to accommodate the new area. The second actually inserts them.
*/
base = obase;
nr_new = 0;
@@ -994,7 +994,10 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
if (*idx == (u64)ULLONG_MAX) {
idx_a = type_a->cnt - 1;
- idx_b = type_b->cnt;
+ if (type_b != NULL)
+ idx_b = type_b->cnt;
+ else
+ idx_b = 0;
}
for (; idx_a >= 0; idx_a--) {
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 66beca1ad92f..2ff0289ad061 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2337,8 +2337,11 @@ int memcg_kmem_charge(struct page *page, gfp_t gfp, int order)
return 0;
memcg = get_mem_cgroup_from_mm(current->mm);
- if (!mem_cgroup_is_root(memcg))
+ if (!mem_cgroup_is_root(memcg)) {
ret = memcg_kmem_charge_memcg(page, gfp, order, memcg);
+ if (!ret)
+ __SetPageKmemcg(page);
+ }
css_put(&memcg->css);
return ret;
}
@@ -2365,6 +2368,11 @@ void memcg_kmem_uncharge(struct page *page, int order)
page_counter_uncharge(&memcg->memsw, nr_pages);
page->mem_cgroup = NULL;
+
+ /* slab pages do not have PageKmemcg flag set */
+ if (PageKmemcg(page))
+ __ClearPageKmemcg(page);
+
css_put_many(&memcg->css, nr_pages);
}
#endif /* !CONFIG_SLOB */
@@ -4069,14 +4077,32 @@ static struct cftype mem_cgroup_legacy_files[] = {
static DEFINE_IDR(mem_cgroup_idr);
-static void mem_cgroup_id_get(struct mem_cgroup *memcg)
+static void mem_cgroup_id_get_many(struct mem_cgroup *memcg, unsigned int n)
{
- atomic_inc(&memcg->id.ref);
+ atomic_add(n, &memcg->id.ref);
}
-static void mem_cgroup_id_put(struct mem_cgroup *memcg)
+static struct mem_cgroup *mem_cgroup_id_get_online(struct mem_cgroup *memcg)
{
- if (atomic_dec_and_test(&memcg->id.ref)) {
+ while (!atomic_inc_not_zero(&memcg->id.ref)) {
+ /*
+ * The root cgroup cannot be destroyed, so it's refcount must
+ * always be >= 1.
+ */
+ if (WARN_ON_ONCE(memcg == root_mem_cgroup)) {
+ VM_BUG_ON(1);
+ break;
+ }
+ memcg = parent_mem_cgroup(memcg);
+ if (!memcg)
+ memcg = root_mem_cgroup;
+ }
+ return memcg;
+}
+
+static void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n)
+{
+ if (atomic_sub_and_test(n, &memcg->id.ref)) {
idr_remove(&mem_cgroup_idr, memcg->id.id);
memcg->id.id = 0;
@@ -4085,6 +4111,16 @@ static void mem_cgroup_id_put(struct mem_cgroup *memcg)
}
}
+static inline void mem_cgroup_id_get(struct mem_cgroup *memcg)
+{
+ mem_cgroup_id_get_many(memcg, 1);
+}
+
+static inline void mem_cgroup_id_put(struct mem_cgroup *memcg)
+{
+ mem_cgroup_id_put_many(memcg, 1);
+}
+
/**
* mem_cgroup_from_id - look up a memcg from a memcg id
* @id: the memcg id to look up
@@ -4719,6 +4755,8 @@ static void __mem_cgroup_clear_mc(void)
if (!mem_cgroup_is_root(mc.from))
page_counter_uncharge(&mc.from->memsw, mc.moved_swap);
+ mem_cgroup_id_put_many(mc.from, mc.moved_swap);
+
/*
* we charged both to->memory and to->memsw, so we
* should uncharge to->memory.
@@ -4726,9 +4764,9 @@ static void __mem_cgroup_clear_mc(void)
if (!mem_cgroup_is_root(mc.to))
page_counter_uncharge(&mc.to->memory, mc.moved_swap);
- css_put_many(&mc.from->css, mc.moved_swap);
+ mem_cgroup_id_get_many(mc.to, mc.moved_swap);
+ css_put_many(&mc.to->css, mc.moved_swap);
- /* we've already done css_get(mc.to) */
mc.moved_swap = 0;
}
memcg_oom_recover(from);
@@ -5537,8 +5575,10 @@ static void uncharge_list(struct list_head *page_list)
else
nr_file += nr_pages;
pgpgout++;
- } else
+ } else {
nr_kmem += 1 << compound_order(page);
+ __ClearPageKmemcg(page);
+ }
page->mem_cgroup = NULL;
} while (next != page_list);
@@ -5790,7 +5830,7 @@ subsys_initcall(mem_cgroup_init);
*/
void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
{
- struct mem_cgroup *memcg;
+ struct mem_cgroup *memcg, *swap_memcg;
unsigned short oldid;
VM_BUG_ON_PAGE(PageLRU(page), page);
@@ -5805,16 +5845,27 @@ void mem_cgroup_swapout(struct page *page, swp_entry_t entry)
if (!memcg)
return;
- mem_cgroup_id_get(memcg);
- oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
+ /*
+ * In case the memcg owning these pages has been offlined and doesn't
+ * have an ID allocated to it anymore, charge the closest online
+ * ancestor for the swap instead and transfer the memory+swap charge.
+ */
+ swap_memcg = mem_cgroup_id_get_online(memcg);
+ oldid = swap_cgroup_record(entry, mem_cgroup_id(swap_memcg));
VM_BUG_ON_PAGE(oldid, page);
- mem_cgroup_swap_statistics(memcg, true);
+ mem_cgroup_swap_statistics(swap_memcg, true);
page->mem_cgroup = NULL;
if (!mem_cgroup_is_root(memcg))
page_counter_uncharge(&memcg->memory, 1);
+ if (memcg != swap_memcg) {
+ if (!mem_cgroup_is_root(swap_memcg))
+ page_counter_charge(&swap_memcg->memsw, 1);
+ page_counter_uncharge(&memcg->memsw, 1);
+ }
+
/*
* Interrupts should be disabled here because the caller holds the
* mapping->tree_lock lock which is taken with interrupts-off. It is
@@ -5853,11 +5904,14 @@ int mem_cgroup_try_charge_swap(struct page *page, swp_entry_t entry)
if (!memcg)
return 0;
+ memcg = mem_cgroup_id_get_online(memcg);
+
if (!mem_cgroup_is_root(memcg) &&
- !page_counter_try_charge(&memcg->swap, 1, &counter))
+ !page_counter_try_charge(&memcg->swap, 1, &counter)) {
+ mem_cgroup_id_put(memcg);
return -ENOMEM;
+ }
- mem_cgroup_id_get(memcg);
oldid = swap_cgroup_record(entry, mem_cgroup_id(memcg));
VM_BUG_ON_PAGE(oldid, page);
mem_cgroup_swap_statistics(memcg, true);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 3894b65b1555..41266dc29f33 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1219,6 +1219,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
/* init node's zones as empty zones, we don't have any present pages.*/
free_area_init_node(nid, zones_size, start_pfn, zholes_size);
+ pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat);
/*
* The node we allocated has no zone fallback lists. For avoiding
@@ -1249,6 +1250,7 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
{
arch_refresh_nodedata(nid, NULL);
+ free_percpu(pgdat->per_cpu_nodestats);
arch_free_nodedata(pgdat);
return;
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 7d0a275df822..d53a9aa00977 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -764,7 +764,7 @@ bool task_will_free_mem(struct task_struct *task)
{
struct mm_struct *mm = task->mm;
struct task_struct *p;
- bool ret;
+ bool ret = true;
/*
* Skip tasks without mm because it might have passed its exit_mm and
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 39a372a2a1d6..3fbe73a6fe4b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1008,10 +1008,8 @@ static __always_inline bool free_pages_prepare(struct page *page,
}
if (PageMappingFlags(page))
page->mapping = NULL;
- if (memcg_kmem_enabled() && PageKmemcg(page)) {
+ if (memcg_kmem_enabled() && PageKmemcg(page))
memcg_kmem_uncharge(page, order);
- __ClearPageKmemcg(page);
- }
if (check_free)
bad += free_pages_check(page);
if (bad)
@@ -3756,12 +3754,10 @@ no_zone:
}
out:
- if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page) {
- if (unlikely(memcg_kmem_charge(page, gfp_mask, order))) {
- __free_pages(page, order);
- page = NULL;
- } else
- __SetPageKmemcg(page);
+ if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page &&
+ unlikely(memcg_kmem_charge(page, gfp_mask, order) != 0)) {
+ __free_pages(page, order);
+ page = NULL;
}
if (kmemcheck_enabled && page)
@@ -4064,7 +4060,7 @@ long si_mem_available(void)
int lru;
for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
- pages[lru] = global_page_state(NR_LRU_BASE + lru);
+ pages[lru] = global_node_page_state(NR_LRU_BASE + lru);
for_each_zone(zone)
wmark_low += zone->watermark[WMARK_LOW];
@@ -4761,6 +4757,8 @@ int local_memory_node(int node)
}
#endif
+static void setup_min_unmapped_ratio(void);
+static void setup_min_slab_ratio(void);
#else /* CONFIG_NUMA */
static void set_zonelist_order(void)
@@ -5257,11 +5255,6 @@ static void __meminit setup_zone_pageset(struct zone *zone)
zone->pageset = alloc_percpu(struct per_cpu_pageset);
for_each_possible_cpu(cpu)
zone_pageset_init(zone, cpu);
-
- if (!zone->zone_pgdat->per_cpu_nodestats) {
- zone->zone_pgdat->per_cpu_nodestats =
- alloc_percpu(struct per_cpu_nodestat);
- }
}
/*
@@ -5270,10 +5263,15 @@ static void __meminit setup_zone_pageset(struct zone *zone)
*/
void __init setup_per_cpu_pageset(void)
{
+ struct pglist_data *pgdat;
struct zone *zone;
for_each_populated_zone(zone)
setup_zone_pageset(zone);
+
+ for_each_online_pgdat(pgdat)
+ pgdat->per_cpu_nodestats =
+ alloc_percpu(struct per_cpu_nodestat);
}
static noinline __ref
@@ -5882,9 +5880,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
zone->managed_pages = is_highmem_idx(j) ? realsize : freesize;
#ifdef CONFIG_NUMA
zone->node = nid;
- pgdat->min_unmapped_pages += (freesize*sysctl_min_unmapped_ratio)
- / 100;
- pgdat->min_slab_pages += (freesize * sysctl_min_slab_ratio) / 100;
#endif
zone->name = zone_names[j];
zone->zone_pgdat = pgdat;
@@ -6805,6 +6800,12 @@ int __meminit init_per_zone_wmark_min(void)
setup_per_zone_wmarks();
refresh_zone_stat_thresholds();
setup_per_zone_lowmem_reserve();
+
+#ifdef CONFIG_NUMA
+ setup_min_unmapped_ratio();
+ setup_min_slab_ratio();
+#endif
+
return 0;
}
core_initcall(init_per_zone_wmark_min)
@@ -6846,43 +6847,58 @@ int watermark_scale_factor_sysctl_handler(struct ctl_table *table, int write,
}
#ifdef CONFIG_NUMA
+static void setup_min_unmapped_ratio(void)
+{
+ pg_data_t *pgdat;
+ struct zone *zone;
+
+ for_each_online_pgdat(pgdat)
+ pgdat->min_unmapped_pages = 0;
+
+ for_each_zone(zone)
+ zone->zone_pgdat->min_unmapped_pages += (zone->managed_pages *
+ sysctl_min_unmapped_ratio) / 100;
+}
+
+
int sysctl_min_unmapped_ratio_sysctl_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *length, loff_t *ppos)
{
- struct pglist_data *pgdat;
- struct zone *zone;
int rc;
rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
if (rc)
return rc;
+ setup_min_unmapped_ratio();
+
+ return 0;
+}
+
+static void setup_min_slab_ratio(void)
+{
+ pg_data_t *pgdat;
+ struct zone *zone;
+
for_each_online_pgdat(pgdat)
pgdat->min_slab_pages = 0;
for_each_zone(zone)
- zone->zone_pgdat->min_unmapped_pages += (zone->managed_pages *
- sysctl_min_unmapped_ratio) / 100;
- return 0;
+ zone->zone_pgdat->min_slab_pages += (zone->managed_pages *
+ sysctl_min_slab_ratio) / 100;
}
int sysctl_min_slab_ratio_sysctl_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *length, loff_t *ppos)
{
- struct pglist_data *pgdat;
- struct zone *zone;
int rc;
rc = proc_dointvec_minmax(table, write, buffer, length, ppos);
if (rc)
return rc;
- for_each_online_pgdat(pgdat)
- pgdat->min_slab_pages = 0;
+ setup_min_slab_ratio();
- for_each_zone(zone)
- zone->zone_pgdat->min_slab_pages += (zone->managed_pages *
- sysctl_min_slab_ratio) / 100;
return 0;
}
#endif
diff --git a/mm/page_io.c b/mm/page_io.c
index fb1fa269d3a0..16bd82fad38c 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -319,9 +319,10 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
ret = -ENOMEM;
goto out;
}
- bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
if (wbc->sync_mode == WB_SYNC_ALL)
- bio->bi_rw |= REQ_SYNC;
+ bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC);
+ else
+ bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
count_vm_event(PSWPOUT);
set_page_writeback(page);
unlock_page(page);
diff --git a/mm/rmap.c b/mm/rmap.c
index 709bc83703b1..1ef36404e7b2 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1284,8 +1284,9 @@ void page_add_file_rmap(struct page *page, bool compound)
VM_BUG_ON_PAGE(!PageSwapBacked(page), page);
__inc_node_page_state(page, NR_SHMEM_PMDMAPPED);
} else {
- if (PageTransCompound(page)) {
- VM_BUG_ON_PAGE(!PageLocked(page), page);
+ if (PageTransCompound(page) && page_mapping(page)) {
+ VM_WARN_ON_ONCE(!PageLocked(page));
+
SetPageDoubleMap(compound_head(page));
if (PageMlocked(page))
clear_page_mlock(compound_head(page));
@@ -1303,7 +1304,7 @@ static void page_remove_file_rmap(struct page *page, bool compound)
{
int i, nr = 1;
- VM_BUG_ON_PAGE(compound && !PageTransHuge(page), page);
+ VM_BUG_ON_PAGE(compound && !PageHead(page), page);
lock_page_memcg(page);
/* Hugepages are not counted in NR_FILE_MAPPED for now. */
diff --git a/mm/shmem.c b/mm/shmem.c
index 2ac19a61d565..fd8b2b5741b1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1362,13 +1362,14 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
struct vm_area_struct pvma;
struct inode *inode = &info->vfs_inode;
struct address_space *mapping = inode->i_mapping;
- pgoff_t idx, hindex = round_down(index, HPAGE_PMD_NR);
+ pgoff_t idx, hindex;
void __rcu **results;
struct page *page;
if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE))
return NULL;
+ hindex = round_down(index, HPAGE_PMD_NR);
rcu_read_lock();
if (radix_tree_gang_lookup_slot(&mapping->page_tree, &results, &idx,
hindex, 1) && idx < hindex + HPAGE_PMD_NR) {
@@ -3974,7 +3975,9 @@ static ssize_t shmem_enabled_store(struct kobject *kobj,
struct kobj_attribute shmem_enabled_attr =
__ATTR(shmem_enabled, 0644, shmem_enabled_show, shmem_enabled_store);
+#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE && CONFIG_SYSFS */
+#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
bool shmem_huge_enabled(struct vm_area_struct *vma)
{
struct inode *inode = file_inode(vma->vm_file);
@@ -4005,7 +4008,7 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
return false;
}
}
-#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE && CONFIG_SYSFS */
+#endif /* CONFIG_TRANSPARENT_HUGE_PAGECACHE */
#else /* !CONFIG_SHMEM */
diff --git a/mm/slab.c b/mm/slab.c
index 261147ba156f..b67271024135 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4441,6 +4441,36 @@ static int __init slab_proc_init(void)
module_init(slab_proc_init);
#endif
+#ifdef CONFIG_HARDENED_USERCOPY
+/*
+ * Rejects objects that are incorrectly sized.
+ *
+ * Returns NULL if check passes, otherwise const char * to name of cache
+ * to indicate an error.
+ */
+const char *__check_heap_object(const void *ptr, unsigned long n,
+ struct page *page)
+{
+ struct kmem_cache *cachep;
+ unsigned int objnr;
+ unsigned long offset;
+
+ /* Find and validate object. */
+ cachep = page->slab_cache;
+ objnr = obj_to_index(cachep, page, (void *)ptr);
+ BUG_ON(objnr >= cachep->num);
+
+ /* Find offset within object. */
+ offset = ptr - index_to_obj(cachep, page, objnr) - obj_offset(cachep);
+
+ /* Allow address range falling entirely within object size. */
+ if (offset <= cachep->object_size && n <= cachep->object_size - offset)
+ return NULL;
+
+ return cachep->name;
+}
+#endif /* CONFIG_HARDENED_USERCOPY */
+
/**
* ksize - get the actual amount of memory allocated for a given object
* @objp: Pointer to the object
diff --git a/mm/slub.c b/mm/slub.c
index 26eb6a99540e..9adae58462f8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -124,7 +124,7 @@ static inline int kmem_cache_debug(struct kmem_cache *s)
#endif
}
-inline void *fixup_red_left(struct kmem_cache *s, void *p)
+void *fixup_red_left(struct kmem_cache *s, void *p)
{
if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE)
p += s->red_left_pad;
@@ -3629,6 +3629,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
*/
static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
{
+ LIST_HEAD(discard);
struct page *page, *h;
BUG_ON(irqs_disabled());
@@ -3636,13 +3637,16 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
list_for_each_entry_safe(page, h, &n->partial, lru) {
if (!page->inuse) {
remove_partial(n, page);
- discard_slab(s, page);
+ list_add(&page->lru, &discard);
} else {
list_slab_objects(s, page,
"Objects remaining in %s on __kmem_cache_shutdown()");
}
}
spin_unlock_irq(&n->list_lock);
+
+ list_for_each_entry_safe(page, h, &discard, lru)
+ discard_slab(s, page);
}
/*
@@ -3764,6 +3768,46 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)
EXPORT_SYMBOL(__kmalloc_node);
#endif
+#ifdef CONFIG_HARDENED_USERCOPY
+/*
+ * Rejects objects that are incorrectly sized.
+ *
+ * Returns NULL if check passes, otherwise const char * to name of cache
+ * to indicate an error.
+ */
+const char *__check_heap_object(const void *ptr, unsigned long n,
+ struct page *page)
+{
+ struct kmem_cache *s;
+ unsigned long offset;
+ size_t object_size;
+
+ /* Find object and usable object size. */
+ s = page->slab_cache;
+ object_size = slab_ksize(s);
+
+ /* Reject impossible pointers. */
+ if (ptr < page_address(page))
+ return s->name;
+
+ /* Find offset within object. */
+ offset = (ptr - page_address(page)) % s->size;
+
+ /* Adjust for redzone and reject if within the redzone. */
+ if (kmem_cache_debug(s) && s->flags & SLAB_RED_ZONE) {
+ if (offset < s->red_left_pad)
+ return s->name;
+ offset -= s->red_left_pad;
+ }
+
+ /* Allow address range falling entirely within object size. */
+ if (offset <= object_size && n <= object_size - offset)
+ return NULL;
+
+ return s->name;
+}
+#endif /* CONFIG_HARDENED_USERCOPY */
+
static size_t __ksize(const void *object)
{
struct page *page;
diff --git a/mm/usercopy.c b/mm/usercopy.c
new file mode 100644
index 000000000000..8ebae91a6b55
--- /dev/null
+++ b/mm/usercopy.c
@@ -0,0 +1,268 @@
+/*
+ * This implements the various checks for CONFIG_HARDENED_USERCOPY*,
+ * which are designed to protect kernel memory from needless exposure
+ * and overwrite under many unintended conditions. This code is based
+ * on PAX_USERCOPY, which is:
+ *
+ * Copyright (C) 2001-2016 PaX Team, Bradley Spengler, Open Source
+ * Security Inc.
+ *
+ * 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/sections.h>
+
+enum {
+ BAD_STACK = -1,
+ NOT_STACK = 0,
+ GOOD_FRAME,
+ GOOD_STACK,
+};
+
+/*
+ * Checks if a given pointer and length is contained by the current
+ * stack frame (if possible).
+ *
+ * Returns:
+ * NOT_STACK: not at all on the stack
+ * GOOD_FRAME: fully within a valid stack frame
+ * GOOD_STACK: fully on the stack (when can't do frame-checking)
+ * BAD_STACK: error condition (invalid stack position or bad stack frame)
+ */
+static noinline int check_stack_object(const void *obj, unsigned long len)
+{
+ const void * const stack = task_stack_page(current);
+ const void * const stackend = stack + THREAD_SIZE;
+ int ret;
+
+ /* Object is not on the stack at all. */
+ if (obj + len <= stack || stackend <= obj)
+ return NOT_STACK;
+
+ /*
+ * Reject: object partially overlaps the stack (passing the
+ * the check above means at least one end is within the stack,
+ * so if this check fails, the other end is outside the stack).
+ */
+ if (obj < stack || stackend < obj + len)
+ return BAD_STACK;
+
+ /* Check if object is safely within a valid frame. */
+ ret = arch_within_stack_frames(stack, stackend, obj, len);
+ if (ret)
+ return ret;
+
+ return GOOD_STACK;
+}
+
+static void report_usercopy(const void *ptr, unsigned long len,
+ bool to_user, const char *type)
+{
+ pr_emerg("kernel memory %s attempt detected %s %p (%s) (%lu bytes)\n",
+ to_user ? "exposure" : "overwrite",
+ to_user ? "from" : "to", ptr, type ? : "unknown", len);
+ /*
+ * For greater effect, it would be nice to do do_group_exit(),
+ * but BUG() actually hooks all the lock-breaking and per-arch
+ * Oops code, so that is used here instead.
+ */
+ BUG();
+}
+
+/* Returns true if any portion of [ptr,ptr+n) over laps with [low,high). */
+static bool overlaps(const void *ptr, unsigned long n, unsigned long low,
+ unsigned long high)
+{
+ unsigned long check_low = (uintptr_t)ptr;
+ unsigned long check_high = check_low + n;
+
+ /* Does not overlap if entirely above or entirely below. */
+ if (check_low >= high || check_high < low)
+ return false;
+
+ return true;
+}
+
+/* Is this address range in the kernel text area? */
+static inline const char *check_kernel_text_object(const void *ptr,
+ unsigned long n)
+{
+ unsigned long textlow = (unsigned long)_stext;
+ unsigned long texthigh = (unsigned long)_etext;
+ unsigned long textlow_linear, texthigh_linear;
+
+ if (overlaps(ptr, n, textlow, texthigh))
+ return "<kernel text>";
+
+ /*
+ * Some architectures have virtual memory mappings with a secondary
+ * mapping of the kernel text, i.e. there is more than one virtual
+ * kernel address that points to the kernel image. It is usually
+ * when there is a separate linear physical memory mapping, in that
+ * __pa() is not just the reverse of __va(). This can be detected
+ * and checked:
+ */
+ textlow_linear = (unsigned long)__va(__pa(textlow));
+ /* No different mapping: we're done. */
+ if (textlow_linear == textlow)
+ return NULL;
+
+ /* Check the secondary mapping... */
+ texthigh_linear = (unsigned long)__va(__pa(texthigh));
+ if (overlaps(ptr, n, textlow_linear, texthigh_linear))
+ return "<linear kernel text>";
+
+ return NULL;
+}
+
+static inline const char *check_bogus_address(const void *ptr, unsigned long n)
+{
+ /* Reject if object wraps past end of memory. */
+ if (ptr + n < ptr)
+ return "<wrapped address>";
+
+ /* Reject if NULL or ZERO-allocation. */
+ if (ZERO_OR_NULL_PTR(ptr))
+ return "<null>";
+
+ return NULL;
+}
+
+static inline const char *check_heap_object(const void *ptr, unsigned long n,
+ bool to_user)
+{
+ struct page *page, *endpage;
+ const void *end = ptr + n - 1;
+ bool is_reserved, is_cma;
+
+ /*
+ * Some architectures (arm64) return true for virt_addr_valid() on
+ * vmalloced addresses. Work around this by checking for vmalloc
+ * first.
+ */
+ if (is_vmalloc_addr(ptr))
+ return NULL;
+
+ if (!virt_addr_valid(ptr))
+ return NULL;
+
+ page = virt_to_head_page(ptr);
+
+ /* Check slab allocator for flags and size. */
+ if (PageSlab(page))
+ return __check_heap_object(ptr, n, page);
+
+ /*
+ * Sometimes the kernel data regions are not marked Reserved (see
+ * check below). And sometimes [_sdata,_edata) does not cover
+ * rodata and/or bss, so check each range explicitly.
+ */
+
+ /* Allow reads of kernel rodata region (if not marked as Reserved). */
+ if (ptr >= (const void *)__start_rodata &&
+ end <= (const void *)__end_rodata) {
+ if (!to_user)
+ return "<rodata>";
+ return NULL;
+ }
+
+ /* Allow kernel data region (if not marked as Reserved). */
+ if (ptr >= (const void *)_sdata && end <= (const void *)_edata)
+ return NULL;
+
+ /* Allow kernel bss region (if not marked as Reserved). */
+ if (ptr >= (const void *)__bss_start &&
+ end <= (const void *)__bss_stop)
+ return NULL;
+
+ /* Is the object wholly within one base page? */
+ if (likely(((unsigned long)ptr & (unsigned long)PAGE_MASK) ==
+ ((unsigned long)end & (unsigned long)PAGE_MASK)))
+ return NULL;
+
+ /* Allow if start and end are inside the same compound page. */
+ endpage = virt_to_head_page(end);
+ if (likely(endpage == page))
+ return NULL;
+
+ /*
+ * Reject if range is entirely either Reserved (i.e. special or
+ * device memory), or CMA. Otherwise, reject since the object spans
+ * several independently allocated pages.
+ */
+ is_reserved = PageReserved(page);
+ is_cma = is_migrate_cma_page(page);
+ if (!is_reserved && !is_cma)
+ goto reject;
+
+ for (ptr += PAGE_SIZE; ptr <= end; ptr += PAGE_SIZE) {
+ page = virt_to_head_page(ptr);
+ if (is_reserved && !PageReserved(page))
+ goto reject;
+ if (is_cma && !is_migrate_cma_page(page))
+ goto reject;
+ }
+
+ return NULL;
+
+reject:
+ return "<spans multiple pages>";
+}
+
+/*
+ * Validates that the given object is:
+ * - not bogus address
+ * - known-safe heap or stack object
+ * - not in kernel text
+ */
+void __check_object_size(const void *ptr, unsigned long n, bool to_user)
+{
+ const char *err;
+
+ /* Skip all tests if size is zero. */
+ if (!n)
+ return;
+
+ /* Check for invalid addresses. */
+ err = check_bogus_address(ptr, n);
+ if (err)
+ goto report;
+
+ /* Check for bad heap object. */
+ err = check_heap_object(ptr, n, to_user);
+ if (err)
+ goto report;
+
+ /* Check for bad stack object. */
+ switch (check_stack_object(ptr, n)) {
+ case NOT_STACK:
+ /* Object is not touching the current process stack. */
+ break;
+ case GOOD_FRAME:
+ case GOOD_STACK:
+ /*
+ * Object is either in the correct frame (when it
+ * is possible to check) or just generally on the
+ * process stack (when frame checking not available).
+ */
+ return;
+ default:
+ err = "<process stack>";
+ goto report;
+ }
+
+ /* Check for object in kernel to avoid text exposure. */
+ err = check_kernel_text_object(ptr, n);
+ if (!err)
+ return;
+
+report:
+ report_usercopy(ptr, n, to_user, err);
+}
+EXPORT_SYMBOL(__check_object_size);
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 4acb1d5417aa..f24b25c25106 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -507,8 +507,8 @@ err_out:
/* wakeup anybody waiting for slots to pin pages */
wake_up(&vp_wq);
}
- kfree(in_pages);
- kfree(out_pages);
+ kvfree(in_pages);
+ kvfree(out_pages);
return err;
}
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index c83326c5ba58..ef34a02719d7 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -574,7 +574,7 @@ static void complete_generic_request(struct ceph_mon_generic_request *req)
put_generic_request(req);
}
-void cancel_generic_request(struct ceph_mon_generic_request *req)
+static void cancel_generic_request(struct ceph_mon_generic_request *req)
{
struct ceph_mon_client *monc = req->monc;
struct ceph_mon_generic_request *lookup_req;
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index b5ec09612ff7..a97e7b506612 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -4220,7 +4220,7 @@ static struct ceph_msg *alloc_msg_with_page_vector(struct ceph_msg_header *hdr)
pages = ceph_alloc_page_vector(calc_pages_for(0, data_len),
GFP_NOIO);
- if (!pages) {
+ if (IS_ERR(pages)) {
ceph_msg_put(m);
return NULL;
}
diff --git a/net/ceph/string_table.c b/net/ceph/string_table.c
index ca53c8319209..22fb96efcf34 100644
--- a/net/ceph/string_table.c
+++ b/net/ceph/string_table.c
@@ -84,12 +84,6 @@ retry:
}
EXPORT_SYMBOL(ceph_find_or_create_string);
-static void ceph_free_string(struct rcu_head *head)
-{
- struct ceph_string *cs = container_of(head, struct ceph_string, rcu);
- kfree(cs);
-}
-
void ceph_release_string(struct kref *ref)
{
struct ceph_string *cs = container_of(ref, struct ceph_string, kref);
@@ -101,7 +95,7 @@ void ceph_release_string(struct kref *ref)
}
spin_unlock(&string_tree_lock);
- call_rcu(&cs->rcu, ceph_free_string);
+ kfree_rcu(cs, rcu);
}
EXPORT_SYMBOL(ceph_release_string);
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 23c8e7c39656..976c7812bbd5 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -340,12 +340,14 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
}
static struct gss_upcall_msg *
-__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid)
+__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth)
{
struct gss_upcall_msg *pos;
list_for_each_entry(pos, &pipe->in_downcall, list) {
if (!uid_eq(pos->uid, uid))
continue;
+ if (auth && pos->auth->service != auth->service)
+ continue;
atomic_inc(&pos->count);
dprintk("RPC: %s found msg %p\n", __func__, pos);
return pos;
@@ -365,7 +367,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
struct gss_upcall_msg *old;
spin_lock(&pipe->lock);
- old = __gss_find_upcall(pipe, gss_msg->uid);
+ old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
if (old == NULL) {
atomic_inc(&gss_msg->count);
list_add(&gss_msg->list, &pipe->in_downcall);
@@ -714,7 +716,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
err = -ENOENT;
/* Find a matching upcall */
spin_lock(&pipe->lock);
- gss_msg = __gss_find_upcall(pipe, uid);
+ gss_msg = __gss_find_upcall(pipe, uid, NULL);
if (gss_msg == NULL) {
spin_unlock(&pipe->lock);
goto err_put_ctx;
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index e085f5ae1548..1d281816f2bf 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1230,8 +1230,9 @@ static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
if (status)
goto out;
- dprintk("RPC: svcauth_gss: gss major status = %d\n",
- ud.major_status);
+ dprintk("RPC: svcauth_gss: gss major status = %d "
+ "minor status = %d\n",
+ ud.major_status, ud.minor_status);
switch (ud.major_status) {
case GSS_S_CONTINUE_NEEDED:
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 553bf95f7003..4d8e11f94a35 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -362,7 +362,7 @@ void sunrpc_destroy_cache_detail(struct cache_detail *cd)
cache_purge(cd);
spin_lock(&cache_list_lock);
write_lock(&cd->hash_lock);
- if (cd->entries || atomic_read(&cd->inuse)) {
+ if (cd->entries) {
write_unlock(&cd->hash_lock);
spin_unlock(&cache_list_lock);
goto out;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index cb49898a5a58..7f79fb7dc6a0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2638,6 +2638,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
{
struct rpc_xprt_switch *xps;
struct rpc_xprt *xprt;
+ unsigned long reconnect_timeout;
unsigned char resvport;
int ret = 0;
@@ -2649,6 +2650,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
return -EAGAIN;
}
resvport = xprt->resvport;
+ reconnect_timeout = xprt->max_reconnect_timeout;
rcu_read_unlock();
xprt = xprt_create_transport(xprtargs);
@@ -2657,6 +2659,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt,
goto out_put_switch;
}
xprt->resvport = resvport;
+ xprt->max_reconnect_timeout = reconnect_timeout;
rpc_xprt_switch_set_roundrobin(xps);
if (setup) {
@@ -2673,6 +2676,27 @@ out_put_switch:
}
EXPORT_SYMBOL_GPL(rpc_clnt_add_xprt);
+static int
+rpc_xprt_cap_max_reconnect_timeout(struct rpc_clnt *clnt,
+ struct rpc_xprt *xprt,
+ void *data)
+{
+ unsigned long timeout = *((unsigned long *)data);
+
+ if (timeout < xprt->max_reconnect_timeout)
+ xprt->max_reconnect_timeout = timeout;
+ return 0;
+}
+
+void
+rpc_cap_max_reconnect_timeout(struct rpc_clnt *clnt, unsigned long timeo)
+{
+ rpc_clnt_iterate_for_each_xprt(clnt,
+ rpc_xprt_cap_max_reconnect_timeout,
+ &timeo);
+}
+EXPORT_SYMBOL_GPL(rpc_cap_max_reconnect_timeout);
+
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
static void rpc_show_header(void)
{
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 4f01f63102ee..c3f652395a80 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -21,6 +21,10 @@
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
+static unsigned int svc_rpc_per_connection_limit __read_mostly;
+module_param(svc_rpc_per_connection_limit, uint, 0644);
+
+
static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
static int svc_deferred_recv(struct svc_rqst *rqstp);
static struct cache_deferred_req *svc_defer(struct cache_req *req);
@@ -329,12 +333,45 @@ char *svc_print_addr(struct svc_rqst *rqstp, char *buf, size_t len)
}
EXPORT_SYMBOL_GPL(svc_print_addr);
+static bool svc_xprt_slots_in_range(struct svc_xprt *xprt)
+{
+ unsigned int limit = svc_rpc_per_connection_limit;
+ int nrqsts = atomic_read(&xprt->xpt_nr_rqsts);
+
+ return limit == 0 || (nrqsts >= 0 && nrqsts < limit);
+}
+
+static bool svc_xprt_reserve_slot(struct svc_rqst *rqstp, struct svc_xprt *xprt)
+{
+ if (!test_bit(RQ_DATA, &rqstp->rq_flags)) {
+ if (!svc_xprt_slots_in_range(xprt))
+ return false;
+ atomic_inc(&xprt->xpt_nr_rqsts);
+ set_bit(RQ_DATA, &rqstp->rq_flags);
+ }
+ return true;
+}
+
+static void svc_xprt_release_slot(struct svc_rqst *rqstp)
+{
+ struct svc_xprt *xprt = rqstp->rq_xprt;
+ if (test_and_clear_bit(RQ_DATA, &rqstp->rq_flags)) {
+ atomic_dec(&xprt->xpt_nr_rqsts);
+ svc_xprt_enqueue(xprt);
+ }
+}
+
static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
{
if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE)))
return true;
- if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED)))
- return xprt->xpt_ops->xpo_has_wspace(xprt);
+ if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) {
+ if (xprt->xpt_ops->xpo_has_wspace(xprt) &&
+ svc_xprt_slots_in_range(xprt))
+ return true;
+ trace_svc_xprt_no_write_space(xprt);
+ return false;
+ }
return false;
}
@@ -480,8 +517,6 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved);
rqstp->rq_reserved = space;
- if (xprt->xpt_ops->xpo_adjust_wspace)
- xprt->xpt_ops->xpo_adjust_wspace(xprt);
svc_xprt_enqueue(xprt);
}
}
@@ -512,8 +547,8 @@ static void svc_xprt_release(struct svc_rqst *rqstp)
rqstp->rq_res.head[0].iov_len = 0;
svc_reserve(rqstp, 0);
+ svc_xprt_release_slot(rqstp);
rqstp->rq_xprt = NULL;
-
svc_xprt_put(xprt);
}
@@ -781,7 +816,7 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
svc_add_new_temp_xprt(serv, newxpt);
else
module_put(xprt->xpt_class->xcl_owner);
- } else {
+ } else if (svc_xprt_reserve_slot(rqstp, xprt)) {
/* XPT_DATA|XPT_DEFERRED case: */
dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
rqstp, rqstp->rq_pool->sp_id, xprt,
@@ -871,6 +906,7 @@ EXPORT_SYMBOL_GPL(svc_recv);
*/
void svc_drop(struct svc_rqst *rqstp)
{
+ trace_svc_drop(rqstp);
dprintk("svc: xprt %p dropped request\n", rqstp->rq_xprt);
svc_xprt_release(rqstp);
}
@@ -1148,6 +1184,7 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
spin_unlock(&xprt->xpt_lock);
dprintk("revisit canceled\n");
svc_xprt_put(xprt);
+ trace_svc_drop_deferred(dr);
kfree(dr);
return;
}
@@ -1205,6 +1242,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
set_bit(RQ_DROPME, &rqstp->rq_flags);
dr->handle.revisit = svc_revisit;
+ trace_svc_defer(rqstp);
return &dr->handle;
}
@@ -1245,6 +1283,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt)
struct svc_deferred_req,
handle.recent);
list_del_init(&dr->handle.recent);
+ trace_svc_revisit_deferred(dr);
} else
clear_bit(XPT_DEFERRED, &xprt->xpt_flags);
spin_unlock(&xprt->xpt_lock);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index dadfec66dbd8..57625f64efd5 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -60,7 +60,6 @@
static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *,
int flags);
-static void svc_udp_data_ready(struct sock *);
static int svc_udp_recvfrom(struct svc_rqst *);
static int svc_udp_sendto(struct svc_rqst *);
static void svc_sock_detach(struct svc_xprt *);
@@ -398,48 +397,21 @@ static int svc_sock_secure_port(struct svc_rqst *rqstp)
return svc_port_is_privileged(svc_addr(rqstp));
}
-static bool sunrpc_waitqueue_active(wait_queue_head_t *wq)
-{
- if (!wq)
- return false;
- /*
- * There should normally be a memory * barrier here--see
- * wq_has_sleeper().
- *
- * It appears that isn't currently necessary, though, basically
- * because callers all appear to have sufficient memory barriers
- * between the time the relevant change is made and the
- * time they call these callbacks.
- *
- * The nfsd code itself doesn't actually explicitly wait on
- * these waitqueues, but it may wait on them for example in
- * sendpage() or sendmsg() calls. (And those may be the only
- * places, since it it uses nonblocking reads.)
- *
- * Maybe we should add the memory barriers anyway, but these are
- * hot paths so we'd need to be convinced there's no sigificant
- * penalty.
- */
- return waitqueue_active(wq);
-}
-
/*
* INET callback when data has been received on the socket.
*/
-static void svc_udp_data_ready(struct sock *sk)
+static void svc_data_ready(struct sock *sk)
{
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- wait_queue_head_t *wq = sk_sleep(sk);
if (svsk) {
dprintk("svc: socket %p(inet %p), busy=%d\n",
svsk, sk,
test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
- set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
- svc_xprt_enqueue(&svsk->sk_xprt);
+ svsk->sk_odata(sk);
+ if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags))
+ svc_xprt_enqueue(&svsk->sk_xprt);
}
- if (sunrpc_waitqueue_active(wq))
- wake_up_interruptible(wq);
}
/*
@@ -448,56 +420,22 @@ static void svc_udp_data_ready(struct sock *sk)
static void svc_write_space(struct sock *sk)
{
struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
- wait_queue_head_t *wq = sk_sleep(sk);
if (svsk) {
dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
+ svsk->sk_owspace(sk);
svc_xprt_enqueue(&svsk->sk_xprt);
}
-
- if (sunrpc_waitqueue_active(wq)) {
- dprintk("RPC svc_write_space: someone sleeping on %p\n",
- svsk);
- wake_up_interruptible(wq);
- }
}
static int svc_tcp_has_wspace(struct svc_xprt *xprt)
{
- struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
- struct svc_serv *serv = svsk->sk_xprt.xpt_server;
- int required;
+ struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
if (test_bit(XPT_LISTENER, &xprt->xpt_flags))
return 1;
- required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg;
- if (sk_stream_wspace(svsk->sk_sk) >= required ||
- (sk_stream_min_wspace(svsk->sk_sk) == 0 &&
- atomic_read(&xprt->xpt_reserved) == 0))
- return 1;
- set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
- return 0;
-}
-
-static void svc_tcp_write_space(struct sock *sk)
-{
- struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data);
- struct socket *sock = sk->sk_socket;
-
- if (!sk_stream_is_writeable(sk) || !sock)
- return;
- if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt))
- clear_bit(SOCK_NOSPACE, &sock->flags);
- svc_write_space(sk);
-}
-
-static void svc_tcp_adjust_wspace(struct svc_xprt *xprt)
-{
- struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
-
- if (svc_tcp_has_wspace(xprt))
- clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
+ return !test_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
}
/*
@@ -746,7 +684,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class,
&svsk->sk_xprt, serv);
clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags);
- svsk->sk_sk->sk_data_ready = svc_udp_data_ready;
+ svsk->sk_sk->sk_data_ready = svc_data_ready;
svsk->sk_sk->sk_write_space = svc_write_space;
/* initialise setting must have enough space to
@@ -786,11 +724,12 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
static void svc_tcp_listen_data_ready(struct sock *sk)
{
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- wait_queue_head_t *wq;
dprintk("svc: socket %p TCP (listen) state change %d\n",
sk, sk->sk_state);
+ if (svsk)
+ svsk->sk_odata(sk);
/*
* This callback may called twice when a new connection
* is established as a child socket inherits everything
@@ -808,10 +747,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
} else
printk("svc: socket %p: no user data\n", sk);
}
-
- wq = sk_sleep(sk);
- if (sunrpc_waitqueue_active(wq))
- wake_up_interruptible_all(wq);
}
/*
@@ -820,7 +755,6 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
static void svc_tcp_state_change(struct sock *sk)
{
struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- wait_queue_head_t *wq = sk_sleep(sk);
dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
sk, sk->sk_state, sk->sk_user_data);
@@ -828,26 +762,12 @@ static void svc_tcp_state_change(struct sock *sk)
if (!svsk)
printk("svc: socket %p: no user data\n", sk);
else {
- set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
- svc_xprt_enqueue(&svsk->sk_xprt);
- }
- if (sunrpc_waitqueue_active(wq))
- wake_up_interruptible_all(wq);
-}
-
-static void svc_tcp_data_ready(struct sock *sk)
-{
- struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
- wait_queue_head_t *wq = sk_sleep(sk);
-
- dprintk("svc: socket %p TCP data ready (svsk %p)\n",
- sk, sk->sk_user_data);
- if (svsk) {
- set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
- svc_xprt_enqueue(&svsk->sk_xprt);
+ svsk->sk_ostate(sk);
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+ svc_xprt_enqueue(&svsk->sk_xprt);
+ }
}
- if (sunrpc_waitqueue_active(wq))
- wake_up_interruptible(wq);
}
/*
@@ -901,6 +821,11 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
dprintk("%s: connect from %s\n", serv->sv_name,
__svc_print_addr(sin, buf, sizeof(buf)));
+ /* Reset the inherited callbacks before calling svc_setup_socket */
+ newsock->sk->sk_state_change = svsk->sk_ostate;
+ newsock->sk->sk_data_ready = svsk->sk_odata;
+ newsock->sk->sk_write_space = svsk->sk_owspace;
+
/* make sure that a write doesn't block forever when
* low on memory
*/
@@ -1317,7 +1242,6 @@ static struct svc_xprt_ops svc_tcp_ops = {
.xpo_has_wspace = svc_tcp_has_wspace,
.xpo_accept = svc_tcp_accept,
.xpo_secure_port = svc_sock_secure_port,
- .xpo_adjust_wspace = svc_tcp_adjust_wspace,
};
static struct svc_xprt_class svc_tcp_class = {
@@ -1357,8 +1281,8 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
} else {
dprintk("setting up TCP socket for reading\n");
sk->sk_state_change = svc_tcp_state_change;
- sk->sk_data_ready = svc_tcp_data_ready;
- sk->sk_write_space = svc_tcp_write_space;
+ sk->sk_data_ready = svc_data_ready;
+ sk->sk_write_space = svc_write_space;
svsk->sk_reclen = 0;
svsk->sk_tcplen = 0;
@@ -1368,8 +1292,13 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv)
tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF;
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
- if (sk->sk_state != TCP_ESTABLISHED)
+ switch (sk->sk_state) {
+ case TCP_SYN_RECV:
+ case TCP_ESTABLISHED:
+ break;
+ default:
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+ }
}
}
@@ -1428,17 +1357,14 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
/* Initialize the socket */
if (sock->type == SOCK_DGRAM)
svc_udp_init(svsk, serv);
- else {
- /* initialise setting must have enough space to
- * receive and respond to one request.
- */
- svc_sock_setbufsize(svsk->sk_sock, 4 * serv->sv_max_mesg,
- 4 * serv->sv_max_mesg);
+ else
svc_tcp_init(svsk, serv);
- }
- dprintk("svc: svc_setup_socket created %p (inet %p)\n",
- svsk, svsk->sk_sk);
+ dprintk("svc: svc_setup_socket created %p (inet %p), "
+ "listen %d close %d\n",
+ svsk, svsk->sk_sk,
+ test_bit(XPT_LISTENER, &svsk->sk_xprt.xpt_flags),
+ test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
return svsk;
}
@@ -1606,18 +1532,16 @@ static void svc_sock_detach(struct svc_xprt *xprt)
{
struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
struct sock *sk = svsk->sk_sk;
- wait_queue_head_t *wq;
dprintk("svc: svc_sock_detach(%p)\n", svsk);
/* put back the old socket callbacks */
+ lock_sock(sk);
sk->sk_state_change = svsk->sk_ostate;
sk->sk_data_ready = svsk->sk_odata;
sk->sk_write_space = svsk->sk_owspace;
-
- wq = sk_sleep(sk);
- if (sunrpc_waitqueue_active(wq))
- wake_up_interruptible(wq);
+ sk->sk_user_data = NULL;
+ release_sock(sk);
}
/*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 8313960cac52..ea244b29138b 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -680,6 +680,20 @@ out:
spin_unlock_bh(&xprt->transport_lock);
}
+static bool
+xprt_has_timer(const struct rpc_xprt *xprt)
+{
+ return xprt->idle_timeout != 0;
+}
+
+static void
+xprt_schedule_autodisconnect(struct rpc_xprt *xprt)
+ __must_hold(&xprt->transport_lock)
+{
+ if (list_empty(&xprt->recv) && xprt_has_timer(xprt))
+ mod_timer(&xprt->timer, xprt->last_used + xprt->idle_timeout);
+}
+
static void
xprt_init_autodisconnect(unsigned long data)
{
@@ -688,6 +702,8 @@ xprt_init_autodisconnect(unsigned long data)
spin_lock(&xprt->transport_lock);
if (!list_empty(&xprt->recv))
goto out_abort;
+ /* Reset xprt->last_used to avoid connect/autodisconnect cycling */
+ xprt->last_used = jiffies;
if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
goto out_abort;
spin_unlock(&xprt->transport_lock);
@@ -725,6 +741,7 @@ void xprt_unlock_connect(struct rpc_xprt *xprt, void *cookie)
goto out;
xprt->snd_task =NULL;
xprt->ops->release_xprt(xprt, NULL);
+ xprt_schedule_autodisconnect(xprt);
out:
spin_unlock_bh(&xprt->transport_lock);
wake_up_bit(&xprt->state, XPRT_LOCKED);
@@ -888,11 +905,6 @@ static void xprt_timer(struct rpc_task *task)
spin_unlock_bh(&xprt->transport_lock);
}
-static inline int xprt_has_timer(struct rpc_xprt *xprt)
-{
- return xprt->idle_timeout != 0;
-}
-
/**
* xprt_prepare_transmit - reserve the transport before sending a request
* @task: RPC task about to send a request
@@ -1280,9 +1292,7 @@ void xprt_release(struct rpc_task *task)
if (!list_empty(&req->rq_list))
list_del(&req->rq_list);
xprt->last_used = jiffies;
- if (list_empty(&xprt->recv) && xprt_has_timer(xprt))
- mod_timer(&xprt->timer,
- xprt->last_used + xprt->idle_timeout);
+ xprt_schedule_autodisconnect(xprt);
spin_unlock_bh(&xprt->transport_lock);
if (req->rq_buffer)
xprt->ops->buf_free(req->rq_buffer);
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 111767ab124a..8ede3bc52481 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -177,7 +177,6 @@ static struct ctl_table sunrpc_table[] = {
* increase over time if the server is down or not responding.
*/
#define XS_TCP_INIT_REEST_TO (3U * HZ)
-#define XS_TCP_MAX_REEST_TO (5U * 60 * HZ)
/*
* TCP idle timeout; client drops the transport socket if it is idle
@@ -2173,6 +2172,8 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
write_unlock_bh(&sk->sk_callback_lock);
}
xs_udp_do_set_buffer_size(xprt);
+
+ xprt->stat.connect_start = jiffies;
}
static void xs_udp_setup_socket(struct work_struct *work)
@@ -2236,6 +2237,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
unsigned int keepcnt = xprt->timeout->to_retries + 1;
unsigned int opt_on = 1;
unsigned int timeo;
+ unsigned int addr_pref = IPV6_PREFER_SRC_PUBLIC;
/* TCP Keepalive options */
kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
@@ -2247,6 +2249,16 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
(char *)&keepcnt, sizeof(keepcnt));
+ /* Avoid temporary address, they are bad for long-lived
+ * connections such as NFS mounts.
+ * RFC4941, section 3.6 suggests that:
+ * Individual applications, which have specific
+ * knowledge about the normal duration of connections,
+ * MAY override this as appropriate.
+ */
+ kernel_setsockopt(sock, SOL_IPV6, IPV6_ADDR_PREFERENCES,
+ (char *)&addr_pref, sizeof(addr_pref));
+
/* TCP user timeout (see RFC5482) */
timeo = jiffies_to_msecs(xprt->timeout->to_initval) *
(xprt->timeout->to_retries + 1);
@@ -2295,6 +2307,10 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
/* SYN_SENT! */
if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+ break;
+ case -EADDRNOTAVAIL:
+ /* Source port number is unavailable. Try a new one! */
+ transport->srcport = 0;
}
out:
return ret;
@@ -2369,6 +2385,25 @@ out:
xprt_wake_pending_tasks(xprt, status);
}
+static unsigned long xs_reconnect_delay(const struct rpc_xprt *xprt)
+{
+ unsigned long start, now = jiffies;
+
+ start = xprt->stat.connect_start + xprt->reestablish_timeout;
+ if (time_after(start, now))
+ return start - now;
+ return 0;
+}
+
+static void xs_reconnect_backoff(struct rpc_xprt *xprt)
+{
+ xprt->reestablish_timeout <<= 1;
+ if (xprt->reestablish_timeout > xprt->max_reconnect_timeout)
+ xprt->reestablish_timeout = xprt->max_reconnect_timeout;
+ if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
+ xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
+}
+
/**
* xs_connect - connect a socket to a remote endpoint
* @xprt: pointer to transport structure
@@ -2386,6 +2421,7 @@ out:
static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
{
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
+ unsigned long delay = 0;
WARN_ON_ONCE(!xprt_lock_connect(xprt, task, transport));
@@ -2397,19 +2433,15 @@ static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
/* Start by resetting any existing state */
xs_reset_transport(transport);
- queue_delayed_work(xprtiod_workqueue,
- &transport->connect_worker,
- xprt->reestablish_timeout);
- xprt->reestablish_timeout <<= 1;
- if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
- xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
- if (xprt->reestablish_timeout > XS_TCP_MAX_REEST_TO)
- xprt->reestablish_timeout = XS_TCP_MAX_REEST_TO;
- } else {
+ delay = xs_reconnect_delay(xprt);
+ xs_reconnect_backoff(xprt);
+
+ } else
dprintk("RPC: xs_connect scheduled xprt %p\n", xprt);
- queue_delayed_work(xprtiod_workqueue,
- &transport->connect_worker, 0);
- }
+
+ queue_delayed_work(xprtiod_workqueue,
+ &transport->connect_worker,
+ delay);
}
/**
@@ -2961,6 +2993,8 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
xprt->ops = &xs_tcp_ops;
xprt->timeout = &xs_tcp_default_timeout;
+ xprt->max_reconnect_timeout = xprt->timeout->to_maxval;
+
INIT_WORK(&transport->recv_worker, xs_tcp_data_receive_workfn);
INIT_DELAYED_WORK(&transport->connect_worker, xs_tcp_setup_socket);
diff --git a/net/vmw_vsock/Kconfig b/net/vmw_vsock/Kconfig
index 14810abedc2e..8831e7c42167 100644
--- a/net/vmw_vsock/Kconfig
+++ b/net/vmw_vsock/Kconfig
@@ -26,3 +26,23 @@ config VMWARE_VMCI_VSOCKETS
To compile this driver as a module, choose M here: the module
will be called vmw_vsock_vmci_transport. If unsure, say N.
+
+config VIRTIO_VSOCKETS
+ tristate "virtio transport for Virtual Sockets"
+ depends on VSOCKETS && VIRTIO
+ select VIRTIO_VSOCKETS_COMMON
+ help
+ This module implements a virtio transport for Virtual Sockets.
+
+ Enable this transport if your Virtual Machine host supports Virtual
+ Sockets over virtio.
+
+ To compile this driver as a module, choose M here: the module will be
+ called vmw_vsock_virtio_transport. If unsure, say N.
+
+config VIRTIO_VSOCKETS_COMMON
+ tristate
+ help
+ This option is selected by any driver which needs to access
+ the virtio_vsock. The module will be called
+ vmw_vsock_virtio_transport_common.
diff --git a/net/vmw_vsock/Makefile b/net/vmw_vsock/Makefile
index 2ce52d70f224..bc27c70e0e59 100644
--- a/net/vmw_vsock/Makefile
+++ b/net/vmw_vsock/Makefile
@@ -1,7 +1,13 @@
obj-$(CONFIG_VSOCKETS) += vsock.o
obj-$(CONFIG_VMWARE_VMCI_VSOCKETS) += vmw_vsock_vmci_transport.o
+obj-$(CONFIG_VIRTIO_VSOCKETS) += vmw_vsock_virtio_transport.o
+obj-$(CONFIG_VIRTIO_VSOCKETS_COMMON) += vmw_vsock_virtio_transport_common.o
vsock-y += af_vsock.o vsock_addr.o
vmw_vsock_vmci_transport-y += vmci_transport.o vmci_transport_notify.o \
vmci_transport_notify_qstate.o
+
+vmw_vsock_virtio_transport-y += virtio_transport.o
+
+vmw_vsock_virtio_transport_common-y += virtio_transport_common.o
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index b96ac918e0ba..17dbbe64cd73 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -344,6 +344,16 @@ static bool vsock_in_connected_table(struct vsock_sock *vsk)
return ret;
}
+void vsock_remove_sock(struct vsock_sock *vsk)
+{
+ if (vsock_in_bound_table(vsk))
+ vsock_remove_bound(vsk);
+
+ if (vsock_in_connected_table(vsk))
+ vsock_remove_connected(vsk);
+}
+EXPORT_SYMBOL_GPL(vsock_remove_sock);
+
void vsock_for_each_connected_socket(void (*fn)(struct sock *sk))
{
int i;
@@ -660,12 +670,6 @@ static void __vsock_release(struct sock *sk)
vsk = vsock_sk(sk);
pending = NULL; /* Compiler warning. */
- if (vsock_in_bound_table(vsk))
- vsock_remove_bound(vsk);
-
- if (vsock_in_connected_table(vsk))
- vsock_remove_connected(vsk);
-
transport->release(vsk);
lock_sock(sk);
@@ -1995,6 +1999,15 @@ void vsock_core_exit(void)
}
EXPORT_SYMBOL_GPL(vsock_core_exit);
+const struct vsock_transport *vsock_core_get_transport(void)
+{
+ /* vsock_register_mutex not taken since only the transport uses this
+ * function and only while registered.
+ */
+ return transport;
+}
+EXPORT_SYMBOL_GPL(vsock_core_get_transport);
+
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Virtual Socket Family");
MODULE_VERSION("1.0.1.0-k");
diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
new file mode 100644
index 000000000000..936d7eee62d0
--- /dev/null
+++ b/net/vmw_vsock/virtio_transport.c
@@ -0,0 +1,620 @@
+/*
+ * virtio transport for vsock
+ *
+ * Copyright (C) 2013-2015 Red Hat, Inc.
+ * Author: Asias He <asias@redhat.com>
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * Some of the code is take from Gerd Hoffmann <kraxel@redhat.com>'s
+ * early virtio-vsock proof-of-concept bits.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/atomic.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_vsock.h>
+#include <net/sock.h>
+#include <linux/mutex.h>
+#include <net/af_vsock.h>
+
+static struct workqueue_struct *virtio_vsock_workqueue;
+static struct virtio_vsock *the_virtio_vsock;
+static DEFINE_MUTEX(the_virtio_vsock_mutex); /* protects the_virtio_vsock */
+
+struct virtio_vsock {
+ struct virtio_device *vdev;
+ struct virtqueue *vqs[VSOCK_VQ_MAX];
+
+ /* Virtqueue processing is deferred to a workqueue */
+ struct work_struct tx_work;
+ struct work_struct rx_work;
+ struct work_struct event_work;
+
+ /* The following fields are protected by tx_lock. vqs[VSOCK_VQ_TX]
+ * must be accessed with tx_lock held.
+ */
+ struct mutex tx_lock;
+
+ struct work_struct send_pkt_work;
+ spinlock_t send_pkt_list_lock;
+ struct list_head send_pkt_list;
+
+ atomic_t queued_replies;
+
+ /* The following fields are protected by rx_lock. vqs[VSOCK_VQ_RX]
+ * must be accessed with rx_lock held.
+ */
+ struct mutex rx_lock;
+ int rx_buf_nr;
+ int rx_buf_max_nr;
+
+ /* The following fields are protected by event_lock.
+ * vqs[VSOCK_VQ_EVENT] must be accessed with event_lock held.
+ */
+ struct mutex event_lock;
+ struct virtio_vsock_event event_list[8];
+
+ u32 guest_cid;
+};
+
+static struct virtio_vsock *virtio_vsock_get(void)
+{
+ return the_virtio_vsock;
+}
+
+static u32 virtio_transport_get_local_cid(void)
+{
+ struct virtio_vsock *vsock = virtio_vsock_get();
+
+ return vsock->guest_cid;
+}
+
+static void
+virtio_transport_send_pkt_work(struct work_struct *work)
+{
+ struct virtio_vsock *vsock =
+ container_of(work, struct virtio_vsock, send_pkt_work);
+ struct virtqueue *vq;
+ bool added = false;
+ bool restart_rx = false;
+
+ mutex_lock(&vsock->tx_lock);
+
+ vq = vsock->vqs[VSOCK_VQ_TX];
+
+ for (;;) {
+ struct virtio_vsock_pkt *pkt;
+ struct scatterlist hdr, buf, *sgs[2];
+ int ret, in_sg = 0, out_sg = 0;
+ bool reply;
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ if (list_empty(&vsock->send_pkt_list)) {
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+ break;
+ }
+
+ pkt = list_first_entry(&vsock->send_pkt_list,
+ struct virtio_vsock_pkt, list);
+ list_del_init(&pkt->list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ reply = pkt->reply;
+
+ sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr));
+ sgs[out_sg++] = &hdr;
+ if (pkt->buf) {
+ sg_init_one(&buf, pkt->buf, pkt->len);
+ sgs[out_sg++] = &buf;
+ }
+
+ ret = virtqueue_add_sgs(vq, sgs, out_sg, in_sg, pkt, GFP_KERNEL);
+ /* Usually this means that there is no more space available in
+ * the vq
+ */
+ if (ret < 0) {
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ list_add(&pkt->list, &vsock->send_pkt_list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+ break;
+ }
+
+ if (reply) {
+ struct virtqueue *rx_vq = vsock->vqs[VSOCK_VQ_RX];
+ int val;
+
+ val = atomic_dec_return(&vsock->queued_replies);
+
+ /* Do we now have resources to resume rx processing? */
+ if (val + 1 == virtqueue_get_vring_size(rx_vq))
+ restart_rx = true;
+ }
+
+ added = true;
+ }
+
+ if (added)
+ virtqueue_kick(vq);
+
+ mutex_unlock(&vsock->tx_lock);
+
+ if (restart_rx)
+ queue_work(virtio_vsock_workqueue, &vsock->rx_work);
+}
+
+static int
+virtio_transport_send_pkt(struct virtio_vsock_pkt *pkt)
+{
+ struct virtio_vsock *vsock;
+ int len = pkt->len;
+
+ vsock = virtio_vsock_get();
+ if (!vsock) {
+ virtio_transport_free_pkt(pkt);
+ return -ENODEV;
+ }
+
+ if (pkt->reply)
+ atomic_inc(&vsock->queued_replies);
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ list_add_tail(&pkt->list, &vsock->send_pkt_list);
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ queue_work(virtio_vsock_workqueue, &vsock->send_pkt_work);
+ return len;
+}
+
+static void virtio_vsock_rx_fill(struct virtio_vsock *vsock)
+{
+ int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE;
+ struct virtio_vsock_pkt *pkt;
+ struct scatterlist hdr, buf, *sgs[2];
+ struct virtqueue *vq;
+ int ret;
+
+ vq = vsock->vqs[VSOCK_VQ_RX];
+
+ do {
+ pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
+ if (!pkt)
+ break;
+
+ pkt->buf = kmalloc(buf_len, GFP_KERNEL);
+ if (!pkt->buf) {
+ virtio_transport_free_pkt(pkt);
+ break;
+ }
+
+ pkt->len = buf_len;
+
+ sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr));
+ sgs[0] = &hdr;
+
+ sg_init_one(&buf, pkt->buf, buf_len);
+ sgs[1] = &buf;
+ ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL);
+ if (ret) {
+ virtio_transport_free_pkt(pkt);
+ break;
+ }
+ vsock->rx_buf_nr++;
+ } while (vq->num_free);
+ if (vsock->rx_buf_nr > vsock->rx_buf_max_nr)
+ vsock->rx_buf_max_nr = vsock->rx_buf_nr;
+ virtqueue_kick(vq);
+}
+
+static void virtio_transport_tx_work(struct work_struct *work)
+{
+ struct virtio_vsock *vsock =
+ container_of(work, struct virtio_vsock, tx_work);
+ struct virtqueue *vq;
+ bool added = false;
+
+ vq = vsock->vqs[VSOCK_VQ_TX];
+ mutex_lock(&vsock->tx_lock);
+ do {
+ struct virtio_vsock_pkt *pkt;
+ unsigned int len;
+
+ virtqueue_disable_cb(vq);
+ while ((pkt = virtqueue_get_buf(vq, &len)) != NULL) {
+ virtio_transport_free_pkt(pkt);
+ added = true;
+ }
+ } while (!virtqueue_enable_cb(vq));
+ mutex_unlock(&vsock->tx_lock);
+
+ if (added)
+ queue_work(virtio_vsock_workqueue, &vsock->send_pkt_work);
+}
+
+/* Is there space left for replies to rx packets? */
+static bool virtio_transport_more_replies(struct virtio_vsock *vsock)
+{
+ struct virtqueue *vq = vsock->vqs[VSOCK_VQ_RX];
+ int val;
+
+ smp_rmb(); /* paired with atomic_inc() and atomic_dec_return() */
+ val = atomic_read(&vsock->queued_replies);
+
+ return val < virtqueue_get_vring_size(vq);
+}
+
+static void virtio_transport_rx_work(struct work_struct *work)
+{
+ struct virtio_vsock *vsock =
+ container_of(work, struct virtio_vsock, rx_work);
+ struct virtqueue *vq;
+
+ vq = vsock->vqs[VSOCK_VQ_RX];
+
+ mutex_lock(&vsock->rx_lock);
+
+ do {
+ virtqueue_disable_cb(vq);
+ for (;;) {
+ struct virtio_vsock_pkt *pkt;
+ unsigned int len;
+
+ if (!virtio_transport_more_replies(vsock)) {
+ /* Stop rx until the device processes already
+ * pending replies. Leave rx virtqueue
+ * callbacks disabled.
+ */
+ goto out;
+ }
+
+ pkt = virtqueue_get_buf(vq, &len);
+ if (!pkt) {
+ break;
+ }
+
+ vsock->rx_buf_nr--;
+
+ /* Drop short/long packets */
+ if (unlikely(len < sizeof(pkt->hdr) ||
+ len > sizeof(pkt->hdr) + pkt->len)) {
+ virtio_transport_free_pkt(pkt);
+ continue;
+ }
+
+ pkt->len = len - sizeof(pkt->hdr);
+ virtio_transport_recv_pkt(pkt);
+ }
+ } while (!virtqueue_enable_cb(vq));
+
+out:
+ if (vsock->rx_buf_nr < vsock->rx_buf_max_nr / 2)
+ virtio_vsock_rx_fill(vsock);
+ mutex_unlock(&vsock->rx_lock);
+}
+
+/* event_lock must be held */
+static int virtio_vsock_event_fill_one(struct virtio_vsock *vsock,
+ struct virtio_vsock_event *event)
+{
+ struct scatterlist sg;
+ struct virtqueue *vq;
+
+ vq = vsock->vqs[VSOCK_VQ_EVENT];
+
+ sg_init_one(&sg, event, sizeof(*event));
+
+ return virtqueue_add_inbuf(vq, &sg, 1, event, GFP_KERNEL);
+}
+
+/* event_lock must be held */
+static void virtio_vsock_event_fill(struct virtio_vsock *vsock)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(vsock->event_list); i++) {
+ struct virtio_vsock_event *event = &vsock->event_list[i];
+
+ virtio_vsock_event_fill_one(vsock, event);
+ }
+
+ virtqueue_kick(vsock->vqs[VSOCK_VQ_EVENT]);
+}
+
+static void virtio_vsock_reset_sock(struct sock *sk)
+{
+ lock_sock(sk);
+ sk->sk_state = SS_UNCONNECTED;
+ sk->sk_err = ECONNRESET;
+ sk->sk_error_report(sk);
+ release_sock(sk);
+}
+
+static void virtio_vsock_update_guest_cid(struct virtio_vsock *vsock)
+{
+ struct virtio_device *vdev = vsock->vdev;
+ u64 guest_cid;
+
+ vdev->config->get(vdev, offsetof(struct virtio_vsock_config, guest_cid),
+ &guest_cid, sizeof(guest_cid));
+ vsock->guest_cid = le64_to_cpu(guest_cid);
+}
+
+/* event_lock must be held */
+static void virtio_vsock_event_handle(struct virtio_vsock *vsock,
+ struct virtio_vsock_event *event)
+{
+ switch (le32_to_cpu(event->id)) {
+ case VIRTIO_VSOCK_EVENT_TRANSPORT_RESET:
+ virtio_vsock_update_guest_cid(vsock);
+ vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+ break;
+ }
+}
+
+static void virtio_transport_event_work(struct work_struct *work)
+{
+ struct virtio_vsock *vsock =
+ container_of(work, struct virtio_vsock, event_work);
+ struct virtqueue *vq;
+
+ vq = vsock->vqs[VSOCK_VQ_EVENT];
+
+ mutex_lock(&vsock->event_lock);
+
+ do {
+ struct virtio_vsock_event *event;
+ unsigned int len;
+
+ virtqueue_disable_cb(vq);
+ while ((event = virtqueue_get_buf(vq, &len)) != NULL) {
+ if (len == sizeof(*event))
+ virtio_vsock_event_handle(vsock, event);
+
+ virtio_vsock_event_fill_one(vsock, event);
+ }
+ } while (!virtqueue_enable_cb(vq));
+
+ virtqueue_kick(vsock->vqs[VSOCK_VQ_EVENT]);
+
+ mutex_unlock(&vsock->event_lock);
+}
+
+static void virtio_vsock_event_done(struct virtqueue *vq)
+{
+ struct virtio_vsock *vsock = vq->vdev->priv;
+
+ if (!vsock)
+ return;
+ queue_work(virtio_vsock_workqueue, &vsock->event_work);
+}
+
+static void virtio_vsock_tx_done(struct virtqueue *vq)
+{
+ struct virtio_vsock *vsock = vq->vdev->priv;
+
+ if (!vsock)
+ return;
+ queue_work(virtio_vsock_workqueue, &vsock->tx_work);
+}
+
+static void virtio_vsock_rx_done(struct virtqueue *vq)
+{
+ struct virtio_vsock *vsock = vq->vdev->priv;
+
+ if (!vsock)
+ return;
+ queue_work(virtio_vsock_workqueue, &vsock->rx_work);
+}
+
+static struct virtio_transport virtio_transport = {
+ .transport = {
+ .get_local_cid = virtio_transport_get_local_cid,
+
+ .init = virtio_transport_do_socket_init,
+ .destruct = virtio_transport_destruct,
+ .release = virtio_transport_release,
+ .connect = virtio_transport_connect,
+ .shutdown = virtio_transport_shutdown,
+
+ .dgram_bind = virtio_transport_dgram_bind,
+ .dgram_dequeue = virtio_transport_dgram_dequeue,
+ .dgram_enqueue = virtio_transport_dgram_enqueue,
+ .dgram_allow = virtio_transport_dgram_allow,
+
+ .stream_dequeue = virtio_transport_stream_dequeue,
+ .stream_enqueue = virtio_transport_stream_enqueue,
+ .stream_has_data = virtio_transport_stream_has_data,
+ .stream_has_space = virtio_transport_stream_has_space,
+ .stream_rcvhiwat = virtio_transport_stream_rcvhiwat,
+ .stream_is_active = virtio_transport_stream_is_active,
+ .stream_allow = virtio_transport_stream_allow,
+
+ .notify_poll_in = virtio_transport_notify_poll_in,
+ .notify_poll_out = virtio_transport_notify_poll_out,
+ .notify_recv_init = virtio_transport_notify_recv_init,
+ .notify_recv_pre_block = virtio_transport_notify_recv_pre_block,
+ .notify_recv_pre_dequeue = virtio_transport_notify_recv_pre_dequeue,
+ .notify_recv_post_dequeue = virtio_transport_notify_recv_post_dequeue,
+ .notify_send_init = virtio_transport_notify_send_init,
+ .notify_send_pre_block = virtio_transport_notify_send_pre_block,
+ .notify_send_pre_enqueue = virtio_transport_notify_send_pre_enqueue,
+ .notify_send_post_enqueue = virtio_transport_notify_send_post_enqueue,
+
+ .set_buffer_size = virtio_transport_set_buffer_size,
+ .set_min_buffer_size = virtio_transport_set_min_buffer_size,
+ .set_max_buffer_size = virtio_transport_set_max_buffer_size,
+ .get_buffer_size = virtio_transport_get_buffer_size,
+ .get_min_buffer_size = virtio_transport_get_min_buffer_size,
+ .get_max_buffer_size = virtio_transport_get_max_buffer_size,
+ },
+
+ .send_pkt = virtio_transport_send_pkt,
+};
+
+static int virtio_vsock_probe(struct virtio_device *vdev)
+{
+ vq_callback_t *callbacks[] = {
+ virtio_vsock_rx_done,
+ virtio_vsock_tx_done,
+ virtio_vsock_event_done,
+ };
+ static const char * const names[] = {
+ "rx",
+ "tx",
+ "event",
+ };
+ struct virtio_vsock *vsock = NULL;
+ int ret;
+
+ ret = mutex_lock_interruptible(&the_virtio_vsock_mutex);
+ if (ret)
+ return ret;
+
+ /* Only one virtio-vsock device per guest is supported */
+ if (the_virtio_vsock) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ vsock = kzalloc(sizeof(*vsock), GFP_KERNEL);
+ if (!vsock) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ vsock->vdev = vdev;
+
+ ret = vsock->vdev->config->find_vqs(vsock->vdev, VSOCK_VQ_MAX,
+ vsock->vqs, callbacks, names);
+ if (ret < 0)
+ goto out;
+
+ virtio_vsock_update_guest_cid(vsock);
+
+ ret = vsock_core_init(&virtio_transport.transport);
+ if (ret < 0)
+ goto out_vqs;
+
+ vsock->rx_buf_nr = 0;
+ vsock->rx_buf_max_nr = 0;
+ atomic_set(&vsock->queued_replies, 0);
+
+ vdev->priv = vsock;
+ the_virtio_vsock = vsock;
+ mutex_init(&vsock->tx_lock);
+ mutex_init(&vsock->rx_lock);
+ mutex_init(&vsock->event_lock);
+ spin_lock_init(&vsock->send_pkt_list_lock);
+ INIT_LIST_HEAD(&vsock->send_pkt_list);
+ INIT_WORK(&vsock->rx_work, virtio_transport_rx_work);
+ INIT_WORK(&vsock->tx_work, virtio_transport_tx_work);
+ INIT_WORK(&vsock->event_work, virtio_transport_event_work);
+ INIT_WORK(&vsock->send_pkt_work, virtio_transport_send_pkt_work);
+
+ mutex_lock(&vsock->rx_lock);
+ virtio_vsock_rx_fill(vsock);
+ mutex_unlock(&vsock->rx_lock);
+
+ mutex_lock(&vsock->event_lock);
+ virtio_vsock_event_fill(vsock);
+ mutex_unlock(&vsock->event_lock);
+
+ mutex_unlock(&the_virtio_vsock_mutex);
+ return 0;
+
+out_vqs:
+ vsock->vdev->config->del_vqs(vsock->vdev);
+out:
+ kfree(vsock);
+ mutex_unlock(&the_virtio_vsock_mutex);
+ return ret;
+}
+
+static void virtio_vsock_remove(struct virtio_device *vdev)
+{
+ struct virtio_vsock *vsock = vdev->priv;
+ struct virtio_vsock_pkt *pkt;
+
+ flush_work(&vsock->rx_work);
+ flush_work(&vsock->tx_work);
+ flush_work(&vsock->event_work);
+ flush_work(&vsock->send_pkt_work);
+
+ vdev->config->reset(vdev);
+
+ mutex_lock(&vsock->rx_lock);
+ while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_RX])))
+ virtio_transport_free_pkt(pkt);
+ mutex_unlock(&vsock->rx_lock);
+
+ mutex_lock(&vsock->tx_lock);
+ while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_TX])))
+ virtio_transport_free_pkt(pkt);
+ mutex_unlock(&vsock->tx_lock);
+
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ while (!list_empty(&vsock->send_pkt_list)) {
+ pkt = list_first_entry(&vsock->send_pkt_list,
+ struct virtio_vsock_pkt, list);
+ list_del(&pkt->list);
+ virtio_transport_free_pkt(pkt);
+ }
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+
+ mutex_lock(&the_virtio_vsock_mutex);
+ the_virtio_vsock = NULL;
+ vsock_core_exit();
+ mutex_unlock(&the_virtio_vsock_mutex);
+
+ vdev->config->del_vqs(vdev);
+
+ kfree(vsock);
+}
+
+static struct virtio_device_id id_table[] = {
+ { VIRTIO_ID_VSOCK, VIRTIO_DEV_ANY_ID },
+ { 0 },
+};
+
+static unsigned int features[] = {
+};
+
+static struct virtio_driver virtio_vsock_driver = {
+ .feature_table = features,
+ .feature_table_size = ARRAY_SIZE(features),
+ .driver.name = KBUILD_MODNAME,
+ .driver.owner = THIS_MODULE,
+ .id_table = id_table,
+ .probe = virtio_vsock_probe,
+ .remove = virtio_vsock_remove,
+};
+
+static int __init virtio_vsock_init(void)
+{
+ int ret;
+
+ virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0);
+ if (!virtio_vsock_workqueue)
+ return -ENOMEM;
+ ret = register_virtio_driver(&virtio_vsock_driver);
+ if (ret)
+ destroy_workqueue(virtio_vsock_workqueue);
+ return ret;
+}
+
+static void __exit virtio_vsock_exit(void)
+{
+ unregister_virtio_driver(&virtio_vsock_driver);
+ destroy_workqueue(virtio_vsock_workqueue);
+}
+
+module_init(virtio_vsock_init);
+module_exit(virtio_vsock_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Asias He");
+MODULE_DESCRIPTION("virtio transport for vsock");
+MODULE_DEVICE_TABLE(virtio, id_table);
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
new file mode 100644
index 000000000000..a53b3a16b4f1
--- /dev/null
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -0,0 +1,992 @@
+/*
+ * common code for virtio vsock
+ *
+ * Copyright (C) 2013-2015 Red Hat, Inc.
+ * Author: Asias He <asias@redhat.com>
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_vsock.h>
+
+#include <net/sock.h>
+#include <net/af_vsock.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/vsock_virtio_transport_common.h>
+
+/* How long to wait for graceful shutdown of a connection */
+#define VSOCK_CLOSE_TIMEOUT (8 * HZ)
+
+static const struct virtio_transport *virtio_transport_get_ops(void)
+{
+ const struct vsock_transport *t = vsock_core_get_transport();
+
+ return container_of(t, struct virtio_transport, transport);
+}
+
+struct virtio_vsock_pkt *
+virtio_transport_alloc_pkt(struct virtio_vsock_pkt_info *info,
+ size_t len,
+ u32 src_cid,
+ u32 src_port,
+ u32 dst_cid,
+ u32 dst_port)
+{
+ struct virtio_vsock_pkt *pkt;
+ int err;
+
+ pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
+ if (!pkt)
+ return NULL;
+
+ pkt->hdr.type = cpu_to_le16(info->type);
+ pkt->hdr.op = cpu_to_le16(info->op);
+ pkt->hdr.src_cid = cpu_to_le64(src_cid);
+ pkt->hdr.dst_cid = cpu_to_le64(dst_cid);
+ pkt->hdr.src_port = cpu_to_le32(src_port);
+ pkt->hdr.dst_port = cpu_to_le32(dst_port);
+ pkt->hdr.flags = cpu_to_le32(info->flags);
+ pkt->len = len;
+ pkt->hdr.len = cpu_to_le32(len);
+ pkt->reply = info->reply;
+
+ if (info->msg && len > 0) {
+ pkt->buf = kmalloc(len, GFP_KERNEL);
+ if (!pkt->buf)
+ goto out_pkt;
+ err = memcpy_from_msg(pkt->buf, info->msg, len);
+ if (err)
+ goto out;
+ }
+
+ trace_virtio_transport_alloc_pkt(src_cid, src_port,
+ dst_cid, dst_port,
+ len,
+ info->type,
+ info->op,
+ info->flags);
+
+ return pkt;
+
+out:
+ kfree(pkt->buf);
+out_pkt:
+ kfree(pkt);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_alloc_pkt);
+
+static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
+ struct virtio_vsock_pkt_info *info)
+{
+ u32 src_cid, src_port, dst_cid, dst_port;
+ struct virtio_vsock_sock *vvs;
+ struct virtio_vsock_pkt *pkt;
+ u32 pkt_len = info->pkt_len;
+
+ src_cid = vm_sockets_get_local_cid();
+ src_port = vsk->local_addr.svm_port;
+ if (!info->remote_cid) {
+ dst_cid = vsk->remote_addr.svm_cid;
+ dst_port = vsk->remote_addr.svm_port;
+ } else {
+ dst_cid = info->remote_cid;
+ dst_port = info->remote_port;
+ }
+
+ vvs = vsk->trans;
+
+ /* we can send less than pkt_len bytes */
+ if (pkt_len > VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE)
+ pkt_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE;
+
+ /* virtio_transport_get_credit might return less than pkt_len credit */
+ pkt_len = virtio_transport_get_credit(vvs, pkt_len);
+
+ /* Do not send zero length OP_RW pkt */
+ if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW)
+ return pkt_len;
+
+ pkt = virtio_transport_alloc_pkt(info, pkt_len,
+ src_cid, src_port,
+ dst_cid, dst_port);
+ if (!pkt) {
+ virtio_transport_put_credit(vvs, pkt_len);
+ return -ENOMEM;
+ }
+
+ virtio_transport_inc_tx_pkt(vvs, pkt);
+
+ return virtio_transport_get_ops()->send_pkt(pkt);
+}
+
+static void virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
+ struct virtio_vsock_pkt *pkt)
+{
+ vvs->rx_bytes += pkt->len;
+}
+
+static void virtio_transport_dec_rx_pkt(struct virtio_vsock_sock *vvs,
+ struct virtio_vsock_pkt *pkt)
+{
+ vvs->rx_bytes -= pkt->len;
+ vvs->fwd_cnt += pkt->len;
+}
+
+void virtio_transport_inc_tx_pkt(struct virtio_vsock_sock *vvs, struct virtio_vsock_pkt *pkt)
+{
+ spin_lock_bh(&vvs->tx_lock);
+ pkt->hdr.fwd_cnt = cpu_to_le32(vvs->fwd_cnt);
+ pkt->hdr.buf_alloc = cpu_to_le32(vvs->buf_alloc);
+ spin_unlock_bh(&vvs->tx_lock);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_inc_tx_pkt);
+
+u32 virtio_transport_get_credit(struct virtio_vsock_sock *vvs, u32 credit)
+{
+ u32 ret;
+
+ spin_lock_bh(&vvs->tx_lock);
+ ret = vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt);
+ if (ret > credit)
+ ret = credit;
+ vvs->tx_cnt += ret;
+ spin_unlock_bh(&vvs->tx_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_get_credit);
+
+void virtio_transport_put_credit(struct virtio_vsock_sock *vvs, u32 credit)
+{
+ spin_lock_bh(&vvs->tx_lock);
+ vvs->tx_cnt -= credit;
+ spin_unlock_bh(&vvs->tx_lock);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_put_credit);
+
+static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
+ int type,
+ struct virtio_vsock_hdr *hdr)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_CREDIT_UPDATE,
+ .type = type,
+ };
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+
+static ssize_t
+virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ struct virtio_vsock_pkt *pkt;
+ size_t bytes, total = 0;
+ int err = -EFAULT;
+
+ spin_lock_bh(&vvs->rx_lock);
+ while (total < len && !list_empty(&vvs->rx_queue)) {
+ pkt = list_first_entry(&vvs->rx_queue,
+ struct virtio_vsock_pkt, list);
+
+ bytes = len - total;
+ if (bytes > pkt->len - pkt->off)
+ bytes = pkt->len - pkt->off;
+
+ /* sk_lock is held by caller so no one else can dequeue.
+ * Unlock rx_lock since memcpy_to_msg() may sleep.
+ */
+ spin_unlock_bh(&vvs->rx_lock);
+
+ err = memcpy_to_msg(msg, pkt->buf + pkt->off, bytes);
+ if (err)
+ goto out;
+
+ spin_lock_bh(&vvs->rx_lock);
+
+ total += bytes;
+ pkt->off += bytes;
+ if (pkt->off == pkt->len) {
+ virtio_transport_dec_rx_pkt(vvs, pkt);
+ list_del(&pkt->list);
+ virtio_transport_free_pkt(pkt);
+ }
+ }
+ spin_unlock_bh(&vvs->rx_lock);
+
+ /* Send a credit pkt to peer */
+ virtio_transport_send_credit_update(vsk, VIRTIO_VSOCK_TYPE_STREAM,
+ NULL);
+
+ return total;
+
+out:
+ if (total)
+ err = total;
+ return err;
+}
+
+ssize_t
+virtio_transport_stream_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len, int flags)
+{
+ if (flags & MSG_PEEK)
+ return -EOPNOTSUPP;
+
+ return virtio_transport_stream_do_dequeue(vsk, msg, len);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_dequeue);
+
+int
+virtio_transport_dgram_dequeue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len, int flags)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_dgram_dequeue);
+
+s64 virtio_transport_stream_has_data(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ s64 bytes;
+
+ spin_lock_bh(&vvs->rx_lock);
+ bytes = vvs->rx_bytes;
+ spin_unlock_bh(&vvs->rx_lock);
+
+ return bytes;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_has_data);
+
+static s64 virtio_transport_has_space(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ s64 bytes;
+
+ bytes = vvs->peer_buf_alloc - (vvs->tx_cnt - vvs->peer_fwd_cnt);
+ if (bytes < 0)
+ bytes = 0;
+
+ return bytes;
+}
+
+s64 virtio_transport_stream_has_space(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ s64 bytes;
+
+ spin_lock_bh(&vvs->tx_lock);
+ bytes = virtio_transport_has_space(vsk);
+ spin_unlock_bh(&vvs->tx_lock);
+
+ return bytes;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_has_space);
+
+int virtio_transport_do_socket_init(struct vsock_sock *vsk,
+ struct vsock_sock *psk)
+{
+ struct virtio_vsock_sock *vvs;
+
+ vvs = kzalloc(sizeof(*vvs), GFP_KERNEL);
+ if (!vvs)
+ return -ENOMEM;
+
+ vsk->trans = vvs;
+ vvs->vsk = vsk;
+ if (psk) {
+ struct virtio_vsock_sock *ptrans = psk->trans;
+
+ vvs->buf_size = ptrans->buf_size;
+ vvs->buf_size_min = ptrans->buf_size_min;
+ vvs->buf_size_max = ptrans->buf_size_max;
+ vvs->peer_buf_alloc = ptrans->peer_buf_alloc;
+ } else {
+ vvs->buf_size = VIRTIO_VSOCK_DEFAULT_BUF_SIZE;
+ vvs->buf_size_min = VIRTIO_VSOCK_DEFAULT_MIN_BUF_SIZE;
+ vvs->buf_size_max = VIRTIO_VSOCK_DEFAULT_MAX_BUF_SIZE;
+ }
+
+ vvs->buf_alloc = vvs->buf_size;
+
+ spin_lock_init(&vvs->rx_lock);
+ spin_lock_init(&vvs->tx_lock);
+ INIT_LIST_HEAD(&vvs->rx_queue);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_do_socket_init);
+
+u64 virtio_transport_get_buffer_size(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ return vvs->buf_size;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_get_buffer_size);
+
+u64 virtio_transport_get_min_buffer_size(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ return vvs->buf_size_min;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_get_min_buffer_size);
+
+u64 virtio_transport_get_max_buffer_size(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ return vvs->buf_size_max;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_get_max_buffer_size);
+
+void virtio_transport_set_buffer_size(struct vsock_sock *vsk, u64 val)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ if (val > VIRTIO_VSOCK_MAX_BUF_SIZE)
+ val = VIRTIO_VSOCK_MAX_BUF_SIZE;
+ if (val < vvs->buf_size_min)
+ vvs->buf_size_min = val;
+ if (val > vvs->buf_size_max)
+ vvs->buf_size_max = val;
+ vvs->buf_size = val;
+ vvs->buf_alloc = val;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_set_buffer_size);
+
+void virtio_transport_set_min_buffer_size(struct vsock_sock *vsk, u64 val)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ if (val > VIRTIO_VSOCK_MAX_BUF_SIZE)
+ val = VIRTIO_VSOCK_MAX_BUF_SIZE;
+ if (val > vvs->buf_size)
+ vvs->buf_size = val;
+ vvs->buf_size_min = val;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_set_min_buffer_size);
+
+void virtio_transport_set_max_buffer_size(struct vsock_sock *vsk, u64 val)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ if (val > VIRTIO_VSOCK_MAX_BUF_SIZE)
+ val = VIRTIO_VSOCK_MAX_BUF_SIZE;
+ if (val < vvs->buf_size)
+ vvs->buf_size = val;
+ vvs->buf_size_max = val;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_set_max_buffer_size);
+
+int
+virtio_transport_notify_poll_in(struct vsock_sock *vsk,
+ size_t target,
+ bool *data_ready_now)
+{
+ if (vsock_stream_has_data(vsk))
+ *data_ready_now = true;
+ else
+ *data_ready_now = false;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_poll_in);
+
+int
+virtio_transport_notify_poll_out(struct vsock_sock *vsk,
+ size_t target,
+ bool *space_avail_now)
+{
+ s64 free_space;
+
+ free_space = vsock_stream_has_space(vsk);
+ if (free_space > 0)
+ *space_avail_now = true;
+ else if (free_space == 0)
+ *space_avail_now = false;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_poll_out);
+
+int virtio_transport_notify_recv_init(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_init);
+
+int virtio_transport_notify_recv_pre_block(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_pre_block);
+
+int virtio_transport_notify_recv_pre_dequeue(struct vsock_sock *vsk,
+ size_t target, struct vsock_transport_recv_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_pre_dequeue);
+
+int virtio_transport_notify_recv_post_dequeue(struct vsock_sock *vsk,
+ size_t target, ssize_t copied, bool data_read,
+ struct vsock_transport_recv_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_recv_post_dequeue);
+
+int virtio_transport_notify_send_init(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_send_init);
+
+int virtio_transport_notify_send_pre_block(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_send_pre_block);
+
+int virtio_transport_notify_send_pre_enqueue(struct vsock_sock *vsk,
+ struct vsock_transport_send_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_send_pre_enqueue);
+
+int virtio_transport_notify_send_post_enqueue(struct vsock_sock *vsk,
+ ssize_t written, struct vsock_transport_send_notify_data *data)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_notify_send_post_enqueue);
+
+u64 virtio_transport_stream_rcvhiwat(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ return vvs->buf_size;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_rcvhiwat);
+
+bool virtio_transport_stream_is_active(struct vsock_sock *vsk)
+{
+ return true;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_is_active);
+
+bool virtio_transport_stream_allow(u32 cid, u32 port)
+{
+ return true;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_allow);
+
+int virtio_transport_dgram_bind(struct vsock_sock *vsk,
+ struct sockaddr_vm *addr)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_dgram_bind);
+
+bool virtio_transport_dgram_allow(u32 cid, u32 port)
+{
+ return false;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_dgram_allow);
+
+int virtio_transport_connect(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_REQUEST,
+ .type = VIRTIO_VSOCK_TYPE_STREAM,
+ };
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_connect);
+
+int virtio_transport_shutdown(struct vsock_sock *vsk, int mode)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_SHUTDOWN,
+ .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .flags = (mode & RCV_SHUTDOWN ?
+ VIRTIO_VSOCK_SHUTDOWN_RCV : 0) |
+ (mode & SEND_SHUTDOWN ?
+ VIRTIO_VSOCK_SHUTDOWN_SEND : 0),
+ };
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_shutdown);
+
+int
+virtio_transport_dgram_enqueue(struct vsock_sock *vsk,
+ struct sockaddr_vm *remote_addr,
+ struct msghdr *msg,
+ size_t dgram_len)
+{
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(virtio_transport_dgram_enqueue);
+
+ssize_t
+virtio_transport_stream_enqueue(struct vsock_sock *vsk,
+ struct msghdr *msg,
+ size_t len)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RW,
+ .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .msg = msg,
+ .pkt_len = len,
+ };
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_stream_enqueue);
+
+void virtio_transport_destruct(struct vsock_sock *vsk)
+{
+ struct virtio_vsock_sock *vvs = vsk->trans;
+
+ kfree(vvs);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_destruct);
+
+static int virtio_transport_reset(struct vsock_sock *vsk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RST,
+ .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .reply = !!pkt,
+ };
+
+ /* Send RST only if the original pkt is not a RST pkt */
+ if (pkt && le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST)
+ return 0;
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+
+/* Normally packets are associated with a socket. There may be no socket if an
+ * attempt was made to connect to a socket that does not exist.
+ */
+static int virtio_transport_reset_no_sock(struct virtio_vsock_pkt *pkt)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RST,
+ .type = le16_to_cpu(pkt->hdr.type),
+ .reply = true,
+ };
+
+ /* Send RST only if the original pkt is not a RST pkt */
+ if (le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST)
+ return 0;
+
+ pkt = virtio_transport_alloc_pkt(&info, 0,
+ le32_to_cpu(pkt->hdr.dst_cid),
+ le32_to_cpu(pkt->hdr.dst_port),
+ le32_to_cpu(pkt->hdr.src_cid),
+ le32_to_cpu(pkt->hdr.src_port));
+ if (!pkt)
+ return -ENOMEM;
+
+ return virtio_transport_get_ops()->send_pkt(pkt);
+}
+
+static void virtio_transport_wait_close(struct sock *sk, long timeout)
+{
+ if (timeout) {
+ DEFINE_WAIT(wait);
+
+ do {
+ prepare_to_wait(sk_sleep(sk), &wait,
+ TASK_INTERRUPTIBLE);
+ if (sk_wait_event(sk, &timeout,
+ sock_flag(sk, SOCK_DONE)))
+ break;
+ } while (!signal_pending(current) && timeout);
+
+ finish_wait(sk_sleep(sk), &wait);
+ }
+}
+
+static void virtio_transport_do_close(struct vsock_sock *vsk,
+ bool cancel_timeout)
+{
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+ vsk->peer_shutdown = SHUTDOWN_MASK;
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = SS_DISCONNECTING;
+ sk->sk_state_change(sk);
+
+ if (vsk->close_work_scheduled &&
+ (!cancel_timeout || cancel_delayed_work(&vsk->close_work))) {
+ vsk->close_work_scheduled = false;
+
+ vsock_remove_sock(vsk);
+
+ /* Release refcnt obtained when we scheduled the timeout */
+ sock_put(sk);
+ }
+}
+
+static void virtio_transport_close_timeout(struct work_struct *work)
+{
+ struct vsock_sock *vsk =
+ container_of(work, struct vsock_sock, close_work.work);
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_hold(sk);
+ lock_sock(sk);
+
+ if (!sock_flag(sk, SOCK_DONE)) {
+ (void)virtio_transport_reset(vsk, NULL);
+
+ virtio_transport_do_close(vsk, false);
+ }
+
+ vsk->close_work_scheduled = false;
+
+ release_sock(sk);
+ sock_put(sk);
+}
+
+/* User context, vsk->sk is locked */
+static bool virtio_transport_close(struct vsock_sock *vsk)
+{
+ struct sock *sk = &vsk->sk;
+
+ if (!(sk->sk_state == SS_CONNECTED ||
+ sk->sk_state == SS_DISCONNECTING))
+ return true;
+
+ /* Already received SHUTDOWN from peer, reply with RST */
+ if ((vsk->peer_shutdown & SHUTDOWN_MASK) == SHUTDOWN_MASK) {
+ (void)virtio_transport_reset(vsk, NULL);
+ return true;
+ }
+
+ if ((sk->sk_shutdown & SHUTDOWN_MASK) != SHUTDOWN_MASK)
+ (void)virtio_transport_shutdown(vsk, SHUTDOWN_MASK);
+
+ if (sock_flag(sk, SOCK_LINGER) && !(current->flags & PF_EXITING))
+ virtio_transport_wait_close(sk, sk->sk_lingertime);
+
+ if (sock_flag(sk, SOCK_DONE)) {
+ return true;
+ }
+
+ sock_hold(sk);
+ INIT_DELAYED_WORK(&vsk->close_work,
+ virtio_transport_close_timeout);
+ vsk->close_work_scheduled = true;
+ schedule_delayed_work(&vsk->close_work, VSOCK_CLOSE_TIMEOUT);
+ return false;
+}
+
+void virtio_transport_release(struct vsock_sock *vsk)
+{
+ struct sock *sk = &vsk->sk;
+ bool remove_sock = true;
+
+ lock_sock(sk);
+ if (sk->sk_type == SOCK_STREAM)
+ remove_sock = virtio_transport_close(vsk);
+ release_sock(sk);
+
+ if (remove_sock)
+ vsock_remove_sock(vsk);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_release);
+
+static int
+virtio_transport_recv_connecting(struct sock *sk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+ int err;
+ int skerr;
+
+ switch (le16_to_cpu(pkt->hdr.op)) {
+ case VIRTIO_VSOCK_OP_RESPONSE:
+ sk->sk_state = SS_CONNECTED;
+ sk->sk_socket->state = SS_CONNECTED;
+ vsock_insert_connected(vsk);
+ sk->sk_state_change(sk);
+ break;
+ case VIRTIO_VSOCK_OP_INVALID:
+ break;
+ case VIRTIO_VSOCK_OP_RST:
+ skerr = ECONNRESET;
+ err = 0;
+ goto destroy;
+ default:
+ skerr = EPROTO;
+ err = -EINVAL;
+ goto destroy;
+ }
+ return 0;
+
+destroy:
+ virtio_transport_reset(vsk, pkt);
+ sk->sk_state = SS_UNCONNECTED;
+ sk->sk_err = skerr;
+ sk->sk_error_report(sk);
+ return err;
+}
+
+static int
+virtio_transport_recv_connected(struct sock *sk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ int err = 0;
+
+ switch (le16_to_cpu(pkt->hdr.op)) {
+ case VIRTIO_VSOCK_OP_RW:
+ pkt->len = le32_to_cpu(pkt->hdr.len);
+ pkt->off = 0;
+
+ spin_lock_bh(&vvs->rx_lock);
+ virtio_transport_inc_rx_pkt(vvs, pkt);
+ list_add_tail(&pkt->list, &vvs->rx_queue);
+ spin_unlock_bh(&vvs->rx_lock);
+
+ sk->sk_data_ready(sk);
+ return err;
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ sk->sk_write_space(sk);
+ break;
+ case VIRTIO_VSOCK_OP_SHUTDOWN:
+ if (le32_to_cpu(pkt->hdr.flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
+ vsk->peer_shutdown |= RCV_SHUTDOWN;
+ if (le32_to_cpu(pkt->hdr.flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
+ vsk->peer_shutdown |= SEND_SHUTDOWN;
+ if (vsk->peer_shutdown == SHUTDOWN_MASK &&
+ vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = SS_DISCONNECTING;
+ if (le32_to_cpu(pkt->hdr.flags))
+ sk->sk_state_change(sk);
+ break;
+ case VIRTIO_VSOCK_OP_RST:
+ virtio_transport_do_close(vsk, true);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ virtio_transport_free_pkt(pkt);
+ return err;
+}
+
+static void
+virtio_transport_recv_disconnecting(struct sock *sk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+
+ if (le16_to_cpu(pkt->hdr.op) == VIRTIO_VSOCK_OP_RST)
+ virtio_transport_do_close(vsk, true);
+}
+
+static int
+virtio_transport_send_response(struct vsock_sock *vsk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct virtio_vsock_pkt_info info = {
+ .op = VIRTIO_VSOCK_OP_RESPONSE,
+ .type = VIRTIO_VSOCK_TYPE_STREAM,
+ .remote_cid = le32_to_cpu(pkt->hdr.src_cid),
+ .remote_port = le32_to_cpu(pkt->hdr.src_port),
+ .reply = true,
+ };
+
+ return virtio_transport_send_pkt_info(vsk, &info);
+}
+
+/* Handle server socket */
+static int
+virtio_transport_recv_listen(struct sock *sk, struct virtio_vsock_pkt *pkt)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+ struct vsock_sock *vchild;
+ struct sock *child;
+
+ if (le16_to_cpu(pkt->hdr.op) != VIRTIO_VSOCK_OP_REQUEST) {
+ virtio_transport_reset(vsk, pkt);
+ return -EINVAL;
+ }
+
+ if (sk_acceptq_is_full(sk)) {
+ virtio_transport_reset(vsk, pkt);
+ return -ENOMEM;
+ }
+
+ child = __vsock_create(sock_net(sk), NULL, sk, GFP_KERNEL,
+ sk->sk_type, 0);
+ if (!child) {
+ virtio_transport_reset(vsk, pkt);
+ return -ENOMEM;
+ }
+
+ sk->sk_ack_backlog++;
+
+ lock_sock_nested(child, SINGLE_DEPTH_NESTING);
+
+ child->sk_state = SS_CONNECTED;
+
+ vchild = vsock_sk(child);
+ vsock_addr_init(&vchild->local_addr, le32_to_cpu(pkt->hdr.dst_cid),
+ le32_to_cpu(pkt->hdr.dst_port));
+ vsock_addr_init(&vchild->remote_addr, le32_to_cpu(pkt->hdr.src_cid),
+ le32_to_cpu(pkt->hdr.src_port));
+
+ vsock_insert_connected(vchild);
+ vsock_enqueue_accept(sk, child);
+ virtio_transport_send_response(vchild, pkt);
+
+ release_sock(child);
+
+ sk->sk_data_ready(sk);
+ return 0;
+}
+
+static bool virtio_transport_space_update(struct sock *sk,
+ struct virtio_vsock_pkt *pkt)
+{
+ struct vsock_sock *vsk = vsock_sk(sk);
+ struct virtio_vsock_sock *vvs = vsk->trans;
+ bool space_available;
+
+ /* buf_alloc and fwd_cnt is always included in the hdr */
+ spin_lock_bh(&vvs->tx_lock);
+ vvs->peer_buf_alloc = le32_to_cpu(pkt->hdr.buf_alloc);
+ vvs->peer_fwd_cnt = le32_to_cpu(pkt->hdr.fwd_cnt);
+ space_available = virtio_transport_has_space(vsk);
+ spin_unlock_bh(&vvs->tx_lock);
+ return space_available;
+}
+
+/* We are under the virtio-vsock's vsock->rx_lock or vhost-vsock's vq->mutex
+ * lock.
+ */
+void virtio_transport_recv_pkt(struct virtio_vsock_pkt *pkt)
+{
+ struct sockaddr_vm src, dst;
+ struct vsock_sock *vsk;
+ struct sock *sk;
+ bool space_available;
+
+ vsock_addr_init(&src, le32_to_cpu(pkt->hdr.src_cid),
+ le32_to_cpu(pkt->hdr.src_port));
+ vsock_addr_init(&dst, le32_to_cpu(pkt->hdr.dst_cid),
+ le32_to_cpu(pkt->hdr.dst_port));
+
+ trace_virtio_transport_recv_pkt(src.svm_cid, src.svm_port,
+ dst.svm_cid, dst.svm_port,
+ le32_to_cpu(pkt->hdr.len),
+ le16_to_cpu(pkt->hdr.type),
+ le16_to_cpu(pkt->hdr.op),
+ le32_to_cpu(pkt->hdr.flags),
+ le32_to_cpu(pkt->hdr.buf_alloc),
+ le32_to_cpu(pkt->hdr.fwd_cnt));
+
+ if (le16_to_cpu(pkt->hdr.type) != VIRTIO_VSOCK_TYPE_STREAM) {
+ (void)virtio_transport_reset_no_sock(pkt);
+ goto free_pkt;
+ }
+
+ /* The socket must be in connected or bound table
+ * otherwise send reset back
+ */
+ sk = vsock_find_connected_socket(&src, &dst);
+ if (!sk) {
+ sk = vsock_find_bound_socket(&dst);
+ if (!sk) {
+ (void)virtio_transport_reset_no_sock(pkt);
+ goto free_pkt;
+ }
+ }
+
+ vsk = vsock_sk(sk);
+
+ space_available = virtio_transport_space_update(sk, pkt);
+
+ lock_sock(sk);
+
+ /* Update CID in case it has changed after a transport reset event */
+ vsk->local_addr.svm_cid = dst.svm_cid;
+
+ if (space_available)
+ sk->sk_write_space(sk);
+
+ switch (sk->sk_state) {
+ case VSOCK_SS_LISTEN:
+ virtio_transport_recv_listen(sk, pkt);
+ virtio_transport_free_pkt(pkt);
+ break;
+ case SS_CONNECTING:
+ virtio_transport_recv_connecting(sk, pkt);
+ virtio_transport_free_pkt(pkt);
+ break;
+ case SS_CONNECTED:
+ virtio_transport_recv_connected(sk, pkt);
+ break;
+ case SS_DISCONNECTING:
+ virtio_transport_recv_disconnecting(sk, pkt);
+ virtio_transport_free_pkt(pkt);
+ break;
+ default:
+ virtio_transport_free_pkt(pkt);
+ break;
+ }
+ release_sock(sk);
+
+ /* Release refcnt obtained when we fetched this socket out of the
+ * bound or connected list.
+ */
+ sock_put(sk);
+ return;
+
+free_pkt:
+ virtio_transport_free_pkt(pkt);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_recv_pkt);
+
+void virtio_transport_free_pkt(struct virtio_vsock_pkt *pkt)
+{
+ kfree(pkt->buf);
+ kfree(pkt);
+}
+EXPORT_SYMBOL_GPL(virtio_transport_free_pkt);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Asias He");
+MODULE_DESCRIPTION("common code for virtio vsock");
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 4120b7a538be..4be4fbbc0b50 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -1644,6 +1644,8 @@ static void vmci_transport_destruct(struct vsock_sock *vsk)
static void vmci_transport_release(struct vsock_sock *vsk)
{
+ vsock_remove_sock(vsk);
+
if (!vmci_handle_is_invalid(vmci_trans(vsk)->dg_handle)) {
vmci_datagram_destroy_handle(vmci_trans(vsk)->dg_handle);
vmci_trans(vsk)->dg_handle = VMCI_INVALID_HANDLE;
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index bb3d64ee68aa..0f506220a3bd 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -716,7 +716,7 @@ static bool cfg80211_ir_permissive_chan(struct wiphy *wiphy,
ASSERT_RTNL();
- if (!config_enabled(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
+ if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) ||
!(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR))
return false;
diff --git a/samples/kprobes/jprobe_example.c b/samples/kprobes/jprobe_example.c
index c3108bb15789..e3c0a40909f7 100644
--- a/samples/kprobes/jprobe_example.c
+++ b/samples/kprobes/jprobe_example.c
@@ -48,10 +48,10 @@ static int __init jprobe_init(void)
ret = register_jprobe(&my_jprobe);
if (ret < 0) {
- printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
+ pr_err("register_jprobe failed, returned %d\n", ret);
return -1;
}
- printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
+ pr_info("Planted jprobe at %p, handler addr %p\n",
my_jprobe.kp.addr, my_jprobe.entry);
return 0;
}
@@ -59,7 +59,7 @@ static int __init jprobe_init(void)
static void __exit jprobe_exit(void)
{
unregister_jprobe(&my_jprobe);
- printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe.kp.addr);
+ pr_info("jprobe at %p unregistered\n", my_jprobe.kp.addr);
}
module_init(jprobe_init)
diff --git a/samples/kprobes/kprobe_example.c b/samples/kprobes/kprobe_example.c
index f3b61b4ee09c..88b3e2d227ae 100644
--- a/samples/kprobes/kprobe_example.c
+++ b/samples/kprobes/kprobe_example.c
@@ -27,23 +27,19 @@ static struct kprobe kp = {
static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#ifdef CONFIG_X86
- printk(KERN_INFO "<%s> pre_handler: p->addr = 0x%p, ip = %lx,"
- " flags = 0x%lx\n",
+ pr_info("<%s> pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
p->symbol_name, p->addr, regs->ip, regs->flags);
#endif
#ifdef CONFIG_PPC
- printk(KERN_INFO "<%s> pre_handler: p->addr = 0x%p, nip = 0x%lx,"
- " msr = 0x%lx\n",
+ pr_info("<%s> pre_handler: p->addr = 0x%p, nip = 0x%lx, msr = 0x%lx\n",
p->symbol_name, p->addr, regs->nip, regs->msr);
#endif
#ifdef CONFIG_MIPS
- printk(KERN_INFO "<%s> pre_handler: p->addr = 0x%p, epc = 0x%lx,"
- " status = 0x%lx\n",
+ pr_info("<%s> pre_handler: p->addr = 0x%p, epc = 0x%lx, status = 0x%lx\n",
p->symbol_name, p->addr, regs->cp0_epc, regs->cp0_status);
#endif
#ifdef CONFIG_TILEGX
- printk(KERN_INFO "<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx,"
- " ex1 = 0x%lx\n",
+ pr_info("<%s> pre_handler: p->addr = 0x%p, pc = 0x%lx, ex1 = 0x%lx\n",
p->symbol_name, p->addr, regs->pc, regs->ex1);
#endif
#ifdef CONFIG_ARM64
@@ -61,19 +57,19 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs,
unsigned long flags)
{
#ifdef CONFIG_X86
- printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, flags = 0x%lx\n",
+ pr_info("<%s> post_handler: p->addr = 0x%p, flags = 0x%lx\n",
p->symbol_name, p->addr, regs->flags);
#endif
#ifdef CONFIG_PPC
- printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, msr = 0x%lx\n",
+ pr_info("<%s> post_handler: p->addr = 0x%p, msr = 0x%lx\n",
p->symbol_name, p->addr, regs->msr);
#endif
#ifdef CONFIG_MIPS
- printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, status = 0x%lx\n",
+ pr_info("<%s> post_handler: p->addr = 0x%p, status = 0x%lx\n",
p->symbol_name, p->addr, regs->cp0_status);
#endif
#ifdef CONFIG_TILEGX
- printk(KERN_INFO "<%s> post_handler: p->addr = 0x%p, ex1 = 0x%lx\n",
+ pr_info("<%s> post_handler: p->addr = 0x%p, ex1 = 0x%lx\n",
p->symbol_name, p->addr, regs->ex1);
#endif
#ifdef CONFIG_ARM64
@@ -89,8 +85,7 @@ static void handler_post(struct kprobe *p, struct pt_regs *regs,
*/
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
- printk(KERN_INFO "fault_handler: p->addr = 0x%p, trap #%dn",
- p->addr, trapnr);
+ pr_info("fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr);
/* Return 0 because we don't handle the fault. */
return 0;
}
@@ -104,17 +99,17 @@ static int __init kprobe_init(void)
ret = register_kprobe(&kp);
if (ret < 0) {
- printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
+ pr_err("register_kprobe failed, returned %d\n", ret);
return ret;
}
- printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
+ pr_info("Planted kprobe at %p\n", kp.addr);
return 0;
}
static void __exit kprobe_exit(void)
{
unregister_kprobe(&kp);
- printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
+ pr_info("kprobe at %p unregistered\n", kp.addr);
}
module_init(kprobe_init)
diff --git a/samples/kprobes/kretprobe_example.c b/samples/kprobes/kretprobe_example.c
index ebb1d1aed547..7f9060f435cd 100644
--- a/samples/kprobes/kretprobe_example.c
+++ b/samples/kprobes/kretprobe_example.c
@@ -55,14 +55,14 @@ static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
*/
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
- int retval = regs_return_value(regs);
+ unsigned long retval = regs_return_value(regs);
struct my_data *data = (struct my_data *)ri->data;
s64 delta;
ktime_t now;
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, data->entry_stamp));
- printk(KERN_INFO "%s returned %d and took %lld ns to execute\n",
+ pr_info("%s returned %lu and took %lld ns to execute\n",
func_name, retval, (long long)delta);
return 0;
}
@@ -82,11 +82,10 @@ static int __init kretprobe_init(void)
my_kretprobe.kp.symbol_name = func_name;
ret = register_kretprobe(&my_kretprobe);
if (ret < 0) {
- printk(KERN_INFO "register_kretprobe failed, returned %d\n",
- ret);
+ pr_err("register_kretprobe failed, returned %d\n", ret);
return -1;
}
- printk(KERN_INFO "Planted return probe at %s: %p\n",
+ pr_info("Planted return probe at %s: %p\n",
my_kretprobe.kp.symbol_name, my_kretprobe.kp.addr);
return 0;
}
@@ -94,11 +93,10 @@ static int __init kretprobe_init(void)
static void __exit kretprobe_exit(void)
{
unregister_kretprobe(&my_kretprobe);
- printk(KERN_INFO "kretprobe at %p unregistered\n",
- my_kretprobe.kp.addr);
+ pr_info("kretprobe at %p unregistered\n", my_kretprobe.kp.addr);
/* nmissed > 0 suggests that maxactive was set too low. */
- printk(KERN_INFO "Missed probing %d instances of %s\n",
+ pr_info("Missed probing %d instances of %s\n",
my_kretprobe.nmissed, my_kretprobe.kp.symbol_name);
}
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 15b196fc2f49..179219845dfc 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -108,16 +108,20 @@ as-option = $(call try-run,\
as-instr = $(call try-run,\
printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
+# Do not attempt to build with gcc plugins during cc-option tests.
+# (And this uses delayed resolution so the flags will be up to date.)
+CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS))
+
# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
cc-option = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
+ $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
@@ -127,7 +131,7 @@ cc-option-align = $(subst -functions=0,,\
# cc-disable-warning
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
cc-disable-warning = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+ $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
# cc-name
# Expands to either gcc or clang
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 5e22b60589c1..61f0e6db909b 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -19,25 +19,42 @@ ifdef CONFIG_GCC_PLUGINS
endif
endif
- GCC_PLUGINS_CFLAGS := $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y))
+ GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
- export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN SANCOV_PLUGIN
+ export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR SANCOV_PLUGIN
+ ifneq ($(PLUGINCC),)
+ # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.
+ GCC_PLUGINS_CFLAGS := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGINS_CFLAGS))
+ endif
+
+ KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
+ GCC_PLUGIN := $(gcc-plugin-y)
+ GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y)
+endif
+
+# If plugins aren't supported, abort the build before hard-to-read compiler
+# errors start getting spewed by the main build.
+PHONY += gcc-plugins-check
+gcc-plugins-check: FORCE
+ifdef CONFIG_GCC_PLUGINS
ifeq ($(PLUGINCC),)
ifneq ($(GCC_PLUGINS_CFLAGS),)
ifeq ($(call cc-ifversion, -ge, 0405, y), y)
- PLUGINCC := $(shell $(CONFIG_SHELL) -x $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
- $(warning warning: your gcc installation does not support plugins, perhaps the necessary headers are missing?)
+ $(Q)$(srctree)/scripts/gcc-plugin.sh --show-error "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)" || true
+ @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc installation does not support plugins, perhaps the necessary headers are missing?" >&2 && exit 1
else
- $(warning warning: your gcc version does not support plugins, you should upgrade it to gcc 4.5 at least)
+ @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc version does not support plugins, you should upgrade it to at least gcc 4.5" >&2 && exit 1
endif
endif
- else
- # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.
- GCC_PLUGINS_CFLAGS := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGINS_CFLAGS))
endif
+endif
+ @:
- KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
- GCC_PLUGIN := $(gcc-plugin-y)
-
+# Actually do the build, if requested.
+PHONY += gcc-plugins
+gcc-plugins: scripts_basic gcc-plugins-check
+ifdef CONFIG_GCC_PLUGINS
+ $(Q)$(MAKE) $(build)=scripts/gcc-plugins
endif
+ @:
diff --git a/scripts/gcc-plugin.sh b/scripts/gcc-plugin.sh
index fb9207565471..b65224bfb847 100755
--- a/scripts/gcc-plugin.sh
+++ b/scripts/gcc-plugin.sh
@@ -1,5 +1,12 @@
#!/bin/sh
srctree=$(dirname "$0")
+
+SHOW_ERROR=
+if [ "$1" = "--show-error" ] ; then
+ SHOW_ERROR=1
+ shift || true
+fi
+
gccplugins_dir=$($3 -print-file-name=plugin)
plugincc=$($1 -E -x c++ - -o /dev/null -I"${srctree}"/gcc-plugins -I"${gccplugins_dir}"/include 2>&1 <<EOF
#include "gcc-common.h"
@@ -13,6 +20,9 @@ EOF
if [ $? -ne 0 ]
then
+ if [ -n "$SHOW_ERROR" ] ; then
+ echo "${plugincc}" >&2
+ fi
exit 1
fi
@@ -48,4 +58,8 @@ then
echo "$2"
exit 0
fi
+
+if [ -n "$SHOW_ERROR" ] ; then
+ echo "${plugincc}" >&2
+fi
exit 1
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index 88c8ec47232b..8b29dc17c73c 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -12,16 +12,18 @@ else
export HOST_EXTRACXXFLAGS
endif
-export GCCPLUGINS_DIR HOSTLIBS
-
ifneq ($(CFLAGS_KCOV), $(SANCOV_PLUGIN))
GCC_PLUGIN := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGIN))
endif
-$(HOSTLIBS)-y := $(GCC_PLUGIN)
+export HOSTLIBS
+
+$(HOSTLIBS)-y := $(foreach p,$(GCC_PLUGIN),$(if $(findstring /,$(p)),,$(p)))
always := $($(HOSTLIBS)-y)
-cyc_complexity_plugin-objs := cyc_complexity_plugin.o
-sancov_plugin-objs := sancov_plugin.o
+$(foreach p,$($(HOSTLIBS)-y:%.so=%),$(eval $(p)-objs := $(p).o))
+
+subdir-y := $(GCC_PLUGIN_SUBDIR)
+subdir- += $(GCC_PLUGIN_SUBDIR)
clean-files += *.so
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 122fcdaf42c8..49a00d54b835 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -432,7 +432,7 @@ foreach my $file (@ARGV) {
die "$P: file '${file}' not found\n";
}
}
- if ($from_filename || vcs_file_exists($file)) {
+ if ($from_filename || ($file ne "&STDIN" && vcs_file_exists($file))) {
$file =~ s/^\Q${cur_path}\E//; #strip any absolute path
$file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree
push(@files, $file);
diff --git a/security/Kconfig b/security/Kconfig
index 176758cdfa57..df28f2b6f3e1 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -118,6 +118,34 @@ config LSM_MMAP_MIN_ADDR
this low address space will need the permission specific to the
systems running LSM.
+config HAVE_HARDENED_USERCOPY_ALLOCATOR
+ bool
+ help
+ The heap allocator implements __check_heap_object() for
+ validating memory ranges against heap object sizes in
+ support of CONFIG_HARDENED_USERCOPY.
+
+config HAVE_ARCH_HARDENED_USERCOPY
+ bool
+ help
+ The architecture supports CONFIG_HARDENED_USERCOPY by
+ calling check_object_size() just before performing the
+ userspace copies in the low level implementation of
+ copy_to_user() and copy_from_user().
+
+config HARDENED_USERCOPY
+ bool "Harden memory copies between kernel and userspace"
+ depends on HAVE_ARCH_HARDENED_USERCOPY
+ select BUG
+ help
+ This option checks for obviously wrong memory regions when
+ copying memory to/from the kernel (via copy_to_user() and
+ copy_from_user() functions) by rejecting memory ranges that
+ are larger than the specified heap object, span multiple
+ separately allocates pages, are not on the process stack,
+ or are part of the kernel text. This kills entire classes
+ of heap overflow exploits and similar kernel memory exposures.
+
source security/selinux/Kconfig
source security/smack/Kconfig
source security/tomoyo/Kconfig
diff --git a/security/security.c b/security/security.c
index c4bb47db30ee..4838e7fefa1f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -356,7 +356,7 @@ void security_inode_free(struct inode *inode)
}
int security_dentry_init_security(struct dentry *dentry, int mode,
- struct qstr *name, void **ctx,
+ const struct qstr *name, void **ctx,
u32 *ctxlen)
{
return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ec30880c4b98..13185a6c266a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2832,7 +2832,7 @@ static void selinux_inode_free_security(struct inode *inode)
}
static int selinux_dentry_init_security(struct dentry *dentry, int mode,
- struct qstr *name, void **ctx,
+ const struct qstr *name, void **ctx,
u32 *ctxlen)
{
u32 newsid;
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index e0406211716b..65171f6657a2 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -9,14 +9,6 @@ menuconfig SND_ARM
Drivers that are implemented on ASoC can be found in
"ALSA for SoC audio support" section.
-config SND_PXA2XX_LIB
- tristate
- select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
- select SND_DMAENGINE_PCM
-
-config SND_PXA2XX_LIB_AC97
- bool
-
if SND_ARM
config SND_ARMAACI
@@ -42,3 +34,10 @@ config SND_PXA2XX_AC97
endif # SND_ARM
+config SND_PXA2XX_LIB
+ tristate
+ select SND_AC97_CODEC if SND_PXA2XX_LIB_AC97
+ select SND_DMAENGINE_PCM
+
+config SND_PXA2XX_LIB_AC97
+ bool
diff --git a/sound/hda/array.c b/sound/hda/array.c
index 516795baa7db..5dfa610e4471 100644
--- a/sound/hda/array.c
+++ b/sound/hda/array.c
@@ -21,13 +21,15 @@ void *snd_array_new(struct snd_array *array)
return NULL;
if (array->used >= array->alloced) {
int num = array->alloced + array->alloc_align;
+ int oldsize = array->alloced * array->elem_size;
int size = (num + 1) * array->elem_size;
void *nlist;
if (snd_BUG_ON(num >= 4096))
return NULL;
- nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
+ nlist = krealloc(array->list, size, GFP_KERNEL);
if (!nlist)
return NULL;
+ memset(nlist + oldsize, 0, size - oldsize);
array->list = nlist;
array->alloced = num;
}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 6f8ea13323c1..160c7f713722 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -906,20 +906,23 @@ static int azx_resume(struct device *dev)
struct snd_card *card = dev_get_drvdata(dev);
struct azx *chip;
struct hda_intel *hda;
+ struct hdac_bus *bus;
if (!card)
return 0;
chip = card->private_data;
hda = container_of(chip, struct hda_intel, chip);
+ bus = azx_bus(chip);
if (chip->disabled || hda->init_failed || !chip->running)
return 0;
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
- && hda->need_i915_power) {
- snd_hdac_display_power(azx_bus(chip), true);
- snd_hdac_i915_set_bclk(azx_bus(chip));
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+ snd_hdac_display_power(bus, true);
+ if (hda->need_i915_power)
+ snd_hdac_i915_set_bclk(bus);
}
+
if (chip->msi)
if (pci_enable_msi(pci) < 0)
chip->msi = 0;
@@ -929,6 +932,11 @@ static int azx_resume(struct device *dev)
hda_intel_init_chip(chip, true);
+ /* power down again for link-controlled chips */
+ if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+ !hda->need_i915_power)
+ snd_hdac_display_power(bus, false);
+
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
trace_azx_resume(chip);
@@ -1008,6 +1016,7 @@ static int azx_runtime_resume(struct device *dev)
chip = card->private_data;
hda = container_of(chip, struct hda_intel, chip);
+ bus = azx_bus(chip);
if (chip->disabled || hda->init_failed)
return 0;
@@ -1015,15 +1024,9 @@ static int azx_runtime_resume(struct device *dev)
return 0;
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
- bus = azx_bus(chip);
- if (hda->need_i915_power) {
- snd_hdac_display_power(bus, true);
+ snd_hdac_display_power(bus, true);
+ if (hda->need_i915_power)
snd_hdac_i915_set_bclk(bus);
- } else {
- /* toggle codec wakeup bit for STATESTS read */
- snd_hdac_set_codec_wakeup(bus, true);
- snd_hdac_set_codec_wakeup(bus, false);
- }
}
/* Read STATESTS before controller reset */
@@ -1043,6 +1046,11 @@ static int azx_runtime_resume(struct device *dev)
azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
~STATESTS_INT_MASK);
+ /* power down again for link-controlled chips */
+ if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) &&
+ !hda->need_i915_power)
+ snd_hdac_display_power(bus, false);
+
trace_azx_runtime_resume(chip);
return 0;
}
@@ -2265,6 +2273,8 @@ static const struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x1022, 0x780d),
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
/* ATI HDMI */
+ { PCI_DEVICE(0x1002, 0x0002),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0x1308),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0x157a),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index ddd29b9819ba..574b1b48996f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4689,6 +4689,22 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
}
}
+static void alc298_fixup_speaker_volume(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ /* The speaker is routed to the Node 0x06 by a mistake, as a result
+ we can't adjust the speaker's volume since this node does not has
+ Amp-out capability. we change the speaker's route to:
+ Node 0x02 (Audio Output) -> Node 0x0c (Audio Mixer) -> Node 0x17 (
+ Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
+ speaker's volume now. */
+
+ hda_nid_t conn1[1] = { 0x0c };
+ snd_hda_override_conn_list(codec, 0x17, 1, conn1);
+ }
+}
+
/* Hook to update amp GPIO4 for automute */
static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
@@ -4838,6 +4854,7 @@ enum {
ALC280_FIXUP_HP_HEADSET_MIC,
ALC221_FIXUP_HP_FRONT_MIC,
ALC292_FIXUP_TPT460,
+ ALC298_FIXUP_SPK_VOLUME,
};
static const struct hda_fixup alc269_fixups[] = {
@@ -5493,6 +5510,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE,
},
+ [ALC298_FIXUP_SPK_VOLUME] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc298_fixup_speaker_volume,
+ .chained = true,
+ .chain_id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5539,6 +5562,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+ SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5814,6 +5838,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x1b, 0x01014020},
{0x21, 0x0221103f}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x14, 0x90170130},
+ {0x1b, 0x02011020},
+ {0x21, 0x0221103f}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x14, 0x90170150},
{0x1b, 0x02011020},
{0x21, 0x0221105f}),
@@ -6549,6 +6577,7 @@ enum {
ALC668_FIXUP_ASUS_Nx51,
ALC891_FIXUP_HEADSET_MODE,
ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
+ ALC662_FIXUP_ACER_VERITON,
};
static const struct hda_fixup alc662_fixups[] = {
@@ -6818,6 +6847,13 @@ static const struct hda_fixup alc662_fixups[] = {
.chained = true,
.chain_id = ALC891_FIXUP_HEADSET_MODE
},
+ [ALC662_FIXUP_ACER_VERITON] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x15, 0x50170120 }, /* no internal speaker */
+ { }
+ }
+ },
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -6856,6 +6892,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
+ SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
#if 0
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 6adde457b602..6cf1f3597455 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1128,6 +1128,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
{
/* devices which do not support reading the sample rate. */
switch (chip->usb_id) {
+ case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */
case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema */
case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
case USB_ID(0x045E, 0x076E): /* MS Lifecam HD-5001 */
@@ -1138,6 +1139,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
+ case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
case USB_ID(0x1de7, 0x0013): /* Phoenix Audio MT202exe */
case USB_ID(0x1de7, 0x0014): /* Phoenix Audio TMX320 */
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 4a413485f9eb..92a8308b96f6 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -225,7 +225,6 @@
#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
-#define X86_FEATURE_PCOMMIT ( 9*32+22) /* PCOMMIT instruction */
#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
@@ -301,10 +300,6 @@
#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
-#define X86_BUG_NULL_SEG X86_BUG(9) /* Nulling a selector preserves the base */
-#define X86_BUG_SWAPGS_FENCE X86_BUG(10) /* SWAPGS without input dep on GS */
-
-
#ifdef CONFIG_X86_32
/*
* 64-bit kernels don't use X86_BUG_ESPFIX. Make the define conditional
@@ -312,5 +307,7 @@
*/
#define X86_BUG_ESPFIX X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */
#endif
-
+#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
+#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
+#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
index 911e9358ceb1..85599ad4d024 100644
--- a/tools/arch/x86/include/asm/disabled-features.h
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -56,5 +56,7 @@
#define DISABLED_MASK14 0
#define DISABLED_MASK15 0
#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE)
+#define DISABLED_MASK17 0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
#endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h
index 4916144e3c42..fac9a5c0abe9 100644
--- a/tools/arch/x86/include/asm/required-features.h
+++ b/tools/arch/x86/include/asm/required-features.h
@@ -99,5 +99,7 @@
#define REQUIRED_MASK14 0
#define REQUIRED_MASK15 0
#define REQUIRED_MASK16 0
+#define REQUIRED_MASK17 0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
#endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
index 5b15d94a33f8..37fee272618f 100644
--- a/tools/arch/x86/include/uapi/asm/vmx.h
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -78,7 +78,6 @@
#define EXIT_REASON_PML_FULL 62
#define EXIT_REASON_XSAVES 63
#define EXIT_REASON_XRSTORS 64
-#define EXIT_REASON_PCOMMIT 65
#define VMX_EXIT_REASONS \
{ EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
@@ -127,8 +126,7 @@
{ EXIT_REASON_INVVPID, "INVVPID" }, \
{ EXIT_REASON_INVPCID, "INVPCID" }, \
{ EXIT_REASON_XSAVES, "XSAVES" }, \
- { EXIT_REASON_XRSTORS, "XRSTORS" }, \
- { EXIT_REASON_PCOMMIT, "PCOMMIT" }
+ { EXIT_REASON_XRSTORS, "XRSTORS" }
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..43c1c5021e4b 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -3,6 +3,7 @@
#include <string.h>
#include <linux/bitops.h>
+#include <stdlib.h>
#define DECLARE_BITMAP(name,bits) \
unsigned long name[BITS_TO_LONGS(bits)]
@@ -10,6 +11,8 @@
int __bitmap_weight(const unsigned long *bitmap, int bits);
void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
const unsigned long *bitmap2, int bits);
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int bits);
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
@@ -65,4 +68,38 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
return (old & mask) != 0;
}
+/**
+ * bitmap_alloc - Allocate bitmap
+ * @nr: Bit to set
+ */
+static inline unsigned long *bitmap_alloc(int nbits)
+{
+ return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
+}
+
+/*
+ * bitmap_scnprintf - print bitmap list into buffer
+ * @bitmap: bitmap
+ * @nbits: size of bitmap
+ * @buf: buffer to store output
+ * @size: size of @buf
+ */
+size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
+ char *buf, size_t size);
+
+/**
+ * bitmap_and - Do logical and on bitmaps
+ * @dst: resulting bitmap
+ * @src1: operand 1
+ * @src2: operand 2
+ * @nbits: size of bitmap
+ */
+static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, unsigned int nbits)
+{
+ if (small_const_nbits(nbits))
+ return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+ return __bitmap_and(dst, src1, src2, nbits);
+}
+
#endif /* _PERF_BITOPS_H */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 406459b935a2..da218fec6056 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -84,6 +84,7 @@ enum bpf_map_type {
BPF_MAP_TYPE_PERCPU_HASH,
BPF_MAP_TYPE_PERCPU_ARRAY,
BPF_MAP_TYPE_STACK_TRACE,
+ BPF_MAP_TYPE_CGROUP_ARRAY,
};
enum bpf_prog_type {
@@ -93,6 +94,7 @@ enum bpf_prog_type {
BPF_PROG_TYPE_SCHED_CLS,
BPF_PROG_TYPE_SCHED_ACT,
BPF_PROG_TYPE_TRACEPOINT,
+ BPF_PROG_TYPE_XDP,
};
#define BPF_PSEUDO_MAP_FD 1
@@ -313,6 +315,66 @@ enum bpf_func_id {
*/
BPF_FUNC_skb_get_tunnel_opt,
BPF_FUNC_skb_set_tunnel_opt,
+
+ /**
+ * bpf_skb_change_proto(skb, proto, flags)
+ * Change protocol of the skb. Currently supported is
+ * v4 -> v6, v6 -> v4 transitions. The helper will also
+ * resize the skb. eBPF program is expected to fill the
+ * new headers via skb_store_bytes and lX_csum_replace.
+ * @skb: pointer to skb
+ * @proto: new skb->protocol type
+ * @flags: reserved
+ * Return: 0 on success or negative error
+ */
+ BPF_FUNC_skb_change_proto,
+
+ /**
+ * bpf_skb_change_type(skb, type)
+ * Change packet type of skb.
+ * @skb: pointer to skb
+ * @type: new skb->pkt_type type
+ * Return: 0 on success or negative error
+ */
+ BPF_FUNC_skb_change_type,
+
+ /**
+ * bpf_skb_in_cgroup(skb, map, index) - Check cgroup2 membership of skb
+ * @skb: pointer to skb
+ * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
+ * @index: index of the cgroup in the bpf_map
+ * Return:
+ * == 0 skb failed the cgroup2 descendant test
+ * == 1 skb succeeded the cgroup2 descendant test
+ * < 0 error
+ */
+ BPF_FUNC_skb_in_cgroup,
+
+ /**
+ * bpf_get_hash_recalc(skb)
+ * Retrieve and possibly recalculate skb->hash.
+ * @skb: pointer to skb
+ * Return: hash
+ */
+ BPF_FUNC_get_hash_recalc,
+
+ /**
+ * u64 bpf_get_current_task(void)
+ * Returns current task_struct
+ * Return: current
+ */
+ BPF_FUNC_get_current_task,
+
+ /**
+ * bpf_probe_write_user(void *dst, void *src, int len)
+ * safely attempt to write to a location
+ * @dst: destination address in userspace
+ * @src: source address on stack
+ * @len: number of bytes to copy
+ * Return: 0 on success or negative error
+ */
+ BPF_FUNC_probe_write_user,
+
__BPF_FUNC_MAX_ID,
};
@@ -347,9 +409,11 @@ enum bpf_func_id {
#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
#define BPF_F_DONT_FRAGMENT (1ULL << 2)
-/* BPF_FUNC_perf_event_output flags. */
+/* BPF_FUNC_perf_event_output and BPF_FUNC_perf_event_read flags. */
#define BPF_F_INDEX_MASK 0xffffffffULL
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
+/* BPF_FUNC_perf_event_output for sk_buff input context. */
+#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
/* user accessible mirror of in-kernel sk_buff.
* new fields can only be added to the end of this structure
@@ -386,4 +450,24 @@ struct bpf_tunnel_key {
__u32 tunnel_label;
};
+/* User return codes for XDP prog type.
+ * A valid XDP program must return one of these defined values. All other
+ * return codes are reserved for future use. Unknown return codes will result
+ * in packet drop.
+ */
+enum xdp_action {
+ XDP_ABORTED = 0,
+ XDP_DROP,
+ XDP_PASS,
+ XDP_TX,
+};
+
+/* user accessible metadata for XDP packet hook
+ * new fields must be added to the end of this structure
+ */
+struct xdp_md {
+ __u32 data;
+ __u32 data_end;
+};
+
#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adc1111fd..38748b0e342f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,47 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
for (k = 0; k < nr; k++)
dst[k] = bitmap1[k] | bitmap2[k];
}
+
+size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
+ char *buf, size_t size)
+{
+ /* current bit is 'cur', most recently seen range is [rbot, rtop] */
+ int cur, rbot, rtop;
+ bool first = true;
+ size_t ret = 0;
+
+ rbot = cur = find_first_bit(bitmap, nbits);
+ while (cur < nbits) {
+ rtop = cur;
+ cur = find_next_bit(bitmap, nbits, cur + 1);
+ if (cur < nbits && cur <= rtop + 1)
+ continue;
+
+ if (!first)
+ ret += scnprintf(buf + ret, size - ret, ",");
+
+ first = false;
+
+ ret += scnprintf(buf + ret, size - ret, "%d", rbot);
+ if (rbot < rtop)
+ ret += scnprintf(buf + ret, size - ret, "-%d", rtop);
+
+ rbot = cur;
+ }
+ return ret;
+}
+
+int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int bits)
+{
+ unsigned int k;
+ unsigned int lim = bits/BITS_PER_LONG;
+ unsigned long result = 0;
+
+ for (k = 0; k < lim; k++)
+ result |= (dst[k] = bitmap1[k] & bitmap2[k]);
+ if (bits % BITS_PER_LONG)
+ result |= (dst[k] = bitmap1[k] & bitmap2[k] &
+ BITMAP_LAST_WORD_MASK(bits));
+ return result != 0;
+}
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
index 3c60335fe7be..9e9f25fb1922 100644
--- a/tools/lib/traceevent/.gitignore
+++ b/tools/lib/traceevent/.gitignore
@@ -1,2 +1,3 @@
TRACEEVENT-CFLAGS
libtraceevent-dynamic-list
+libtraceevent.so.*
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 736da44596e4..b303bcdd8ed1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -176,10 +176,18 @@ Each probe argument follows below syntax.
'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters.
-'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
+'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. Currently, basic types (u8/u16/u32/u64/s8/s16/s32/s64), signedness casting (u/s), "string" and bitfield are supported. (see TYPES for detail)
On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
+TYPES
+-----
+Basic types (u8/u16/u32/u64/s8/s16/s32/s64) are integer types. Prefix 's' and 'u' means those types are signed and unsigned respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). You can also use 's' or 'u' to specify only signedness and leave its size auto-detected by perf probe.
+String type is a special type, which fetches a "null-terminated" string from kernel space. This means it will fail and store NULL if the string container has been paged out. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
+Bitfield is another special type, which takes 3 parameters, bit-width, bit-offset, and container-size (usually 32). The syntax is;
+
+ b<bit-width>@<bit-offset>/<container-size>
+
LINE SYNTAX
-----------
Line range is described by following syntax.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 69966abf65d1..379a2bed07c0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -192,6 +192,9 @@ OPTIONS
--period::
Record the sample period.
+--sample-cpu::
+ Record the sample cpu.
+
-n::
--no-samples::
Don't sample.
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 1f6c70594f0f..053bbbd84ece 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,8 +116,8 @@ OPTIONS
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
- srcline, period, iregs, brstack, brstacksym, flags.
- Field list can be prepended with the type, trace, sw or hw,
+ srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
+ callindent. Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
diff --git a/tools/perf/config/Makefile b/tools/perf/Makefile.config
index 24803c58049a..24803c58049a 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/Makefile.config
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 6641abb97f0a..2d9087501633 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -161,7 +161,7 @@ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
BPF_DIR = $(srctree)/tools/lib/bpf/
SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
-# include config/Makefile by default and rule out
+# include Makefile.config by default and rule out
# non-config cases
config := 1
@@ -183,7 +183,7 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
FEATURE_TESTS := all
endif
endif
-include config/Makefile
+include Makefile.config
endif
ifeq ($(config),0)
@@ -706,7 +706,7 @@ $(INSTALL_DOC_TARGETS):
### Cleaning rules
#
-# This is here, not in config/Makefile, because config/Makefile does
+# This is here, not in Makefile.config, because Makefile.config does
# not get included for the clean target:
#
config-clean:
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index c6d0f91731a1..8d4dc97d80ba 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -54,10 +54,6 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
#endif
#if defined(_CALL_ELF) && _CALL_ELF == 2
-bool arch__prefers_symtab(void)
-{
- return true;
-}
#ifdef HAVE_LIBELF_SUPPORT
void arch__sym_update(struct symbol *s, GElf_Sym *sym)
@@ -100,4 +96,27 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
tev->point.offset += lep_offset;
}
}
+
+void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
+ int ntevs)
+{
+ struct probe_trace_event *tev;
+ struct map *map;
+ struct symbol *sym = NULL;
+ struct rb_node *tmp;
+ int i = 0;
+
+ map = get_target_map(pev->target, pev->uprobes);
+ if (!map || map__load(map, NULL) < 0)
+ return;
+
+ for (i = 0; i < ntevs; i++) {
+ tev = &pev->tevs[i];
+ map__for_each_symbol(map, sym, tmp) {
+ if (map->unmap_ip(map, sym->start) == tev->point.address)
+ arch__fix_tev_from_maps(pev, tev, map, sym);
+ }
+ }
+}
+
#endif
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 8f2c16d9275f..6355902fbfc8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1434,6 +1434,7 @@ struct option __record_options[] = {
OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
"per thread counts"),
OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
+ OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
&record.opts.sample_time_set,
"Record the sample timestamps"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 971ff91b16cb..9c640a8081c7 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -2116,7 +2116,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
- "callindent", parse_output_fields),
+ "bpf-output,callindent", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 0c16d20d7e32..3c7452b39f57 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -331,7 +331,7 @@ static int read_counter(struct perf_evsel *counter)
return 0;
}
-static void read_counters(bool close_counters)
+static void read_counters(void)
{
struct perf_evsel *counter;
@@ -341,11 +341,6 @@ static void read_counters(bool close_counters)
if (perf_stat_process_counter(&stat_config, counter))
pr_warning("failed to process counter %s\n", counter->name);
-
- if (close_counters) {
- perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
- thread_map__nr(evsel_list->threads));
- }
}
}
@@ -353,7 +348,7 @@ static void process_interval(void)
{
struct timespec ts, rs;
- read_counters(false);
+ read_counters();
clock_gettime(CLOCK_MONOTONIC, &ts);
diff_timespec(&rs, &ts, &ref_time);
@@ -380,6 +375,17 @@ static void enable_counters(void)
perf_evlist__enable(evsel_list);
}
+static void disable_counters(void)
+{
+ /*
+ * If we don't have tracee (attaching to task or cpu), counters may
+ * still be running. To get accurate group ratios, we must stop groups
+ * from counting before reading their constituent counters.
+ */
+ if (!target__none(&target))
+ perf_evlist__disable(evsel_list);
+}
+
static volatile int workload_exec_errno;
/*
@@ -657,11 +663,20 @@ try_again:
}
}
+ disable_counters();
+
t1 = rdclock();
update_stats(&walltime_nsecs_stats, t1 - t0);
- read_counters(true);
+ /*
+ * Closing a group leader splits the group, and as we only disable
+ * group leaders, results in remaining events becoming enabled. To
+ * avoid arbitrary skew, we must read all counters before closing any
+ * group leaders.
+ */
+ read_counters();
+ perf_evlist__close(evsel_list);
return WEXITSTATUS(status);
}
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bd108683fcb8..418ed94756d3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -128,10 +128,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err;
}
- err = symbol__annotate(sym, map, 0);
+ err = symbol__disassemble(sym, map, 0);
if (err == 0) {
out_assign:
top->sym_filter_entry = he;
+ } else {
+ char msg[BUFSIZ];
+ symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
+ pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
}
pthread_mutex_unlock(&notes->lock);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index a7e0f1497244..cb0f1356ff81 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,6 +52,7 @@ struct record_opts {
bool sample_weight;
bool sample_time;
bool sample_time_set;
+ bool sample_cpu;
bool period;
bool running_time;
bool full_auxtrace;
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
index 928e110179cb..34faecf774ae 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Build
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build
@@ -1,3 +1,5 @@
libperf-y += Context.o
-CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default
+CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes
+CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef
+CFLAGS_Context.o += -Wno-switch-default -Wno-shadow
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index cb20ae1c0d35..dc51bc570e51 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -41,6 +41,7 @@ perf-y += event-times.o
perf-y += backward-ring-buffer.o
perf-y += sdt.o
perf-y += is_printable_array.o
+perf-y += bitmap.o
$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
$(call rule_mkdir)
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
new file mode 100644
index 000000000000..9abe6c13090f
--- /dev/null
+++ b/tools/perf/tests/bitmap.c
@@ -0,0 +1,53 @@
+#include <linux/compiler.h>
+#include <linux/bitmap.h>
+#include "tests.h"
+#include "cpumap.h"
+#include "debug.h"
+
+#define NBITS 100
+
+static unsigned long *get_bitmap(const char *str, int nbits)
+{
+ struct cpu_map *map = cpu_map__new(str);
+ unsigned long *bm = NULL;
+ int i;
+
+ bm = bitmap_alloc(nbits);
+
+ if (map && bm) {
+ bitmap_zero(bm, nbits);
+
+ for (i = 0; i < map->nr; i++)
+ set_bit(map->map[i], bm);
+ }
+
+ if (map)
+ cpu_map__put(map);
+ return bm;
+}
+
+static int test_bitmap(const char *str)
+{
+ unsigned long *bm = get_bitmap(str, NBITS);
+ char buf[100];
+ int ret;
+
+ bitmap_scnprintf(bm, NBITS, buf, sizeof(buf));
+ pr_debug("bitmap: %s\n", buf);
+
+ ret = !strcmp(buf, str);
+ free(bm);
+ return ret;
+}
+
+int test__bitmap_print(int subtest __maybe_unused)
+{
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3,5,7,9,11,13,15,17,19,21-40"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("2-5"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
+ TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40"));
+ return 0;
+}
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index e53bc91fa260..268e5f8e4aa2 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -31,8 +31,8 @@ struct bpf_map_def SEC("maps") flip_table = {
.max_entries = 1,
};
-SEC("func=sys_epoll_wait")
-int bpf_func__sys_epoll_wait(void *ctx)
+SEC("func=SyS_epoll_wait")
+int bpf_func__SyS_epoll_wait(void *ctx)
{
int ind =0;
int *flag = bpf_map_lookup_elem(&flip_table, &ind);
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 10eb30686c9c..778668a2a966 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -226,6 +226,10 @@ static struct test generic_tests[] = {
.func = test__is_printable_array,
},
{
+ .desc = "Test bitmap print",
+ .func = test__bitmap_print,
+ },
+ {
.func = NULL,
},
};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 68a69a195545..2af156a8d4e5 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -33,44 +33,86 @@ static unsigned int hex(char c)
return c - 'A' + 10;
}
-static size_t read_objdump_line(const char *line, size_t line_len, void *buf,
- size_t len)
+static size_t read_objdump_chunk(const char **line, unsigned char **buf,
+ size_t *buf_len)
{
- const char *p;
- size_t i, j = 0;
-
- /* Skip to a colon */
- p = strchr(line, ':');
- if (!p)
- return 0;
- i = p + 1 - line;
+ size_t bytes_read = 0;
+ unsigned char *chunk_start = *buf;
/* Read bytes */
- while (j < len) {
+ while (*buf_len > 0) {
char c1, c2;
- /* Skip spaces */
- for (; i < line_len; i++) {
- if (!isspace(line[i]))
- break;
- }
/* Get 2 hex digits */
- if (i >= line_len || !isxdigit(line[i]))
+ c1 = *(*line)++;
+ if (!isxdigit(c1))
break;
- c1 = line[i++];
- if (i >= line_len || !isxdigit(line[i]))
+ c2 = *(*line)++;
+ if (!isxdigit(c2))
break;
- c2 = line[i++];
- /* Followed by a space */
- if (i < line_len && line[i] && !isspace(line[i]))
+
+ /* Store byte and advance buf */
+ **buf = (hex(c1) << 4) | hex(c2);
+ (*buf)++;
+ (*buf_len)--;
+ bytes_read++;
+
+ /* End of chunk? */
+ if (isspace(**line))
break;
- /* Store byte */
- *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
- buf += 1;
- j++;
}
+
+ /*
+ * objdump will display raw insn as LE if code endian
+ * is LE and bytes_per_chunk > 1. In that case reverse
+ * the chunk we just read.
+ *
+ * see disassemble_bytes() at binutils/objdump.c for details
+ * how objdump chooses display endian)
+ */
+ if (bytes_read > 1 && !bigendian()) {
+ unsigned char *chunk_end = chunk_start + bytes_read - 1;
+ unsigned char tmp;
+
+ while (chunk_start < chunk_end) {
+ tmp = *chunk_start;
+ *chunk_start = *chunk_end;
+ *chunk_end = tmp;
+ chunk_start++;
+ chunk_end--;
+ }
+ }
+
+ return bytes_read;
+}
+
+static size_t read_objdump_line(const char *line, unsigned char *buf,
+ size_t buf_len)
+{
+ const char *p;
+ size_t ret, bytes_read = 0;
+
+ /* Skip to a colon */
+ p = strchr(line, ':');
+ if (!p)
+ return 0;
+ p++;
+
+ /* Skip initial spaces */
+ while (*p) {
+ if (!isspace(*p))
+ break;
+ p++;
+ }
+
+ do {
+ ret = read_objdump_chunk(&p, &buf, &buf_len);
+ bytes_read += ret;
+ p++;
+ } while (ret > 0);
+
/* return number of successfully read bytes */
- return j;
+ return bytes_read;
}
static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
@@ -95,7 +137,7 @@ static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
}
/* read objdump data into temporary buffer */
- read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp));
+ read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
if (!read_bytes)
continue;
@@ -152,7 +194,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
ret = read_objdump_output(f, buf, &len, addr);
if (len) {
- pr_debug("objdump read too few bytes\n");
+ pr_debug("objdump read too few bytes: %zd\n", len);
if (!ret)
ret = len;
}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 9bfc0e06c61a..7c196c585472 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -90,6 +90,7 @@ int test__backward_ring_buffer(int subtest);
int test__cpu_map_print(int subtest);
int test__sdt_event(int subtest);
int test__is_printable_array(int subtest);
+int test__bitmap_print(int subtest);
#if defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 29dc6d20364e..2e2d10022355 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -1026,7 +1026,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
.use_navkeypressed = true,
},
};
- int ret = -1;
+ int ret = -1, err;
int nr_pcnt = 1;
size_t sizeof_bdl = sizeof(struct browser_disasm_line);
@@ -1050,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
(nr_pcnt - 1);
}
- if (symbol__annotate(sym, map, sizeof_bdl) < 0) {
- ui__error("%s", ui_helpline__last_msg);
+ err = symbol__disassemble(sym, map, sizeof_bdl);
+ if (err) {
+ char msg[BUFSIZ];
+ symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
+ ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
goto out_free_offsets;
}
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 9c7ff8d31b27..42d319927762 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -162,12 +162,16 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
GtkWidget *notebook;
GtkWidget *scrolled_window;
GtkWidget *tab_label;
+ int err;
if (map->dso->annotate_warned)
return -1;
- if (symbol__annotate(sym, map, 0) < 0) {
- ui__error("%s", ui_helpline__current);
+ err = symbol__disassemble(sym, map, 0);
+ if (err) {
+ char msg[BUFSIZ];
+ symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
+ ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
return -1;
}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index e9825fe825fd..4024d309bb00 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -1123,7 +1123,46 @@ static void delete_last_nop(struct symbol *sym)
}
}
-int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
+int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
+ int errnum, char *buf, size_t buflen)
+{
+ struct dso *dso = map->dso;
+
+ BUG_ON(buflen == 0);
+
+ if (errnum >= 0) {
+ str_error_r(errnum, buf, buflen);
+ return 0;
+ }
+
+ switch (errnum) {
+ case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
+ char bf[SBUILD_ID_SIZE + 15] = " with build id ";
+ char *build_id_msg = NULL;
+
+ if (dso->has_build_id) {
+ build_id__sprintf(dso->build_id,
+ sizeof(dso->build_id), bf + 15);
+ build_id_msg = bf;
+ }
+ scnprintf(buf, buflen,
+ "No vmlinux file%s\nwas found in the path.\n\n"
+ "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
+ "Please use:\n\n"
+ " perf buildid-cache -vu vmlinux\n\n"
+ "or:\n\n"
+ " --vmlinux vmlinux\n", build_id_msg ?: "");
+ }
+ break;
+ default:
+ scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
+ break;
+ }
+
+ return 0;
+}
+
+int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
{
struct dso *dso = map->dso;
char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -1134,22 +1173,20 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
char symfs_filename[PATH_MAX];
struct kcore_extract kce;
bool delete_extract = false;
+ int stdout_fd[2];
int lineno = 0;
int nline;
+ pid_t pid;
if (filename)
symbol__join_symfs(symfs_filename, filename);
if (filename == NULL) {
- if (dso->has_build_id) {
- pr_err("Can't annotate %s: not enough memory\n",
- sym->name);
- return -ENOMEM;
- }
+ if (dso->has_build_id)
+ return ENOMEM;
goto fallback;
- } else if (dso__is_kcore(dso)) {
- goto fallback;
- } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
+ } else if (dso__is_kcore(dso) ||
+ readlink(symfs_filename, command, sizeof(command)) < 0 ||
strstr(command, DSO__NAME_KALLSYMS) ||
access(symfs_filename, R_OK)) {
free(filename);
@@ -1166,27 +1203,7 @@ fallback:
if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
!dso__is_kcore(dso)) {
- char bf[SBUILD_ID_SIZE + 15] = " with build id ";
- char *build_id_msg = NULL;
-
- if (dso->annotate_warned)
- goto out_free_filename;
-
- if (dso->has_build_id) {
- build_id__sprintf(dso->build_id,
- sizeof(dso->build_id), bf + 15);
- build_id_msg = bf;
- }
- err = -ENOENT;
- dso->annotate_warned = 1;
- pr_err("Can't annotate %s:\n\n"
- "No vmlinux file%s\nwas found in the path.\n\n"
- "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
- "Please use:\n\n"
- " perf buildid-cache -vu vmlinux\n\n"
- "or:\n\n"
- " --vmlinux vmlinux\n",
- sym->name, build_id_msg ?: "");
+ err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
goto out_free_filename;
}
@@ -1258,9 +1275,32 @@ fallback:
pr_debug("Executing: %s\n", command);
- file = popen(command, "r");
+ err = -1;
+ if (pipe(stdout_fd) < 0) {
+ pr_err("Failure creating the pipe to run %s\n", command);
+ goto out_remove_tmp;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ pr_err("Failure forking to run %s\n", command);
+ goto out_close_stdout;
+ }
+
+ if (pid == 0) {
+ close(stdout_fd[0]);
+ dup2(stdout_fd[1], 1);
+ close(stdout_fd[1]);
+ execl("/bin/sh", "sh", "-c", command, NULL);
+ perror(command);
+ exit(-1);
+ }
+
+ close(stdout_fd[1]);
+
+ file = fdopen(stdout_fd[0], "r");
if (!file) {
- pr_err("Failure running %s\n", command);
+ pr_err("Failure creating FILE stream for %s\n", command);
/*
* If we were using debug info should retry with
* original binary.
@@ -1286,9 +1326,11 @@ fallback:
if (dso__is_kcore(dso))
delete_last_nop(sym);
- pclose(file);
-
+ fclose(file);
+ err = 0;
out_remove_tmp:
+ close(stdout_fd[0]);
+
if (dso__needs_decompress(dso))
unlink(symfs_filename);
out_free_filename:
@@ -1297,6 +1339,10 @@ out_free_filename:
if (free_filename)
free(filename);
return err;
+
+out_close_stdout:
+ close(stdout_fd[1]);
+ goto out_remove_tmp;
}
static void insert_source_line(struct rb_root *root, struct source_line *src_line)
@@ -1663,7 +1709,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
struct rb_root source_line = RB_ROOT;
u64 len;
- if (symbol__annotate(sym, map, 0) < 0)
+ if (symbol__disassemble(sym, map, 0) < 0)
return -1;
len = symbol__size(sym);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a23084f54128..f67ccb027561 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -155,7 +155,27 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(struct symbol *sym);
-int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
+int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize);
+
+enum symbol_disassemble_errno {
+ SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
+
+ /*
+ * Choose an arbitrary negative big number not to clash with standard
+ * errno since SUS requires the errno has distinct positive values.
+ * See 'Issue 6' in the link below.
+ *
+ * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
+ */
+ __SYMBOL_ANNOTATE_ERRNO__START = -10000,
+
+ SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
+
+ __SYMBOL_ANNOTATE_ERRNO__END,
+};
+
+int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
+ int errnum, char *buf, size_t buflen);
int symbol__annotate_init(struct map *map, struct symbol *sym);
int symbol__annotate_printf(struct symbol *sym, struct map *map,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 2a40b8e1def7..097b3ed77fdd 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -239,31 +239,13 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
int perf_evlist__add_default(struct perf_evlist *evlist)
{
- struct perf_event_attr attr = {
- .type = PERF_TYPE_HARDWARE,
- .config = PERF_COUNT_HW_CPU_CYCLES,
- };
- struct perf_evsel *evsel;
-
- event_attr_init(&attr);
+ struct perf_evsel *evsel = perf_evsel__new_cycles();
- perf_event_attr__set_max_precise_ip(&attr);
-
- evsel = perf_evsel__new(&attr);
if (evsel == NULL)
- goto error;
-
- /* use asprintf() because free(evsel) assumes name is allocated */
- if (asprintf(&evsel->name, "cycles%.*s",
- attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
- goto error_free;
+ return -ENOMEM;
perf_evlist__add(evlist, evsel);
return 0;
-error_free:
- perf_evsel__delete(evsel);
-error:
- return -ENOMEM;
}
int perf_evlist__add_dummy(struct perf_evlist *evlist)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8c54df61fe64..d9b80ef881cd 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -253,6 +253,34 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
return evsel;
}
+struct perf_evsel *perf_evsel__new_cycles(void)
+{
+ struct perf_event_attr attr = {
+ .type = PERF_TYPE_HARDWARE,
+ .config = PERF_COUNT_HW_CPU_CYCLES,
+ };
+ struct perf_evsel *evsel;
+
+ event_attr_init(&attr);
+
+ perf_event_attr__set_max_precise_ip(&attr);
+
+ evsel = perf_evsel__new(&attr);
+ if (evsel == NULL)
+ goto out;
+
+ /* use asprintf() because free(evsel) assumes name is allocated */
+ if (asprintf(&evsel->name, "cycles%.*s",
+ attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
+ goto error_free;
+out:
+ return evsel;
+error_free:
+ perf_evsel__delete(evsel);
+ evsel = NULL;
+ goto out;
+}
+
/*
* Returns pointer with encoded error via <linux/err.h> interface.
*/
@@ -854,7 +882,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
perf_evsel__set_sample_bit(evsel, REGS_INTR);
}
- if (target__has_cpu(&opts->target))
+ if (target__has_cpu(&opts->target) || opts->sample_cpu)
perf_evsel__set_sample_bit(evsel, CPU);
if (opts->period)
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 8a4a6c9f1480..4d44129e050b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -175,6 +175,8 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
return perf_evsel__newtp_idx(sys, name, 0);
}
+struct perf_evsel *perf_evsel__new_cycles(void);
+
struct event_format *event_format__new(const char *sys, const char *name);
void perf_evsel__init(struct perf_evsel *evsel,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a18d142cdca3..de15dbcdcecf 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1672,7 +1672,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
}
static void output_resort(struct hists *hists, struct ui_progress *prog,
- bool use_callchain)
+ bool use_callchain, hists__resort_cb_t cb)
{
struct rb_root *root;
struct rb_node *next;
@@ -1711,6 +1711,9 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
n = rb_entry(next, struct hist_entry, rb_node_in);
next = rb_next(&n->rb_node_in);
+ if (cb && cb(n))
+ continue;
+
__hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain);
hists__inc_stats(hists, n);
@@ -1731,12 +1734,18 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
else
use_callchain = symbol_conf.use_callchain;
- output_resort(evsel__hists(evsel), prog, use_callchain);
+ output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
}
void hists__output_resort(struct hists *hists, struct ui_progress *prog)
{
- output_resort(hists, prog, symbol_conf.use_callchain);
+ output_resort(hists, prog, symbol_conf.use_callchain, NULL);
+}
+
+void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
+ hists__resort_cb_t cb)
+{
+ output_resort(hists, prog, symbol_conf.use_callchain, cb);
}
static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 49aa4fac148f..0a1edf1ab450 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -153,8 +153,12 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
struct perf_hpp_fmt *fmt, int printed);
void hist_entry__delete(struct hist_entry *he);
+typedef int (*hists__resort_cb_t)(struct hist_entry *he);
+
void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
void hists__output_resort(struct hists *hists, struct ui_progress *prog);
+void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
+ hists__resort_cb_t cb);
int hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 953dc1ab2ed7..28733962cd80 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -170,15 +170,17 @@ static struct map *kernel_get_module_map(const char *module)
module = "kernel";
for (pos = maps__first(maps); pos; pos = map__next(pos)) {
+ /* short_name is "[module]" */
if (strncmp(pos->dso->short_name + 1, module,
- pos->dso->short_name_len - 2) == 0) {
+ pos->dso->short_name_len - 2) == 0 &&
+ module[pos->dso->short_name_len - 2] == '\0') {
return pos;
}
}
return NULL;
}
-static struct map *get_target_map(const char *target, bool user)
+struct map *get_target_map(const char *target, bool user)
{
/* Init maps of given executable or kernel */
if (user)
@@ -385,7 +387,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
if (uprobes)
address = sym->start;
else
- address = map->unmap_ip(map, sym->start);
+ address = map->unmap_ip(map, sym->start) - map->reloc;
break;
}
if (!address) {
@@ -664,22 +666,14 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
return ret;
}
-/* Post processing the probe events */
-static int post_process_probe_trace_events(struct probe_trace_event *tevs,
- int ntevs, const char *module,
- bool uprobe)
+static int
+post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
+ int ntevs)
{
struct ref_reloc_sym *reloc_sym;
char *tmp;
int i, skipped = 0;
- if (uprobe)
- return add_exec_to_probe_trace_events(tevs, ntevs, module);
-
- /* Note that currently ref_reloc_sym based probe is not for drivers */
- if (module)
- return add_module_to_probe_trace_events(tevs, ntevs, module);
-
reloc_sym = kernel_get_ref_reloc_sym();
if (!reloc_sym) {
pr_warning("Relocated base symbol is not found!\n");
@@ -711,6 +705,34 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
return skipped;
}
+void __weak
+arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unused,
+ int ntevs __maybe_unused)
+{
+}
+
+/* Post processing the probe events */
+static int post_process_probe_trace_events(struct perf_probe_event *pev,
+ struct probe_trace_event *tevs,
+ int ntevs, const char *module,
+ bool uprobe)
+{
+ int ret;
+
+ if (uprobe)
+ ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
+ else if (module)
+ /* Currently ref_reloc_sym based probe is not for drivers */
+ ret = add_module_to_probe_trace_events(tevs, ntevs, module);
+ else
+ ret = post_process_kernel_probe_trace_events(tevs, ntevs);
+
+ if (ret >= 0)
+ arch__post_process_probe_trace_events(pev, ntevs);
+
+ return ret;
+}
+
/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs)
@@ -749,7 +771,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("Found %d probe_trace_events.\n", ntevs);
- ret = post_process_probe_trace_events(*tevs, ntevs,
+ ret = post_process_probe_trace_events(pev, *tevs, ntevs,
pev->target, pev->uprobes);
if (ret < 0 || ret == ntevs) {
clear_probe_trace_events(*tevs, ntevs);
@@ -2936,8 +2958,6 @@ errout:
return err;
}
-bool __weak arch__prefers_symtab(void) { return false; }
-
/* Concatinate two arrays */
static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
{
@@ -3158,12 +3178,6 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */
return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
- if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
- ret = find_probe_trace_events_from_map(pev, tevs);
- if (ret > 0)
- return ret; /* Found in symbol table */
- }
-
/* Convert perf_probe_event with debuginfo */
ret = try_to_find_probe_trace_events(pev, tevs);
if (ret != 0)
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e18ea9fe6385..f4f45db77c1c 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -158,7 +158,6 @@ int show_line_range(struct line_range *lr, const char *module, bool user);
int show_available_vars(struct perf_probe_event *pevs, int npevs,
struct strfilter *filter);
int show_available_funcs(const char *module, struct strfilter *filter, bool user);
-bool arch__prefers_symtab(void);
void arch__fix_tev_from_maps(struct perf_probe_event *pev,
struct probe_trace_event *tev, struct map *map,
struct symbol *sym);
@@ -173,4 +172,9 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
struct perf_probe_arg *pvar);
+struct map *get_target_map(const char *target, bool user);
+
+void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
+ int ntevs);
+
#endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index f2d9ff064e2d..5c290c682afe 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -297,10 +297,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
char sbuf[STRERR_BUFSIZE];
int bsize, boffs, total;
int ret;
+ char sign;
/* TODO: check all types */
- if (cast && strcmp(cast, "string") != 0) {
+ if (cast && strcmp(cast, "string") != 0 &&
+ strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
/* Non string type is OK */
+ /* and respect signedness cast */
tvar->type = strdup(cast);
return (tvar->type == NULL) ? -ENOMEM : 0;
}
@@ -361,6 +364,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
return (tvar->type == NULL) ? -ENOMEM : 0;
}
+ if (cast && (strcmp(cast, "u") == 0))
+ sign = 'u';
+ else if (cast && (strcmp(cast, "s") == 0))
+ sign = 's';
+ else
+ sign = die_is_signed_type(&type) ? 's' : 'u';
+
ret = dwarf_bytesize(&type);
if (ret <= 0)
/* No size ... try to use default type */
@@ -373,8 +383,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
ret = MAX_BASIC_TYPE_BITS;
}
- ret = snprintf(buf, 16, "%c%d",
- die_is_signed_type(&type) ? 's' : 'u', ret);
+ ret = snprintf(buf, 16, "%c%d", sign, ret);
formatted:
if (ret < 0 || ret >= 16) {
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 947d21f38398..3d3cb8392c86 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -588,7 +588,11 @@ static char *get_trace_output(struct hist_entry *he)
} else {
pevent_event_info(&seq, evsel->tp_format, &rec);
}
- return seq.buffer;
+ /*
+ * Trim the buffer, it starts at 4KB and we're not going to
+ * add anything more to this buffer.
+ */
+ return realloc(seq.buffer, seq.len + 1);
}
static int64_t
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 8cdcf4641c51..21c4d9b23c24 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -122,11 +122,7 @@ int target__strerror(struct target *target, int errnum,
BUG_ON(buflen == 0);
if (errnum >= 0) {
- const char *err = str_error_r(errnum, buf, buflen);
-
- if (err != buf)
- scnprintf(buf, buflen, "%s", err);
-
+ str_error_r(errnum, buf, buflen);
return 0;
}
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 5404efa578a3..dd48f421844c 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
#include <linux/libnvdimm.h>
#include <linux/vmalloc.h>
#include <linux/device.h>
@@ -1474,6 +1475,7 @@ static int nfit_test_probe(struct platform_device *pdev)
if (nfit_test->setup != nfit_test0_setup)
return 0;
+ flush_work(&acpi_desc->work);
nfit_test->setup_hotplug = 1;
nfit_test->setup(nfit_test);
diff --git a/tools/testing/selftests/ntb/ntb_test.sh b/tools/testing/selftests/ntb/ntb_test.sh
new file mode 100755
index 000000000000..a676d3eefefb
--- /dev/null
+++ b/tools/testing/selftests/ntb/ntb_test.sh
@@ -0,0 +1,422 @@
+#!/bin/bash
+# Copyright (c) 2016 Microsemi. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it would 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.
+#
+# Author: Logan Gunthorpe <logang@deltatee.com>
+
+REMOTE_HOST=
+LIST_DEVS=FALSE
+
+DEBUGFS=${DEBUGFS-/sys/kernel/debug}
+
+PERF_RUN_ORDER=32
+MAX_MW_SIZE=0
+RUN_DMA_TESTS=
+DONT_CLEANUP=
+MW_SIZE=65536
+
+function show_help()
+{
+ echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV"
+ echo "Run tests on a pair of NTB endpoints."
+ echo
+ echo "If the NTB device loops back to the same host then,"
+ echo "just specifying the two PCI ids on the command line is"
+ echo "sufficient. Otherwise, if the NTB link spans two hosts"
+ echo "use the -r option to specify the hostname for the remote"
+ echo "device. SSH will then be used to test the remote side."
+ echo "An SSH key between the root users of the host would then"
+ echo "be highly recommended."
+ echo
+ echo "Options:"
+ echo " -C don't cleanup ntb modules on exit"
+ echo " -d run dma tests"
+ echo " -h show this help message"
+ echo " -l list available local and remote PCI ids"
+ echo " -r REMOTE_HOST specify the remote's hostname to connect"
+ echo " to for the test (using ssh)"
+ echo " -p NUM ntb_perf run order (default: $PERF_RUN_ORDER)"
+ echo " -w max_mw_size maxmium memory window size"
+ echo
+}
+
+function parse_args()
+{
+ OPTIND=0
+ while getopts "Cdhlm:r:p:w:" opt; do
+ case "$opt" in
+ C) DONT_CLEANUP=1 ;;
+ d) RUN_DMA_TESTS=1 ;;
+ h) show_help; exit 0 ;;
+ l) LIST_DEVS=TRUE ;;
+ m) MW_SIZE=${OPTARG} ;;
+ r) REMOTE_HOST=${OPTARG} ;;
+ p) PERF_RUN_ORDER=${OPTARG} ;;
+ w) MAX_MW_SIZE=${OPTARG} ;;
+ \?)
+ echo "Invalid option: -$OPTARG" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+parse_args "$@"
+shift $((OPTIND-1))
+LOCAL_DEV=$1
+shift
+parse_args "$@"
+shift $((OPTIND-1))
+REMOTE_DEV=$1
+shift
+parse_args "$@"
+
+set -e
+
+function _modprobe()
+{
+ modprobe "$@"
+}
+
+function split_remote()
+{
+ VPATH=$1
+ REMOTE=
+
+ if [[ "$VPATH" == *":/"* ]]; then
+ REMOTE=${VPATH%%:*}
+ VPATH=${VPATH#*:}
+ fi
+}
+
+function read_file()
+{
+ split_remote $1
+ if [[ "$REMOTE" != "" ]]; then
+ ssh "$REMOTE" cat "$VPATH"
+ else
+ cat "$VPATH"
+ fi
+}
+
+function write_file()
+{
+ split_remote $2
+ VALUE=$1
+
+ if [[ "$REMOTE" != "" ]]; then
+ ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\""
+ else
+ echo "$VALUE" > "$VPATH"
+ fi
+}
+
+function link_test()
+{
+ LOC=$1
+ REM=$2
+ EXP=0
+
+ echo "Running link tests on: $(basename $LOC) / $(basename $REM)"
+
+ if ! write_file "N" "$LOC/link" 2> /dev/null; then
+ echo " Unsupported"
+ return
+ fi
+
+ write_file "N" "$LOC/link_event"
+
+ if [[ $(read_file "$REM/link") != "N" ]]; then
+ echo "Expected remote link to be down in $REM/link" >&2
+ exit -1
+ fi
+
+ write_file "Y" "$LOC/link"
+ write_file "Y" "$LOC/link_event"
+
+ echo " Passed"
+}
+
+function doorbell_test()
+{
+ LOC=$1
+ REM=$2
+ EXP=0
+
+ echo "Running db tests on: $(basename $LOC) / $(basename $REM)"
+
+ write_file "c 0xFFFFFFFF" "$REM/db"
+
+ for ((i=1; i <= 8; i++)); do
+ let DB=$(read_file "$REM/db") || true
+ if [[ "$DB" != "$EXP" ]]; then
+ echo "Doorbell doesn't match expected value $EXP " \
+ "in $REM/db" >&2
+ exit -1
+ fi
+
+ let "MASK=1 << ($i-1)" || true
+ let "EXP=$EXP | $MASK" || true
+ write_file "s $MASK" "$LOC/peer_db"
+ done
+
+ echo " Passed"
+}
+
+function read_spad()
+{
+ VPATH=$1
+ IDX=$2
+
+ ROW=($(read_file "$VPATH" | grep -e "^$IDX"))
+ let VAL=${ROW[1]} || true
+ echo $VAL
+}
+
+function scratchpad_test()
+{
+ LOC=$1
+ REM=$2
+ CNT=$(read_file "$LOC/spad" | wc -l)
+
+ echo "Running spad tests on: $(basename $LOC) / $(basename $REM)"
+
+ for ((i = 0; i < $CNT; i++)); do
+ VAL=$RANDOM
+ write_file "$i $VAL" "$LOC/peer_spad"
+ RVAL=$(read_spad "$REM/spad" $i)
+
+ if [[ "$VAL" != "$RVAL" ]]; then
+ echo "Scratchpad doesn't match expected value $VAL " \
+ "in $REM/spad, got $RVAL" >&2
+ exit -1
+ fi
+
+ done
+
+ echo " Passed"
+}
+
+function write_mw()
+{
+ split_remote $2
+
+ if [[ "$REMOTE" != "" ]]; then
+ ssh "$REMOTE" \
+ dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
+ else
+ dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
+ fi
+}
+
+function mw_test()
+{
+ IDX=$1
+ LOC=$2
+ REM=$3
+
+ echo "Running $IDX tests on: $(basename $LOC) / $(basename $REM)"
+
+ write_mw "$LOC/$IDX"
+
+ split_remote "$LOC/$IDX"
+ if [[ "$REMOTE" == "" ]]; then
+ A=$VPATH
+ else
+ A=/tmp/ntb_test.$$.A
+ ssh "$REMOTE" cat "$VPATH" > "$A"
+ fi
+
+ split_remote "$REM/peer_$IDX"
+ if [[ "$REMOTE" == "" ]]; then
+ B=$VPATH
+ else
+ B=/tmp/ntb_test.$$.B
+ ssh "$REMOTE" cat "$VPATH" > "$B"
+ fi
+
+ cmp -n $MW_SIZE "$A" "$B"
+ if [[ $? != 0 ]]; then
+ echo "Memory window $MW did not match!" >&2
+ fi
+
+ if [[ "$A" == "/tmp/*" ]]; then
+ rm "$A"
+ fi
+
+ if [[ "$B" == "/tmp/*" ]]; then
+ rm "$B"
+ fi
+
+ echo " Passed"
+}
+
+function pingpong_test()
+{
+ LOC=$1
+ REM=$2
+
+ echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)"
+
+ LOC_START=$(read_file $LOC/count)
+ REM_START=$(read_file $REM/count)
+
+ sleep 7
+
+ LOC_END=$(read_file $LOC/count)
+ REM_END=$(read_file $REM/count)
+
+ if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then
+ echo "Ping pong counter not incrementing!" >&2
+ exit 1
+ fi
+
+ echo " Passed"
+}
+
+function perf_test()
+{
+ USE_DMA=$1
+
+ if [[ $USE_DMA == "1" ]]; then
+ WITH="with"
+ else
+ WITH="without"
+ fi
+
+ _modprobe ntb_perf run_order=$PERF_RUN_ORDER \
+ max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA
+
+ echo "Running local perf test $WITH DMA"
+ write_file "" $LOCAL_PERF/run
+ echo -n " "
+ read_file $LOCAL_PERF/run
+ echo " Passed"
+
+ echo "Running remote perf test $WITH DMA"
+ write_file "" $REMOTE_PERF/run
+ echo -n " "
+ read_file $LOCAL_PERF/run
+ echo " Passed"
+
+ _modprobe -r ntb_perf
+}
+
+function ntb_tool_tests()
+{
+ LOCAL_TOOL=$DEBUGFS/ntb_tool/$LOCAL_DEV
+ REMOTE_TOOL=$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV
+
+ echo "Starting ntb_tool tests..."
+
+ _modprobe ntb_tool
+
+ write_file Y $LOCAL_TOOL/link_event
+ write_file Y $REMOTE_TOOL/link_event
+
+ link_test $LOCAL_TOOL $REMOTE_TOOL
+ link_test $REMOTE_TOOL $LOCAL_TOOL
+
+ for PEER_TRANS in $(ls $LOCAL_TOOL/peer_trans*); do
+ PT=$(basename $PEER_TRANS)
+ write_file $MW_SIZE $LOCAL_TOOL/$PT
+ write_file $MW_SIZE $REMOTE_TOOL/$PT
+ done
+
+ doorbell_test $LOCAL_TOOL $REMOTE_TOOL
+ doorbell_test $REMOTE_TOOL $LOCAL_TOOL
+ scratchpad_test $LOCAL_TOOL $REMOTE_TOOL
+ scratchpad_test $REMOTE_TOOL $LOCAL_TOOL
+
+ for MW in $(ls $LOCAL_TOOL/mw*); do
+ MW=$(basename $MW)
+
+ mw_test $MW $LOCAL_TOOL $REMOTE_TOOL
+ mw_test $MW $REMOTE_TOOL $LOCAL_TOOL
+ done
+
+ _modprobe -r ntb_tool
+}
+
+function ntb_pingpong_tests()
+{
+ LOCAL_PP=$DEBUGFS/ntb_pingpong/$LOCAL_DEV
+ REMOTE_PP=$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV
+
+ echo "Starting ntb_pingpong tests..."
+
+ _modprobe ntb_pingpong
+
+ pingpong_test $LOCAL_PP $REMOTE_PP
+
+ _modprobe -r ntb_pingpong
+}
+
+function ntb_perf_tests()
+{
+ LOCAL_PERF=$DEBUGFS/ntb_perf/$LOCAL_DEV
+ REMOTE_PERF=$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV
+
+ echo "Starting ntb_perf tests..."
+
+ perf_test 0
+
+ if [[ $RUN_DMA_TESTS ]]; then
+ perf_test 1
+ fi
+}
+
+function cleanup()
+{
+ set +e
+ _modprobe -r ntb_tool 2> /dev/null
+ _modprobe -r ntb_perf 2> /dev/null
+ _modprobe -r ntb_pingpong 2> /dev/null
+ _modprobe -r ntb_transport 2> /dev/null
+ set -e
+}
+
+cleanup
+
+if ! [[ $$DONT_CLEANUP ]]; then
+ trap cleanup EXIT
+fi
+
+if [ "$(id -u)" != "0" ]; then
+ echo "This script must be run as root" 1>&2
+ exit 1
+fi
+
+if [[ "$LIST_DEVS" == TRUE ]]; then
+ echo "Local Devices:"
+ ls -1 /sys/bus/ntb/devices
+ echo
+
+ if [[ "$REMOTE_HOST" != "" ]]; then
+ echo "Remote Devices:"
+ ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices
+ fi
+
+ exit 0
+fi
+
+if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then
+ show_help
+ exit 1
+fi
+
+ntb_tool_tests
+echo
+ntb_pingpong_tests
+echo
+ntb_perf_tests
+echo
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 3c40c9d0e6c7..1cc6d64c39b7 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -8,7 +8,7 @@ ifeq ($(ARCH),powerpc)
GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
-CFLAGS := -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
+CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
export CFLAGS
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index 624bce51b27d..4230d3052e5d 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -144,11 +144,12 @@ test_READ:
retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
if (retval == -1) {
- if (errno == ENOTTY) {
+ if (errno == EINVAL) {
fprintf(stderr,
"\n...Alarm IRQs not supported.\n");
goto test_PIE;
}
+
perror("RTC_ALM_SET ioctl");
exit(errno);
}
@@ -166,6 +167,12 @@ test_READ:
/* Enable alarm interrupts */
retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
+ if (errno == EINVAL) {
+ fprintf(stderr,
+ "\n...Alarm IRQs not supported.\n");
+ goto test_PIE;
+ }
+
perror("RTC_AIE_ON ioctl");
exit(errno);
}
@@ -193,7 +200,7 @@ test_PIE:
retval = ioctl(fd, RTC_IRQP_READ, &tmp);
if (retval == -1) {
/* not all RTCs support periodic IRQs */
- if (errno == ENOTTY) {
+ if (errno == EINVAL) {
fprintf(stderr, "\nNo periodic IRQ support\n");
goto done;
}
@@ -211,7 +218,7 @@ test_PIE:
retval = ioctl(fd, RTC_IRQP_SET, tmp);
if (retval == -1) {
/* not all RTCs can change their periodic IRQ rate */
- if (errno == ENOTTY) {
+ if (errno == EINVAL) {
fprintf(stderr,
"\n...Periodic IRQ rate is fixed\n");
goto done;
diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h
index 4f93af89ae16..18601f6689b9 100644
--- a/tools/virtio/linux/dma-mapping.h
+++ b/tools/virtio/linux/dma-mapping.h
@@ -14,4 +14,20 @@ enum dma_data_direction {
DMA_NONE = 3,
};
+#define dma_alloc_coherent(d, s, hp, f) ({ \
+ void *__dma_alloc_coherent_p = kmalloc((s), (f)); \
+ *(hp) = (unsigned long)__dma_alloc_coherent_p; \
+ __dma_alloc_coherent_p; \
+})
+
+#define dma_free_coherent(d, s, p, h) kfree(p)
+
+#define dma_map_page(d, p, o, s, dir) (page_to_phys(p) + (o))
+
+#define dma_map_single(d, p, s, dir) (virt_to_phys(p))
+#define dma_mapping_error(...) (0)
+
+#define dma_unmap_single(...) do { } while (0)
+#define dma_unmap_page(...) do { } while (0)
+
#endif
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 033849948215..d9554fc3f340 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -20,7 +20,9 @@
#define PAGE_SIZE getpagesize()
#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_ALIGN(x) ((x + PAGE_SIZE - 1) & PAGE_MASK)
+typedef unsigned long long phys_addr_t;
typedef unsigned long long dma_addr_t;
typedef size_t __kernel_size_t;
typedef unsigned int __wsum;
@@ -57,6 +59,11 @@ static inline void *kzalloc(size_t s, gfp_t gfp)
return p;
}
+static inline void *alloc_pages_exact(size_t s, gfp_t gfp)
+{
+ return kmalloc(s, gfp);
+}
+
static inline void kfree(void *p)
{
if (p >= __kfree_ignore_start && p < __kfree_ignore_end)
@@ -64,6 +71,11 @@ static inline void kfree(void *p)
free(p);
}
+static inline void free_pages_exact(void *p, size_t s)
+{
+ kfree(p);
+}
+
static inline void *krealloc(void *p, size_t s, gfp_t gfp)
{
return realloc(p, s);
@@ -105,6 +117,8 @@ static inline void free_page(unsigned long addr)
#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#define WARN_ON_ONCE(cond) ((cond) && fprintf (stderr, "WARNING\n"))
+
#define min(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
index 81baeac8ae40..7e1c1197d439 100644
--- a/tools/virtio/linux/slab.h
+++ b/tools/virtio/linux/slab.h
@@ -1,2 +1,6 @@
#ifndef LINUX_SLAB_H
+#define GFP_KERNEL 0
+#define GFP_ATOMIC 0
+#define __GFP_NOWARN 0
+#define __GFP_ZERO 0
#endif
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index ee125e714053..9377c8b4ac16 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -3,8 +3,12 @@
#include <linux/scatterlist.h>
#include <linux/kernel.h>
+struct device {
+ void *parent;
+};
+
struct virtio_device {
- void *dev;
+ struct device dev;
u64 features;
};
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 57a6964a1e35..9ba11815e0a1 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -40,6 +40,19 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev,
#define virtio_has_feature(dev, feature) \
(__virtio_test_bit((dev), feature))
+/**
+ * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
+ * @vdev: the device
+ */
+static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
+{
+ /*
+ * Note the reverse polarity of the quirk feature (compared to most
+ * other features), this is for compatibility with legacy systems.
+ */
+ return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+}
+
static inline bool virtio_is_little_endian(struct virtio_device *vdev)
{
return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c
index 68e4f9f0da3a..bd2ad1d3b7a9 100644
--- a/tools/virtio/ringtest/ptr_ring.c
+++ b/tools/virtio/ringtest/ptr_ring.c
@@ -13,6 +13,7 @@
#define cache_line_size() SMP_CACHE_BYTES
#define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES)))
#define unlikely(x) (__builtin_expect(!!(x), 0))
+#define likely(x) (__builtin_expect(!!(x), 1))
#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a))
typedef pthread_spinlock_t spinlock_t;
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 1e30ce08700d..83777c1cbae0 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -73,12 +73,8 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
int i, vcpu_lock_idx = -1, ret;
struct kvm_vcpu *vcpu;
- mutex_lock(&kvm->lock);
-
- if (irqchip_in_kernel(kvm)) {
- ret = -EEXIST;
- goto out;
- }
+ if (irqchip_in_kernel(kvm))
+ return -EEXIST;
/*
* This function is also called by the KVM_CREATE_IRQCHIP handler,
@@ -87,10 +83,8 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
* the proper checks already.
*/
if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
- !kvm_vgic_global_state.can_emulate_gicv2) {
- ret = -ENODEV;
- goto out;
- }
+ !kvm_vgic_global_state.can_emulate_gicv2)
+ return -ENODEV;
/*
* Any time a vcpu is run, vcpu_load is called which tries to grab the
@@ -138,9 +132,6 @@ out_unlock:
vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
mutex_unlock(&vcpu->mutex);
}
-
-out:
- mutex_unlock(&kvm->lock);
return ret;
}
@@ -264,6 +255,10 @@ int vgic_init(struct kvm *kvm)
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_vgic_vcpu_init(vcpu);
+ ret = kvm_vgic_setup_default_irq_routing(kvm);
+ if (ret)
+ goto out;
+
dist->initialized = true;
out:
return ret;
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c
index c675513270bb..b31a51a14efb 100644
--- a/virt/kvm/arm/vgic/vgic-irqfd.c
+++ b/virt/kvm/arm/vgic/vgic-irqfd.c
@@ -17,36 +17,116 @@
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <trace/events/kvm.h>
+#include <kvm/arm_vgic.h>
+#include "vgic.h"
-int kvm_irq_map_gsi(struct kvm *kvm,
- struct kvm_kernel_irq_routing_entry *entries,
- int gsi)
+/**
+ * vgic_irqfd_set_irq: inject the IRQ corresponding to the
+ * irqchip routing entry
+ *
+ * This is the entry point for irqfd IRQ injection
+ */
+static int vgic_irqfd_set_irq(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
{
- return 0;
+ unsigned int spi_id = e->irqchip.pin + VGIC_NR_PRIVATE_IRQS;
+
+ if (!vgic_valid_spi(kvm, spi_id))
+ return -EINVAL;
+ return kvm_vgic_inject_irq(kvm, 0, spi_id, level);
}
-int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned int irqchip,
- unsigned int pin)
+/**
+ * kvm_set_routing_entry: populate a kvm routing entry
+ * from a user routing entry
+ *
+ * @kvm: the VM this entry is applied to
+ * @e: kvm kernel routing entry handle
+ * @ue: user api routing entry handle
+ * return 0 on success, -EINVAL on errors.
+ */
+#ifdef KVM_CAP_X2APIC_API
+int kvm_set_routing_entry(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+#else
+/* Remove this version and the ifdefery once merged into 4.8 */
+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+#endif
{
- return pin;
+ int r = -EINVAL;
+
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_IRQCHIP:
+ e->set = vgic_irqfd_set_irq;
+ e->irqchip.irqchip = ue->u.irqchip.irqchip;
+ e->irqchip.pin = ue->u.irqchip.pin;
+ if ((e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) ||
+ (e->irqchip.irqchip >= KVM_NR_IRQCHIPS))
+ goto out;
+ break;
+ case KVM_IRQ_ROUTING_MSI:
+ e->set = kvm_set_msi;
+ e->msi.address_lo = ue->u.msi.address_lo;
+ e->msi.address_hi = ue->u.msi.address_hi;
+ e->msi.data = ue->u.msi.data;
+ e->msi.flags = ue->flags;
+ e->msi.devid = ue->u.msi.devid;
+ break;
+ default:
+ goto out;
+ }
+ r = 0;
+out:
+ return r;
}
-int kvm_set_irq(struct kvm *kvm, int irq_source_id,
- u32 irq, int level, bool line_status)
+/**
+ * kvm_set_msi: inject the MSI corresponding to the
+ * MSI routing entry
+ *
+ * This is the entry point for irqfd MSI injection
+ * and userspace MSI injection.
+ */
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
+ struct kvm *kvm, int irq_source_id,
+ int level, bool line_status)
{
- unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS;
+ struct kvm_msi msi;
- trace_kvm_set_irq(irq, level, irq_source_id);
+ msi.address_lo = e->msi.address_lo;
+ msi.address_hi = e->msi.address_hi;
+ msi.data = e->msi.data;
+ msi.flags = e->msi.flags;
+ msi.devid = e->msi.devid;
- BUG_ON(!vgic_initialized(kvm));
+ if (!vgic_has_its(kvm))
+ return -ENODEV;
- return kvm_vgic_inject_irq(kvm, 0, spi, level);
+ return vgic_its_inject_msi(kvm, &msi);
}
-/* MSI not implemented yet */
-int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
- struct kvm *kvm, int irq_source_id,
- int level, bool line_status)
+int kvm_vgic_setup_default_irq_routing(struct kvm *kvm)
{
- return 0;
+ struct kvm_irq_routing_entry *entries;
+ struct vgic_dist *dist = &kvm->arch.vgic;
+ u32 nr = dist->nr_spis;
+ int i, ret;
+
+ entries = kcalloc(nr, sizeof(struct kvm_kernel_irq_routing_entry),
+ GFP_KERNEL);
+ if (!entries)
+ return -ENOMEM;
+
+ for (i = 0; i < nr; i++) {
+ entries[i].gsi = i;
+ entries[i].type = KVM_IRQ_ROUTING_IRQCHIP;
+ entries[i].u.irqchip.irqchip = 0;
+ entries[i].u.irqchip.pin = i;
+ }
+ ret = kvm_set_irq_routing(kvm, entries, nr, 0);
+ kfree(entries);
+ return ret;
}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 39f3358c6d91..e7aeac719e09 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -711,10 +711,3 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
return map_is_active;
}
-int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
-{
- if (vgic_has_its(kvm))
- return vgic_its_inject_msi(kvm, msi);
- else
- return -ENODEV;
-}
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index df99e9c3b64d..3bcc9990adf7 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -62,12 +62,14 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
{
struct kvm_kernel_irq_routing_entry route;
- if (!irqchip_in_kernel(kvm) || msi->flags != 0)
+ if (!irqchip_in_kernel(kvm) || (msi->flags & ~KVM_MSI_VALID_DEVID))
return -EINVAL;
route.msi.address_lo = msi->address_lo;
route.msi.address_hi = msi->address_hi;
route.msi.data = msi->data;
+ route.msi.flags = msi->flags;
+ route.msi.devid = msi->devid;
return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false);
}
@@ -177,6 +179,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
unsigned flags)
{
struct kvm_irq_routing_table *new, *old;
+ struct kvm_kernel_irq_routing_entry *e;
u32 i, j, nr_rt_entries = 0;
int r;
@@ -200,23 +203,25 @@ int kvm_set_irq_routing(struct kvm *kvm,
new->chip[i][j] = -1;
for (i = 0; i < nr; ++i) {
- struct kvm_kernel_irq_routing_entry *e;
-
r = -ENOMEM;
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
goto out;
r = -EINVAL;
- if (ue->flags) {
- kfree(e);
- goto out;
+ switch (ue->type) {
+ case KVM_IRQ_ROUTING_MSI:
+ if (ue->flags & ~KVM_MSI_VALID_DEVID)
+ goto free_entry;
+ break;
+ default:
+ if (ue->flags)
+ goto free_entry;
+ break;
}
r = setup_routing_entry(kvm, new, e, ue);
- if (r) {
- kfree(e);
- goto out;
- }
+ if (r)
+ goto free_entry;
++ue;
}
@@ -233,7 +238,10 @@ int kvm_set_irq_routing(struct kvm *kvm,
new = old;
r = 0;
+ goto out;
+free_entry:
+ kfree(e);
out:
free_irq_routing_table(new);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index cc081ccfcaa3..195078225aa5 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -696,6 +696,11 @@ static void kvm_destroy_devices(struct kvm *kvm)
{
struct kvm_device *dev, *tmp;
+ /*
+ * We do not need to take the kvm->lock here, because nobody else
+ * has a reference to the struct kvm at this point and therefore
+ * cannot access the devices list anyhow.
+ */
list_for_each_entry_safe(dev, tmp, &kvm->devices, vm_node) {
list_del(&dev->vm_node);
dev->ops->destroy(dev);
@@ -2832,19 +2837,28 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
dev->ops = ops;
dev->kvm = kvm;
+ mutex_lock(&kvm->lock);
ret = ops->create(dev, cd->type);
if (ret < 0) {
+ mutex_unlock(&kvm->lock);
kfree(dev);
return ret;
}
+ list_add(&dev->vm_node, &kvm->devices);
+ mutex_unlock(&kvm->lock);
+
+ if (ops->init)
+ ops->init(dev);
ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
if (ret < 0) {
ops->destroy(dev);
+ mutex_lock(&kvm->lock);
+ list_del(&dev->vm_node);
+ mutex_unlock(&kvm->lock);
return ret;
}
- list_add(&dev->vm_node, &kvm->devices);
kvm_get_kvm(kvm);
cd->fd = ret;
return 0;